linux/net/rxrpc/ar-connevent.c
<<
>>
Prefs
   1/* connection-level event handling
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/net.h>
  14#include <linux/skbuff.h>
  15#include <linux/errqueue.h>
  16#include <linux/udp.h>
  17#include <linux/in.h>
  18#include <linux/in6.h>
  19#include <linux/icmp.h>
  20#include <net/sock.h>
  21#include <net/af_rxrpc.h>
  22#include <net/ip.h>
  23#include "ar-internal.h"
  24
  25/*
  26 * pass a connection-level abort onto all calls on that connection
  27 */
  28static void rxrpc_abort_calls(struct rxrpc_connection *conn, int state,
  29                              u32 abort_code)
  30{
  31        struct rxrpc_call *call;
  32        struct rb_node *p;
  33
  34        _enter("{%d},%x", conn->debug_id, abort_code);
  35
  36        read_lock_bh(&conn->lock);
  37
  38        for (p = rb_first(&conn->calls); p; p = rb_next(p)) {
  39                call = rb_entry(p, struct rxrpc_call, conn_node);
  40                write_lock(&call->state_lock);
  41                if (call->state <= RXRPC_CALL_COMPLETE) {
  42                        call->state = state;
  43                        call->abort_code = abort_code;
  44                        if (state == RXRPC_CALL_LOCALLY_ABORTED)
  45                                set_bit(RXRPC_CALL_CONN_ABORT, &call->events);
  46                        else
  47                                set_bit(RXRPC_CALL_RCVD_ABORT, &call->events);
  48                        rxrpc_queue_call(call);
  49                }
  50                write_unlock(&call->state_lock);
  51        }
  52
  53        read_unlock_bh(&conn->lock);
  54        _leave("");
  55}
  56
  57/*
  58 * generate a connection-level abort
  59 */
  60static int rxrpc_abort_connection(struct rxrpc_connection *conn,
  61                                  u32 error, u32 abort_code)
  62{
  63        struct rxrpc_header hdr;
  64        struct msghdr msg;
  65        struct kvec iov[2];
  66        __be32 word;
  67        size_t len;
  68        int ret;
  69
  70        _enter("%d,,%u,%u", conn->debug_id, error, abort_code);
  71
  72        /* generate a connection-level abort */
  73        spin_lock_bh(&conn->state_lock);
  74        if (conn->state < RXRPC_CONN_REMOTELY_ABORTED) {
  75                conn->state = RXRPC_CONN_LOCALLY_ABORTED;
  76                conn->error = error;
  77                spin_unlock_bh(&conn->state_lock);
  78        } else {
  79                spin_unlock_bh(&conn->state_lock);
  80                _leave(" = 0 [already dead]");
  81                return 0;
  82        }
  83
  84        rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, abort_code);
  85
  86        msg.msg_name    = &conn->trans->peer->srx.transport.sin;
  87        msg.msg_namelen = sizeof(conn->trans->peer->srx.transport.sin);
  88        msg.msg_control = NULL;
  89        msg.msg_controllen = 0;
  90        msg.msg_flags   = 0;
  91
  92        hdr.epoch       = conn->epoch;
  93        hdr.cid         = conn->cid;
  94        hdr.callNumber  = 0;
  95        hdr.seq         = 0;
  96        hdr.type        = RXRPC_PACKET_TYPE_ABORT;
  97        hdr.flags       = conn->out_clientflag;
  98        hdr.userStatus  = 0;
  99        hdr.securityIndex = conn->security_ix;
 100        hdr._rsvd       = 0;
 101        hdr.serviceId   = conn->service_id;
 102
 103        word = htonl(abort_code);
 104
 105        iov[0].iov_base = &hdr;
 106        iov[0].iov_len  = sizeof(hdr);
 107        iov[1].iov_base = &word;
 108        iov[1].iov_len  = sizeof(word);
 109
 110        len = iov[0].iov_len + iov[1].iov_len;
 111
 112        hdr.serial = htonl(atomic_inc_return(&conn->serial));
 113        _proto("Tx CONN ABORT %%%u { %d }", ntohl(hdr.serial), abort_code);
 114
 115        ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 2, len);
 116        if (ret < 0) {
 117                _debug("sendmsg failed: %d", ret);
 118                return -EAGAIN;
 119        }
 120
 121        _leave(" = 0");
 122        return 0;
 123}
 124
 125/*
 126 * mark a call as being on a now-secured channel
 127 * - must be called with softirqs disabled
 128 */
 129static void rxrpc_call_is_secure(struct rxrpc_call *call)
 130{
 131        _enter("%p", call);
 132        if (call) {
 133                read_lock(&call->state_lock);
 134                if (call->state < RXRPC_CALL_COMPLETE &&
 135                    !test_and_set_bit(RXRPC_CALL_SECURED, &call->events))
 136                        rxrpc_queue_call(call);
 137                read_unlock(&call->state_lock);
 138        }
 139}
 140
 141/*
 142 * connection-level Rx packet processor
 143 */
 144static int rxrpc_process_event(struct rxrpc_connection *conn,
 145                               struct sk_buff *skb,
 146                               u32 *_abort_code)
 147{
 148        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 149        __be32 tmp;
 150        u32 serial;
 151        int loop, ret;
 152
 153        if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) {
 154                kleave(" = -ECONNABORTED [%u]", conn->state);
 155                return -ECONNABORTED;
 156        }
 157
 158        serial = ntohl(sp->hdr.serial);
 159
 160        _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, serial);
 161
 162        switch (sp->hdr.type) {
 163        case RXRPC_PACKET_TYPE_ABORT:
 164                if (skb_copy_bits(skb, 0, &tmp, sizeof(tmp)) < 0)
 165                        return -EPROTO;
 166                _proto("Rx ABORT %%%u { ac=%d }", serial, ntohl(tmp));
 167
 168                conn->state = RXRPC_CONN_REMOTELY_ABORTED;
 169                rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED,
 170                                  ntohl(tmp));
 171                return -ECONNABORTED;
 172
 173        case RXRPC_PACKET_TYPE_CHALLENGE:
 174                if (conn->security)
 175                        return conn->security->respond_to_challenge(
 176                                conn, skb, _abort_code);
 177                return -EPROTO;
 178
 179        case RXRPC_PACKET_TYPE_RESPONSE:
 180                if (!conn->security)
 181                        return -EPROTO;
 182
 183                ret = conn->security->verify_response(conn, skb, _abort_code);
 184                if (ret < 0)
 185                        return ret;
 186
 187                ret = conn->security->init_connection_security(conn);
 188                if (ret < 0)
 189                        return ret;
 190
 191                conn->security->prime_packet_security(conn);
 192                read_lock_bh(&conn->lock);
 193                spin_lock(&conn->state_lock);
 194
 195                if (conn->state == RXRPC_CONN_SERVER_CHALLENGING) {
 196                        conn->state = RXRPC_CONN_SERVER;
 197                        for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
 198                                rxrpc_call_is_secure(conn->channels[loop]);
 199                }
 200
 201                spin_unlock(&conn->state_lock);
 202                read_unlock_bh(&conn->lock);
 203                return 0;
 204
 205        default:
 206                _leave(" = -EPROTO [%u]", sp->hdr.type);
 207                return -EPROTO;
 208        }
 209}
 210
 211/*
 212 * set up security and issue a challenge
 213 */
 214static void rxrpc_secure_connection(struct rxrpc_connection *conn)
 215{
 216        u32 abort_code;
 217        int ret;
 218
 219        _enter("{%d}", conn->debug_id);
 220
 221        ASSERT(conn->security_ix != 0);
 222
 223        if (!conn->key) {
 224                _debug("set up security");
 225                ret = rxrpc_init_server_conn_security(conn);
 226                switch (ret) {
 227                case 0:
 228                        break;
 229                case -ENOENT:
 230                        abort_code = RX_CALL_DEAD;
 231                        goto abort;
 232                default:
 233                        abort_code = RXKADNOAUTH;
 234                        goto abort;
 235                }
 236        }
 237
 238        ASSERT(conn->security != NULL);
 239
 240        if (conn->security->issue_challenge(conn) < 0) {
 241                abort_code = RX_CALL_DEAD;
 242                ret = -ENOMEM;
 243                goto abort;
 244        }
 245
 246        _leave("");
 247        return;
 248
 249abort:
 250        _debug("abort %d, %d", ret, abort_code);
 251        rxrpc_abort_connection(conn, -ret, abort_code);
 252        _leave(" [aborted]");
 253}
 254
 255/*
 256 * connection-level event processor
 257 */
 258void rxrpc_process_connection(struct work_struct *work)
 259{
 260        struct rxrpc_connection *conn =
 261                container_of(work, struct rxrpc_connection, processor);
 262        struct sk_buff *skb;
 263        u32 abort_code = RX_PROTOCOL_ERROR;
 264        int ret;
 265
 266        _enter("{%d}", conn->debug_id);
 267
 268        atomic_inc(&conn->usage);
 269
 270        if (test_and_clear_bit(RXRPC_CONN_CHALLENGE, &conn->events)) {
 271                rxrpc_secure_connection(conn);
 272                rxrpc_put_connection(conn);
 273        }
 274
 275        /* go through the conn-level event packets, releasing the ref on this
 276         * connection that each one has when we've finished with it */
 277        while ((skb = skb_dequeue(&conn->rx_queue))) {
 278                ret = rxrpc_process_event(conn, skb, &abort_code);
 279                switch (ret) {
 280                case -EPROTO:
 281                case -EKEYEXPIRED:
 282                case -EKEYREJECTED:
 283                        goto protocol_error;
 284                case -EAGAIN:
 285                        goto requeue_and_leave;
 286                case -ECONNABORTED:
 287                default:
 288                        rxrpc_put_connection(conn);
 289                        rxrpc_free_skb(skb);
 290                        break;
 291                }
 292        }
 293
 294out:
 295        rxrpc_put_connection(conn);
 296        _leave("");
 297        return;
 298
 299requeue_and_leave:
 300        skb_queue_head(&conn->rx_queue, skb);
 301        goto out;
 302
 303protocol_error:
 304        if (rxrpc_abort_connection(conn, -ret, abort_code) < 0)
 305                goto requeue_and_leave;
 306        rxrpc_put_connection(conn);
 307        rxrpc_free_skb(skb);
 308        _leave(" [EPROTO]");
 309        goto out;
 310}
 311
 312/*
 313 * put a packet up for transport-level abort
 314 */
 315void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
 316{
 317        CHECK_SLAB_OKAY(&local->usage);
 318
 319        if (!atomic_inc_not_zero(&local->usage)) {
 320                printk("resurrected on reject\n");
 321                BUG();
 322        }
 323
 324        skb_queue_tail(&local->reject_queue, skb);
 325        rxrpc_queue_work(&local->rejecter);
 326}
 327
 328/*
 329 * reject packets through the local endpoint
 330 */
 331void rxrpc_reject_packets(struct work_struct *work)
 332{
 333        union {
 334                struct sockaddr sa;
 335                struct sockaddr_in sin;
 336        } sa;
 337        struct rxrpc_skb_priv *sp;
 338        struct rxrpc_header hdr;
 339        struct rxrpc_local *local;
 340        struct sk_buff *skb;
 341        struct msghdr msg;
 342        struct kvec iov[2];
 343        size_t size;
 344        __be32 code;
 345
 346        local = container_of(work, struct rxrpc_local, rejecter);
 347        rxrpc_get_local(local);
 348
 349        _enter("%d", local->debug_id);
 350
 351        iov[0].iov_base = &hdr;
 352        iov[0].iov_len = sizeof(hdr);
 353        iov[1].iov_base = &code;
 354        iov[1].iov_len = sizeof(code);
 355        size = sizeof(hdr) + sizeof(code);
 356
 357        msg.msg_name = &sa;
 358        msg.msg_control = NULL;
 359        msg.msg_controllen = 0;
 360        msg.msg_flags = 0;
 361
 362        memset(&sa, 0, sizeof(sa));
 363        sa.sa.sa_family = local->srx.transport.family;
 364        switch (sa.sa.sa_family) {
 365        case AF_INET:
 366                msg.msg_namelen = sizeof(sa.sin);
 367                break;
 368        default:
 369                msg.msg_namelen = 0;
 370                break;
 371        }
 372
 373        memset(&hdr, 0, sizeof(hdr));
 374        hdr.type = RXRPC_PACKET_TYPE_ABORT;
 375
 376        while ((skb = skb_dequeue(&local->reject_queue))) {
 377                sp = rxrpc_skb(skb);
 378                switch (sa.sa.sa_family) {
 379                case AF_INET:
 380                        sa.sin.sin_port = udp_hdr(skb)->source;
 381                        sa.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
 382                        code = htonl(skb->priority);
 383
 384                        hdr.epoch = sp->hdr.epoch;
 385                        hdr.cid = sp->hdr.cid;
 386                        hdr.callNumber = sp->hdr.callNumber;
 387                        hdr.serviceId = sp->hdr.serviceId;
 388                        hdr.flags = sp->hdr.flags;
 389                        hdr.flags ^= RXRPC_CLIENT_INITIATED;
 390                        hdr.flags &= RXRPC_CLIENT_INITIATED;
 391
 392                        kernel_sendmsg(local->socket, &msg, iov, 2, size);
 393                        break;
 394
 395                default:
 396                        break;
 397                }
 398
 399                rxrpc_free_skb(skb);
 400                rxrpc_put_local(local);
 401        }
 402
 403        rxrpc_put_local(local);
 404        _leave("");
 405}
 406
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.