rxrpc: Separate the connection's protocol service ID from the lookup ID
authorDavid Howells <dhowells@redhat.com>
Mon, 5 Jun 2017 13:30:49 +0000 (14:30 +0100)
committerDavid Howells <dhowells@redhat.com>
Mon, 5 Jun 2017 13:30:49 +0000 (14:30 +0100)
Keep the rxrpc_connection struct's idea of the service ID that is exposed
in the protocol separate from the service ID that's used as a lookup key.

This allows the protocol service ID on a client connection to get upgraded
without making the connection unfindable for other client calls that also
would like to use the upgraded connection.

The connection's actual service ID is then returned through recvmsg() by
way of msg_name.

Whilst we're at it, we get rid of the last_service_id field from each
channel.  The service ID is per-connection, not per-call and an entire
connection is upgraded in one go.

Signed-off-by: David Howells <dhowells@redhat.com>
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/conn_client.c
net/rxrpc/conn_event.c
net/rxrpc/conn_object.c
net/rxrpc/conn_service.c
net/rxrpc/proc.c
net/rxrpc/recvmsg.c
net/rxrpc/rxkad.c
net/rxrpc/security.c

index cd34ffbff1d10defd6c9fc52540fd3cc551c6c22..1e4ac889ec00d35cc94aae1165c518554f75565f 100644 (file)
@@ -131,9 +131,8 @@ static int rxrpc_validate_address(struct rxrpc_sock *rx,
 static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
 {
        struct sockaddr_rxrpc *srx = (struct sockaddr_rxrpc *)saddr;
-       struct sock *sk = sock->sk;
        struct rxrpc_local *local;
-       struct rxrpc_sock *rx = rxrpc_sk(sk);
+       struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
        u16 service_id = srx->srx_service;
        int ret;
 
@@ -152,7 +151,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
 
        memcpy(&rx->srx, srx, sizeof(rx->srx));
 
-       local = rxrpc_lookup_local(sock_net(sock->sk), &rx->srx);
+       local = rxrpc_lookup_local(sock_net(&rx->sk), &rx->srx);
        if (IS_ERR(local)) {
                ret = PTR_ERR(local);
                goto error_unlock;
index 067dbb3121d0b1f87170852551cec3eec785716b..de98a49adb359470dd926607f707117972f5186f 100644 (file)
@@ -386,7 +386,6 @@ struct rxrpc_connection {
                u32                     call_counter;   /* Call ID counter */
                u32                     last_call;      /* ID of last call */
                u8                      last_type;      /* Type of last packet */
-               u16                     last_service_id;
                union {
                        u32             last_seq;
                        u32             last_abort;
@@ -417,6 +416,7 @@ struct rxrpc_connection {
        atomic_t                serial;         /* packet serial number counter */
        unsigned int            hi_serial;      /* highest serial number received */
        u32                     security_nonce; /* response re-use preventer */
+       u16                     service_id;     /* Service ID, possibly upgraded */
        u8                      size_align;     /* data size alignment (for security) */
        u8                      security_size;  /* security header size */
        u8                      security_ix;    /* security type */
index c86f3202f96781909845c7dbc3e344409acec1bf..3f358bf424ad81586eb50f7f88fea5b5bc23bcf9 100644 (file)
@@ -188,6 +188,7 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
        conn->params            = *cp;
        conn->out_clientflag    = RXRPC_CLIENT_INITIATED;
        conn->state             = RXRPC_CONN_CLIENT;
+       conn->service_id        = cp->service_id;
 
        ret = rxrpc_get_client_connection_id(conn, gfp);
        if (ret < 0)
@@ -343,6 +344,7 @@ static int rxrpc_get_client_conn(struct rxrpc_call *call,
        if (cp->exclusive) {
                call->conn = candidate;
                call->security_ix = candidate->security_ix;
+               call->service_id = candidate->service_id;
                _leave(" = 0 [exclusive %d]", candidate->debug_id);
                return 0;
        }
@@ -392,6 +394,7 @@ candidate_published:
        set_bit(RXRPC_CONN_IN_CLIENT_CONNS, &candidate->flags);
        call->conn = candidate;
        call->security_ix = candidate->security_ix;
+       call->service_id = candidate->service_id;
        spin_unlock(&local->client_conns_lock);
        _leave(" = 0 [new %d]", candidate->debug_id);
        return 0;
@@ -413,6 +416,7 @@ found_extant_conn:
        spin_lock(&conn->channel_lock);
        call->conn = conn;
        call->security_ix = conn->security_ix;
+       call->service_id = conn->service_id;
        list_add(&call->chan_wait_link, &conn->waiting_calls);
        spin_unlock(&conn->channel_lock);
        _leave(" = 0 [extant %d]", conn->debug_id);
index 46babcf82ce8648190e018ee69ad16701e2e969a..59a51a56e7c88e78d69dfc0184ca1230ca797a2e 100644 (file)
@@ -74,7 +74,7 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
        pkt.whdr.userStatus     = 0;
        pkt.whdr.securityIndex  = conn->security_ix;
        pkt.whdr._rsvd          = 0;
-       pkt.whdr.serviceId      = htons(chan->last_service_id);
+       pkt.whdr.serviceId      = htons(conn->service_id);
 
        len = sizeof(pkt.whdr);
        switch (chan->last_type) {
@@ -208,7 +208,7 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
        whdr.userStatus = 0;
        whdr.securityIndex = conn->security_ix;
        whdr._rsvd      = 0;
-       whdr.serviceId  = htons(conn->params.service_id);
+       whdr.serviceId  = htons(conn->service_id);
 
        word            = htonl(conn->local_abort);
 
index ade4d3d0b2a7e24e6d3fd94acfb393de7a49822f..5bb255107427b2fe29cfa07be708e1b9ac822976 100644 (file)
@@ -167,7 +167,6 @@ void __rxrpc_disconnect_call(struct rxrpc_connection *conn,
                 * through the channel, whilst disposing of the actual call record.
                 */
                trace_rxrpc_disconnect_call(call);
-               chan->last_service_id = call->service_id;
                if (call->abort_code) {
                        chan->last_abort = call->abort_code;
                        chan->last_type = RXRPC_PACKET_TYPE_ABORT;
index edfc633f7d5e214d9e8fd8acec1d76ceeda9243c..c7f8682a55b2909c8e406ff91ca4de617a27dc60 100644 (file)
@@ -160,6 +160,7 @@ void rxrpc_new_incoming_connection(struct rxrpc_connection *conn,
        conn->proto.epoch       = sp->hdr.epoch;
        conn->proto.cid         = sp->hdr.cid & RXRPC_CIDMASK;
        conn->params.service_id = sp->hdr.serviceId;
+       conn->service_id        = sp->hdr.serviceId;
        conn->security_ix       = sp->hdr.securityIndex;
        conn->out_clientflag    = 0;
        if (conn->security_ix)
index e92d8405b15a707900823c1582da2b03ec487e4a..7421656963a91de1197ba13404826313dbc1d3f4 100644 (file)
@@ -190,7 +190,7 @@ print:
                   " %s %08x %08x %08x\n",
                   lbuff,
                   rbuff,
-                  conn->params.service_id,
+                  conn->service_id,
                   conn->proto.cid,
                   rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
                   atomic_read(&conn->usage),
index f9caf3b775097f62e8cb27fe12f3e925a3f8c323..bdece21f313de7d2a0d3bdf3dd1933c8d7a7d0b2 100644 (file)
@@ -522,8 +522,11 @@ try_again:
        }
 
        if (msg->msg_name) {
-               size_t len = sizeof(call->conn->params.peer->srx);
-               memcpy(msg->msg_name, &call->conn->params.peer->srx, len);
+               struct sockaddr_rxrpc *srx = msg->msg_name;
+               size_t len = sizeof(call->peer->srx);
+
+               memcpy(msg->msg_name, &call->peer->srx, len);
+               srx->srx_service = call->service_id;
                msg->msg_namelen = len;
        }
 
index 29fe20ad04aa8da8164362926aab9cb6b9339c82..46d1a1f0b55b1c620451db900c16b0ef5fc3c013 100644 (file)
@@ -649,7 +649,7 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
        whdr.userStatus = 0;
        whdr.securityIndex = conn->security_ix;
        whdr._rsvd      = 0;
-       whdr.serviceId  = htons(conn->params.service_id);
+       whdr.serviceId  = htons(conn->service_id);
 
        iov[0].iov_base = &whdr;
        iov[0].iov_len  = sizeof(whdr);
index 7d921e56e71544ee2886f93b00d30776992bcfe8..b9f5dbbe0b8b761284e96df9e8a45f80ede30c85 100644 (file)
@@ -121,7 +121,7 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
 
        _enter("");
 
-       sprintf(kdesc, "%u:%u", conn->params.service_id, conn->security_ix);
+       sprintf(kdesc, "%u:%u", conn->service_id, conn->security_ix);
 
        sec = rxrpc_security_lookup(conn->security_ix);
        if (!sec) {
@@ -133,7 +133,7 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
        read_lock(&local->services_lock);
        rx = rcu_dereference_protected(local->service,
                                       lockdep_is_held(&local->services_lock));
-       if (rx && rx->srx.srx_service == conn->params.service_id)
+       if (rx && rx->srx.srx_service == conn->service_id)
                goto found_service;
 
        /* the service appears to have died */