···6868 * packet6969 */7070struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local,7171- struct rxrpc_peer *peer,7271 struct sk_buff *skb)7372{7473 struct rxrpc_connection *conn;7474+ struct rxrpc_conn_proto k;7575 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);7676+ struct sockaddr_rxrpc srx;7777+ struct rxrpc_peer *peer;7678 struct rb_node *p;7777- u32 epoch, cid;78797980 _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags);80818181- read_lock_bh(&peer->conn_lock);8282+ if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)8383+ goto not_found;82848383- cid = sp->hdr.cid & RXRPC_CIDMASK;8484- epoch = sp->hdr.epoch;8585+ /* We may have to handle mixing IPv4 and IPv6 */8686+ if (srx.transport.family != local->srx.transport.family) {8787+ pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n",8888+ srx.transport.family,8989+ local->srx.transport.family);9090+ goto not_found;9191+ }9292+9393+ k.epoch = sp->hdr.epoch;9494+ k.cid = sp->hdr.cid & RXRPC_CIDMASK;85958696 if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) {9797+ /* We need to look up service connections by the full protocol9898+ * parameter set. We look up the peer first as an intermediate9999+ * step and then the connection from the peer's tree.100100+ */101101+ peer = rxrpc_lookup_peer_rcu(local, &srx);102102+ if (!peer)103103+ goto not_found;104104+105105+ read_lock_bh(&peer->conn_lock);106106+87107 p = peer->service_conns.rb_node;88108 while (p) {89109 conn = rb_entry(p, struct rxrpc_connection, service_node);9011091111 _debug("maybe %x", conn->proto.cid);921129393- if (epoch < conn->proto.epoch)113113+ if (k.epoch < conn->proto.epoch)94114 p = p->rb_left;9595- else if (epoch > conn->proto.epoch)115115+ else if (k.epoch > conn->proto.epoch)96116 p = p->rb_right;9797- else if (cid < conn->proto.cid)117117+ else if (k.cid < conn->proto.cid)98118 p = p->rb_left;9999- else if (cid > conn->proto.cid)119119+ else if (k.cid > conn->proto.cid)100120 p = p->rb_right;101121 else102102- goto found;122122+ goto found_service_conn;103123 }124124+ read_unlock_bh(&peer->conn_lock);104125 } else {105105- conn = idr_find(&rxrpc_client_conn_ids, cid >> RXRPC_CIDSHIFT);106106- if (conn &&107107- conn->proto.epoch == epoch &&108108- conn->params.peer == peer)109109- goto found;126126+ conn = idr_find(&rxrpc_client_conn_ids,127127+ k.cid >> RXRPC_CIDSHIFT);128128+ if (!conn ||129129+ conn->proto.epoch != k.epoch ||130130+ conn->params.local != local)131131+ goto not_found;132132+133133+ peer = conn->params.peer;134134+ switch (srx.transport.family) {135135+ case AF_INET:136136+ if (peer->srx.transport.sin.sin_port !=137137+ srx.transport.sin.sin_port ||138138+ peer->srx.transport.sin.sin_addr.s_addr !=139139+ srx.transport.sin.sin_addr.s_addr)140140+ goto not_found;141141+ break;142142+ default:143143+ BUG();144144+ }145145+146146+ conn = rxrpc_get_connection_maybe(conn);147147+ _leave(" = %p", conn);148148+ return conn;110149 }111150112112- read_unlock_bh(&peer->conn_lock);151151+not_found:113152 _leave(" = NULL");114153 return NULL;115154116116-found:155155+found_service_conn:117156 conn = rxrpc_get_connection_maybe(conn);118157 read_unlock_bh(&peer->conn_lock);119158 _leave(" = %p", conn);
+3-27
net/rxrpc/input.c
···626626 return 0;627627}628628629629-static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,630630- struct sk_buff *skb)631631-{632632- struct rxrpc_peer *peer;633633- struct rxrpc_connection *conn;634634- struct sockaddr_rxrpc srx;635635-636636- rxrpc_get_addr_from_skb(local, skb, &srx);637637- rcu_read_lock();638638- peer = rxrpc_lookup_peer_rcu(local, &srx);639639- if (!peer)640640- goto cant_find_peer;641641-642642- conn = rxrpc_find_connection(local, peer, skb);643643- rcu_read_unlock();644644- if (!conn)645645- goto cant_find_conn;646646-647647- return conn;648648-649649-cant_find_peer:650650- rcu_read_unlock();651651-cant_find_conn:652652- return NULL;653653-}654654-655629/*656630 * handle data received on the local endpoint657631 * - may be called in interrupt context···705731 * old-fashioned way doesn't really hurt */706732 struct rxrpc_connection *conn;707733708708- conn = rxrpc_conn_from_local(local, skb);734734+ rcu_read_lock();735735+ conn = rxrpc_find_connection(local, skb);736736+ rcu_read_unlock();709737 if (!conn)710738 goto cant_route_call;711739
-27
net/rxrpc/utils.c
···1515#include "ar-internal.h"16161717/*1818- * Set up an RxRPC address from a socket buffer.1919- */2020-void rxrpc_get_addr_from_skb(struct rxrpc_local *local,2121- const struct sk_buff *skb,2222- struct sockaddr_rxrpc *srx)2323-{2424- memset(srx, 0, sizeof(*srx));2525- srx->transport_type = local->srx.transport_type;2626- srx->transport.family = local->srx.transport.family;2727-2828- /* Can we see an ipv4 UDP packet on an ipv6 UDP socket? and vice2929- * versa?3030- */3131- switch (srx->transport.family) {3232- case AF_INET:3333- srx->transport.sin.sin_port = udp_hdr(skb)->source;3434- srx->transport_len = sizeof(struct sockaddr_in);3535- memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr,3636- sizeof(struct in_addr));3737- break;3838-3939- default:4040- BUG();4141- }4242-}4343-4444-/*4518 * Fill out a peer address from a socket buffer containing a packet.4619 */4720int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb)