linux/net/802/mrp.c
<<
>>
Prefs
   1/*
   2 *      IEEE 802.1Q Multiple Registration Protocol (MRP)
   3 *
   4 *      Copyright (c) 2012 Massachusetts Institute of Technology
   5 *
   6 *      Adapted from code in net/802/garp.c
   7 *      Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
   8 *
   9 *      This program is free software; you can redistribute it and/or
  10 *      modify it under the terms of the GNU General Public License
  11 *      version 2 as published by the Free Software Foundation.
  12 */
  13#include <linux/kernel.h>
  14#include <linux/timer.h>
  15#include <linux/skbuff.h>
  16#include <linux/netdevice.h>
  17#include <linux/etherdevice.h>
  18#include <linux/rtnetlink.h>
  19#include <linux/slab.h>
  20#include <linux/module.h>
  21#include <net/mrp.h>
  22#include <asm/unaligned.h>
  23
  24static unsigned int mrp_join_time __read_mostly = 200;
  25module_param(mrp_join_time, uint, 0644);
  26MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)");
  27
  28static unsigned int mrp_periodic_time __read_mostly = 1000;
  29module_param(mrp_periodic_time, uint, 0644);
  30MODULE_PARM_DESC(mrp_periodic_time, "Periodic time in ms (default 1s)");
  31
  32MODULE_LICENSE("GPL");
  33
  34static const u8
  35mrp_applicant_state_table[MRP_APPLICANT_MAX + 1][MRP_EVENT_MAX + 1] = {
  36        [MRP_APPLICANT_VO] = {
  37                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
  38                [MRP_EVENT_JOIN]        = MRP_APPLICANT_VP,
  39                [MRP_EVENT_LV]          = MRP_APPLICANT_VO,
  40                [MRP_EVENT_TX]          = MRP_APPLICANT_VO,
  41                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_VO,
  42                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_AO,
  43                [MRP_EVENT_R_IN]        = MRP_APPLICANT_VO,
  44                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_VO,
  45                [MRP_EVENT_R_MT]        = MRP_APPLICANT_VO,
  46                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VO,
  47                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VO,
  48                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VO,
  49                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_VO,
  50        },
  51        [MRP_APPLICANT_VP] = {
  52                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
  53                [MRP_EVENT_JOIN]        = MRP_APPLICANT_VP,
  54                [MRP_EVENT_LV]          = MRP_APPLICANT_VO,
  55                [MRP_EVENT_TX]          = MRP_APPLICANT_AA,
  56                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_VP,
  57                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_AP,
  58                [MRP_EVENT_R_IN]        = MRP_APPLICANT_VP,
  59                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_VP,
  60                [MRP_EVENT_R_MT]        = MRP_APPLICANT_VP,
  61                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VP,
  62                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VP,
  63                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VP,
  64                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_VP,
  65        },
  66        [MRP_APPLICANT_VN] = {
  67                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
  68                [MRP_EVENT_JOIN]        = MRP_APPLICANT_VN,
  69                [MRP_EVENT_LV]          = MRP_APPLICANT_LA,
  70                [MRP_EVENT_TX]          = MRP_APPLICANT_AN,
  71                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_VN,
  72                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_VN,
  73                [MRP_EVENT_R_IN]        = MRP_APPLICANT_VN,
  74                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_VN,
  75                [MRP_EVENT_R_MT]        = MRP_APPLICANT_VN,
  76                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VN,
  77                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VN,
  78                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VN,
  79                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_VN,
  80        },
  81        [MRP_APPLICANT_AN] = {
  82                [MRP_EVENT_NEW]         = MRP_APPLICANT_AN,
  83                [MRP_EVENT_JOIN]        = MRP_APPLICANT_AN,
  84                [MRP_EVENT_LV]          = MRP_APPLICANT_LA,
  85                [MRP_EVENT_TX]          = MRP_APPLICANT_QA,
  86                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_AN,
  87                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_AN,
  88                [MRP_EVENT_R_IN]        = MRP_APPLICANT_AN,
  89                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AN,
  90                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AN,
  91                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VN,
  92                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VN,
  93                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VN,
  94                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_AN,
  95        },
  96        [MRP_APPLICANT_AA] = {
  97                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
  98                [MRP_EVENT_JOIN]        = MRP_APPLICANT_AA,
  99                [MRP_EVENT_LV]          = MRP_APPLICANT_LA,
 100                [MRP_EVENT_TX]          = MRP_APPLICANT_QA,
 101                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_AA,
 102                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_QA,
 103                [MRP_EVENT_R_IN]        = MRP_APPLICANT_AA,
 104                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AA,
 105                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AA,
 106                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VP,
 107                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VP,
 108                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VP,
 109                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_AA,
 110        },
 111        [MRP_APPLICANT_QA] = {
 112                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
 113                [MRP_EVENT_JOIN]        = MRP_APPLICANT_QA,
 114                [MRP_EVENT_LV]          = MRP_APPLICANT_LA,
 115                [MRP_EVENT_TX]          = MRP_APPLICANT_QA,
 116                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_QA,
 117                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_QA,
 118                [MRP_EVENT_R_IN]        = MRP_APPLICANT_QA,
 119                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AA,
 120                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AA,
 121                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VP,
 122                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VP,
 123                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VP,
 124                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_AA,
 125        },
 126        [MRP_APPLICANT_LA] = {
 127                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
 128                [MRP_EVENT_JOIN]        = MRP_APPLICANT_AA,
 129                [MRP_EVENT_LV]          = MRP_APPLICANT_LA,
 130                [MRP_EVENT_TX]          = MRP_APPLICANT_VO,
 131                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_LA,
 132                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_LA,
 133                [MRP_EVENT_R_IN]        = MRP_APPLICANT_LA,
 134                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_LA,
 135                [MRP_EVENT_R_MT]        = MRP_APPLICANT_LA,
 136                [MRP_EVENT_R_LV]        = MRP_APPLICANT_LA,
 137                [MRP_EVENT_R_LA]        = MRP_APPLICANT_LA,
 138                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_LA,
 139                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_LA,
 140        },
 141        [MRP_APPLICANT_AO] = {
 142                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
 143                [MRP_EVENT_JOIN]        = MRP_APPLICANT_AP,
 144                [MRP_EVENT_LV]          = MRP_APPLICANT_AO,
 145                [MRP_EVENT_TX]          = MRP_APPLICANT_AO,
 146                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_AO,
 147                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_QO,
 148                [MRP_EVENT_R_IN]        = MRP_APPLICANT_AO,
 149                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AO,
 150                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AO,
 151                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VO,
 152                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VO,
 153                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VO,
 154                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_AO,
 155        },
 156        [MRP_APPLICANT_QO] = {
 157                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
 158                [MRP_EVENT_JOIN]        = MRP_APPLICANT_QP,
 159                [MRP_EVENT_LV]          = MRP_APPLICANT_QO,
 160                [MRP_EVENT_TX]          = MRP_APPLICANT_QO,
 161                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_QO,
 162                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_QO,
 163                [MRP_EVENT_R_IN]        = MRP_APPLICANT_QO,
 164                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AO,
 165                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AO,
 166                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VO,
 167                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VO,
 168                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VO,
 169                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_QO,
 170        },
 171        [MRP_APPLICANT_AP] = {
 172                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
 173                [MRP_EVENT_JOIN]        = MRP_APPLICANT_AP,
 174                [MRP_EVENT_LV]          = MRP_APPLICANT_AO,
 175                [MRP_EVENT_TX]          = MRP_APPLICANT_QA,
 176                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_AP,
 177                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_QP,
 178                [MRP_EVENT_R_IN]        = MRP_APPLICANT_AP,
 179                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AP,
 180                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AP,
 181                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VP,
 182                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VP,
 183                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VP,
 184                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_AP,
 185        },
 186        [MRP_APPLICANT_QP] = {
 187                [MRP_EVENT_NEW]         = MRP_APPLICANT_VN,
 188                [MRP_EVENT_JOIN]        = MRP_APPLICANT_QP,
 189                [MRP_EVENT_LV]          = MRP_APPLICANT_QO,
 190                [MRP_EVENT_TX]          = MRP_APPLICANT_QP,
 191                [MRP_EVENT_R_NEW]       = MRP_APPLICANT_QP,
 192                [MRP_EVENT_R_JOIN_IN]   = MRP_APPLICANT_QP,
 193                [MRP_EVENT_R_IN]        = MRP_APPLICANT_QP,
 194                [MRP_EVENT_R_JOIN_MT]   = MRP_APPLICANT_AP,
 195                [MRP_EVENT_R_MT]        = MRP_APPLICANT_AP,
 196                [MRP_EVENT_R_LV]        = MRP_APPLICANT_VP,
 197                [MRP_EVENT_R_LA]        = MRP_APPLICANT_VP,
 198                [MRP_EVENT_REDECLARE]   = MRP_APPLICANT_VP,
 199                [MRP_EVENT_PERIODIC]    = MRP_APPLICANT_AP,
 200        },
 201};
 202
 203static const u8
 204mrp_tx_action_table[MRP_APPLICANT_MAX + 1] = {
 205        [MRP_APPLICANT_VO] = MRP_TX_ACTION_S_IN_OPTIONAL,
 206        [MRP_APPLICANT_VP] = MRP_TX_ACTION_S_JOIN_IN,
 207        [MRP_APPLICANT_VN] = MRP_TX_ACTION_S_NEW,
 208        [MRP_APPLICANT_AN] = MRP_TX_ACTION_S_NEW,
 209        [MRP_APPLICANT_AA] = MRP_TX_ACTION_S_JOIN_IN,
 210        [MRP_APPLICANT_QA] = MRP_TX_ACTION_S_JOIN_IN_OPTIONAL,
 211        [MRP_APPLICANT_LA] = MRP_TX_ACTION_S_LV,
 212        [MRP_APPLICANT_AO] = MRP_TX_ACTION_S_IN_OPTIONAL,
 213        [MRP_APPLICANT_QO] = MRP_TX_ACTION_S_IN_OPTIONAL,
 214        [MRP_APPLICANT_AP] = MRP_TX_ACTION_S_JOIN_IN,
 215        [MRP_APPLICANT_QP] = MRP_TX_ACTION_S_IN_OPTIONAL,
 216};
 217
 218static void mrp_attrvalue_inc(void *value, u8 len)
 219{
 220        u8 *v = (u8 *)value;
 221
 222        /* Add 1 to the last byte. If it becomes zero,
 223         * go to the previous byte and repeat.
 224         */
 225        while (len > 0 && !++v[--len])
 226                ;
 227}
 228
 229static int mrp_attr_cmp(const struct mrp_attr *attr,
 230                         const void *value, u8 len, u8 type)
 231{
 232        if (attr->type != type)
 233                return attr->type - type;
 234        if (attr->len != len)
 235                return attr->len - len;
 236        return memcmp(attr->value, value, len);
 237}
 238
 239static struct mrp_attr *mrp_attr_lookup(const struct mrp_applicant *app,
 240                                        const void *value, u8 len, u8 type)
 241{
 242        struct rb_node *parent = app->mad.rb_node;
 243        struct mrp_attr *attr;
 244        int d;
 245
 246        while (parent) {
 247                attr = rb_entry(parent, struct mrp_attr, node);
 248                d = mrp_attr_cmp(attr, value, len, type);
 249                if (d > 0)
 250                        parent = parent->rb_left;
 251                else if (d < 0)
 252                        parent = parent->rb_right;
 253                else
 254                        return attr;
 255        }
 256        return NULL;
 257}
 258
 259static struct mrp_attr *mrp_attr_create(struct mrp_applicant *app,
 260                                        const void *value, u8 len, u8 type)
 261{
 262        struct rb_node *parent = NULL, **p = &app->mad.rb_node;
 263        struct mrp_attr *attr;
 264        int d;
 265
 266        while (*p) {
 267                parent = *p;
 268                attr = rb_entry(parent, struct mrp_attr, node);
 269                d = mrp_attr_cmp(attr, value, len, type);
 270                if (d > 0)
 271                        p = &parent->rb_left;
 272                else if (d < 0)
 273                        p = &parent->rb_right;
 274                else {
 275                        /* The attribute already exists; re-use it. */
 276                        return attr;
 277                }
 278        }
 279        attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
 280        if (!attr)
 281                return attr;
 282        attr->state = MRP_APPLICANT_VO;
 283        attr->type  = type;
 284        attr->len   = len;
 285        memcpy(attr->value, value, len);
 286
 287        rb_link_node(&attr->node, parent, p);
 288        rb_insert_color(&attr->node, &app->mad);
 289        return attr;
 290}
 291
 292static void mrp_attr_destroy(struct mrp_applicant *app, struct mrp_attr *attr)
 293{
 294        rb_erase(&attr->node, &app->mad);
 295        kfree(attr);
 296}
 297
 298static int mrp_pdu_init(struct mrp_applicant *app)
 299{
 300        struct sk_buff *skb;
 301        struct mrp_pdu_hdr *ph;
 302
 303        skb = alloc_skb(app->dev->mtu + LL_RESERVED_SPACE(app->dev),
 304                        GFP_ATOMIC);
 305        if (!skb)
 306                return -ENOMEM;
 307
 308        skb->dev = app->dev;
 309        skb->protocol = app->app->pkttype.type;
 310        skb_reserve(skb, LL_RESERVED_SPACE(app->dev));
 311        skb_reset_network_header(skb);
 312        skb_reset_transport_header(skb);
 313
 314        ph = (struct mrp_pdu_hdr *)__skb_put(skb, sizeof(*ph));
 315        ph->version = app->app->version;
 316
 317        app->pdu = skb;
 318        return 0;
 319}
 320
 321static int mrp_pdu_append_end_mark(struct mrp_applicant *app)
 322{
 323        __be16 *endmark;
 324
 325        if (skb_tailroom(app->pdu) < sizeof(*endmark))
 326                return -1;
 327        endmark = (__be16 *)__skb_put(app->pdu, sizeof(*endmark));
 328        put_unaligned(MRP_END_MARK, endmark);
 329        return 0;
 330}
 331
 332static void mrp_pdu_queue(struct mrp_applicant *app)
 333{
 334        if (!app->pdu)
 335                return;
 336
 337        if (mrp_cb(app->pdu)->mh)
 338                mrp_pdu_append_end_mark(app);
 339        mrp_pdu_append_end_mark(app);
 340
 341        dev_hard_header(app->pdu, app->dev, ntohs(app->app->pkttype.type),
 342                        app->app->group_address, app->dev->dev_addr,
 343                        app->pdu->len);
 344
 345        skb_queue_tail(&app->queue, app->pdu);
 346        app->pdu = NULL;
 347}
 348
 349static void mrp_queue_xmit(struct mrp_applicant *app)
 350{
 351        struct sk_buff *skb;
 352
 353        while ((skb = skb_dequeue(&app->queue)))
 354                dev_queue_xmit(skb);
 355}
 356
 357static int mrp_pdu_append_msg_hdr(struct mrp_applicant *app,
 358                                  u8 attrtype, u8 attrlen)
 359{
 360        struct mrp_msg_hdr *mh;
 361
 362        if (mrp_cb(app->pdu)->mh) {
 363                if (mrp_pdu_append_end_mark(app) < 0)
 364                        return -1;
 365                mrp_cb(app->pdu)->mh = NULL;
 366                mrp_cb(app->pdu)->vah = NULL;
 367        }
 368
 369        if (skb_tailroom(app->pdu) < sizeof(*mh))
 370                return -1;
 371        mh = (struct mrp_msg_hdr *)__skb_put(app->pdu, sizeof(*mh));
 372        mh->attrtype = attrtype;
 373        mh->attrlen = attrlen;
 374        mrp_cb(app->pdu)->mh = mh;
 375        return 0;
 376}
 377
 378static int mrp_pdu_append_vecattr_hdr(struct mrp_applicant *app,
 379                                      const void *firstattrvalue, u8 attrlen)
 380{
 381        struct mrp_vecattr_hdr *vah;
 382
 383        if (skb_tailroom(app->pdu) < sizeof(*vah) + attrlen)
 384                return -1;
 385        vah = (struct mrp_vecattr_hdr *)__skb_put(app->pdu,
 386                                                  sizeof(*vah) + attrlen);
 387        put_unaligned(0, &vah->lenflags);
 388        memcpy(vah->firstattrvalue, firstattrvalue, attrlen);
 389        mrp_cb(app->pdu)->vah = vah;
 390        memcpy(mrp_cb(app->pdu)->attrvalue, firstattrvalue, attrlen);
 391        return 0;
 392}
 393
 394static int mrp_pdu_append_vecattr_event(struct mrp_applicant *app,
 395                                        const struct mrp_attr *attr,
 396                                        enum mrp_vecattr_event vaevent)
 397{
 398        u16 len, pos;
 399        u8 *vaevents;
 400        int err;
 401again:
 402        if (!app->pdu) {
 403                err = mrp_pdu_init(app);
 404                if (err < 0)
 405                        return err;
 406        }
 407
 408        /* If there is no Message header in the PDU, or the Message header is
 409         * for a different attribute type, add an EndMark (if necessary) and a
 410         * new Message header to the PDU.
 411         */
 412        if (!mrp_cb(app->pdu)->mh ||
 413            mrp_cb(app->pdu)->mh->attrtype != attr->type ||
 414            mrp_cb(app->pdu)->mh->attrlen != attr->len) {
 415                if (mrp_pdu_append_msg_hdr(app, attr->type, attr->len) < 0)
 416                        goto queue;
 417        }
 418
 419        /* If there is no VectorAttribute header for this Message in the PDU,
 420         * or this attribute's value does not sequentially follow the previous
 421         * attribute's value, add a new VectorAttribute header to the PDU.
 422         */
 423        if (!mrp_cb(app->pdu)->vah ||
 424            memcmp(mrp_cb(app->pdu)->attrvalue, attr->value, attr->len)) {
 425                if (mrp_pdu_append_vecattr_hdr(app, attr->value, attr->len) < 0)
 426                        goto queue;
 427        }
 428
 429        len = be16_to_cpu(get_unaligned(&mrp_cb(app->pdu)->vah->lenflags));
 430        pos = len % 3;
 431
 432        /* Events are packed into Vectors in the PDU, three to a byte. Add a
 433         * byte to the end of the Vector if necessary.
 434         */
 435        if (!pos) {
 436                if (skb_tailroom(app->pdu) < sizeof(u8))
 437                        goto queue;
 438                vaevents = (u8 *)__skb_put(app->pdu, sizeof(u8));
 439        } else {
 440                vaevents = (u8 *)(skb_tail_pointer(app->pdu) - sizeof(u8));
 441        }
 442
 443        switch (pos) {
 444        case 0:
 445                *vaevents = vaevent * (__MRP_VECATTR_EVENT_MAX *
 446                                       __MRP_VECATTR_EVENT_MAX);
 447                break;
 448        case 1:
 449                *vaevents += vaevent * __MRP_VECATTR_EVENT_MAX;
 450                break;
 451        case 2:
 452                *vaevents += vaevent;
 453                break;
 454        default:
 455                WARN_ON(1);
 456        }
 457
 458        /* Increment the length of the VectorAttribute in the PDU, as well as
 459         * the value of the next attribute that would continue its Vector.
 460         */
 461        put_unaligned(cpu_to_be16(++len), &mrp_cb(app->pdu)->vah->lenflags);
 462        mrp_attrvalue_inc(mrp_cb(app->pdu)->attrvalue, attr->len);
 463
 464        return 0;
 465
 466queue:
 467        mrp_pdu_queue(app);
 468        goto again;
 469}
 470
 471static void mrp_attr_event(struct mrp_applicant *app,
 472                           struct mrp_attr *attr, enum mrp_event event)
 473{
 474        enum mrp_applicant_state state;
 475
 476        state = mrp_applicant_state_table[attr->state][event];
 477        if (state == MRP_APPLICANT_INVALID) {
 478                WARN_ON(1);
 479                return;
 480        }
 481
 482        if (event == MRP_EVENT_TX) {
 483                /* When appending the attribute fails, don't update its state
 484                 * in order to retry at the next TX event.
 485                 */
 486
 487                switch (mrp_tx_action_table[attr->state]) {
 488                case MRP_TX_ACTION_NONE:
 489                case MRP_TX_ACTION_S_JOIN_IN_OPTIONAL:
 490                case MRP_TX_ACTION_S_IN_OPTIONAL:
 491                        break;
 492                case MRP_TX_ACTION_S_NEW:
 493                        if (mrp_pdu_append_vecattr_event(
 494                                    app, attr, MRP_VECATTR_EVENT_NEW) < 0)
 495                                return;
 496                        break;
 497                case MRP_TX_ACTION_S_JOIN_IN:
 498                        if (mrp_pdu_append_vecattr_event(
 499                                    app, attr, MRP_VECATTR_EVENT_JOIN_IN) < 0)
 500                                return;
 501                        break;
 502                case MRP_TX_ACTION_S_LV:
 503                        if (mrp_pdu_append_vecattr_event(
 504                                    app, attr, MRP_VECATTR_EVENT_LV) < 0)
 505                                return;
 506                        /* As a pure applicant, sending a leave message
 507                         * implies that the attribute was unregistered and
 508                         * can be destroyed.
 509                         */
 510                        mrp_attr_destroy(app, attr);
 511                        return;
 512                default:
 513                        WARN_ON(1);
 514                }
 515        }
 516
 517        attr->state = state;
 518}
 519
 520int mrp_request_join(const struct net_device *dev,
 521                     const struct mrp_application *appl,
 522                     const void *value, u8 len, u8 type)
 523{
 524        struct mrp_port *port = rtnl_dereference(dev->mrp_port);
 525        struct mrp_applicant *app = rtnl_dereference(
 526                port->applicants[appl->type]);
 527        struct mrp_attr *attr;
 528
 529        if (sizeof(struct mrp_skb_cb) + len >
 530            FIELD_SIZEOF(struct sk_buff, cb))
 531                return -ENOMEM;
 532
 533        spin_lock_bh(&app->lock);
 534        attr = mrp_attr_create(app, value, len, type);
 535        if (!attr) {
 536                spin_unlock_bh(&app->lock);
 537                return -ENOMEM;
 538        }
 539        mrp_attr_event(app, attr, MRP_EVENT_JOIN);
 540        spin_unlock_bh(&app->lock);
 541        return 0;
 542}
 543EXPORT_SYMBOL_GPL(mrp_request_join);
 544
 545void mrp_request_leave(const struct net_device *dev,
 546                       const struct mrp_application *appl,
 547                       const void *value, u8 len, u8 type)
 548{
 549        struct mrp_port *port = rtnl_dereference(dev->mrp_port);
 550        struct mrp_applicant *app = rtnl_dereference(
 551                port->applicants[appl->type]);
 552        struct mrp_attr *attr;
 553
 554        if (sizeof(struct mrp_skb_cb) + len >
 555            FIELD_SIZEOF(struct sk_buff, cb))
 556                return;
 557
 558        spin_lock_bh(&app->lock);
 559        attr = mrp_attr_lookup(app, value, len, type);
 560        if (!attr) {
 561                spin_unlock_bh(&app->lock);
 562                return;
 563        }
 564        mrp_attr_event(app, attr, MRP_EVENT_LV);
 565        spin_unlock_bh(&app->lock);
 566}
 567EXPORT_SYMBOL_GPL(mrp_request_leave);
 568
 569static void mrp_mad_event(struct mrp_applicant *app, enum mrp_event event)
 570{
 571        struct rb_node *node, *next;
 572        struct mrp_attr *attr;
 573
 574        for (node = rb_first(&app->mad);
 575             next = node ? rb_next(node) : NULL, node != NULL;
 576             node = next) {
 577                attr = rb_entry(node, struct mrp_attr, node);
 578                mrp_attr_event(app, attr, event);
 579        }
 580}
 581
 582static void mrp_join_timer_arm(struct mrp_applicant *app)
 583{
 584        unsigned long delay;
 585
 586        delay = (u64)msecs_to_jiffies(mrp_join_time) * prandom_u32() >> 32;
 587        mod_timer(&app->join_timer, jiffies + delay);
 588}
 589
 590static void mrp_join_timer(unsigned long data)
 591{
 592        struct mrp_applicant *app = (struct mrp_applicant *)data;
 593
 594        spin_lock(&app->lock);
 595        mrp_mad_event(app, MRP_EVENT_TX);
 596        mrp_pdu_queue(app);
 597        spin_unlock(&app->lock);
 598
 599        mrp_queue_xmit(app);
 600        mrp_join_timer_arm(app);
 601}
 602
 603static void mrp_periodic_timer_arm(struct mrp_applicant *app)
 604{
 605        mod_timer(&app->periodic_timer,
 606                  jiffies + msecs_to_jiffies(mrp_periodic_time));
 607}
 608
 609static void mrp_periodic_timer(unsigned long data)
 610{
 611        struct mrp_applicant *app = (struct mrp_applicant *)data;
 612
 613        spin_lock(&app->lock);
 614        mrp_mad_event(app, MRP_EVENT_PERIODIC);
 615        mrp_pdu_queue(app);
 616        spin_unlock(&app->lock);
 617
 618        mrp_periodic_timer_arm(app);
 619}
 620
 621static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset)
 622{
 623        __be16 endmark;
 624
 625        if (skb_copy_bits(skb, *offset, &endmark, sizeof(endmark)) < 0)
 626                return -1;
 627        if (endmark == MRP_END_MARK) {
 628                *offset += sizeof(endmark);
 629                return -1;
 630        }
 631        return 0;
 632}
 633
 634static void mrp_pdu_parse_vecattr_event(struct mrp_applicant *app,
 635                                        struct sk_buff *skb,
 636                                        enum mrp_vecattr_event vaevent)
 637{
 638        struct mrp_attr *attr;
 639        enum mrp_event event;
 640
 641        attr = mrp_attr_lookup(app, mrp_cb(skb)->attrvalue,
 642                               mrp_cb(skb)->mh->attrlen,
 643                               mrp_cb(skb)->mh->attrtype);
 644        if (attr == NULL)
 645                return;
 646
 647        switch (vaevent) {
 648        case MRP_VECATTR_EVENT_NEW:
 649                event = MRP_EVENT_R_NEW;
 650                break;
 651        case MRP_VECATTR_EVENT_JOIN_IN:
 652                event = MRP_EVENT_R_JOIN_IN;
 653                break;
 654        case MRP_VECATTR_EVENT_IN:
 655                event = MRP_EVENT_R_IN;
 656                break;
 657        case MRP_VECATTR_EVENT_JOIN_MT:
 658                event = MRP_EVENT_R_JOIN_MT;
 659                break;
 660        case MRP_VECATTR_EVENT_MT:
 661                event = MRP_EVENT_R_MT;
 662                break;
 663        case MRP_VECATTR_EVENT_LV:
 664                event = MRP_EVENT_R_LV;
 665                break;
 666        default:
 667                return;
 668        }
 669
 670        mrp_attr_event(app, attr, event);
 671}
 672
 673static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
 674                                 struct sk_buff *skb, int *offset)
 675{
 676        struct mrp_vecattr_hdr _vah;
 677        u16 valen;
 678        u8 vaevents, vaevent;
 679
 680        mrp_cb(skb)->vah = skb_header_pointer(skb, *offset, sizeof(_vah),
 681                                              &_vah);
 682        if (!mrp_cb(skb)->vah)
 683                return -1;
 684        *offset += sizeof(_vah);
 685
 686        if (get_unaligned(&mrp_cb(skb)->vah->lenflags) &
 687            MRP_VECATTR_HDR_FLAG_LA)
 688                mrp_mad_event(app, MRP_EVENT_R_LA);
 689        valen = be16_to_cpu(get_unaligned(&mrp_cb(skb)->vah->lenflags) &
 690                            MRP_VECATTR_HDR_LEN_MASK);
 691
 692        /* The VectorAttribute structure in a PDU carries event information
 693         * about one or more attributes having consecutive values. Only the
 694         * value for the first attribute is contained in the structure. So
 695         * we make a copy of that value, and then increment it each time we
 696         * advance to the next event in its Vector.
 697         */
 698        if (sizeof(struct mrp_skb_cb) + mrp_cb(skb)->mh->attrlen >
 699            FIELD_SIZEOF(struct sk_buff, cb))
 700                return -1;
 701        if (skb_copy_bits(skb, *offset, mrp_cb(skb)->attrvalue,
 702                          mrp_cb(skb)->mh->attrlen) < 0)
 703                return -1;
 704        *offset += mrp_cb(skb)->mh->attrlen;
 705
 706        /* In a VectorAttribute, the Vector contains events which are packed
 707         * three to a byte. We process one byte of the Vector at a time.
 708         */
 709        while (valen > 0) {
 710                if (skb_copy_bits(skb, *offset, &vaevents,
 711                                  sizeof(vaevents)) < 0)
 712                        return -1;
 713                *offset += sizeof(vaevents);
 714
 715                /* Extract and process the first event. */
 716                vaevent = vaevents / (__MRP_VECATTR_EVENT_MAX *
 717                                      __MRP_VECATTR_EVENT_MAX);
 718                if (vaevent >= __MRP_VECATTR_EVENT_MAX) {
 719                        /* The byte is malformed; stop processing. */
 720                        return -1;
 721                }
 722                mrp_pdu_parse_vecattr_event(app, skb, vaevent);
 723
 724                /* If present, extract and process the second event. */
 725                if (!--valen)
 726                        break;
 727                mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
 728                                  mrp_cb(skb)->mh->attrlen);
 729                vaevents %= (__MRP_VECATTR_EVENT_MAX *
 730                             __MRP_VECATTR_EVENT_MAX);
 731                vaevent = vaevents / __MRP_VECATTR_EVENT_MAX;
 732                mrp_pdu_parse_vecattr_event(app, skb, vaevent);
 733
 734                /* If present, extract and process the third event. */
 735                if (!--valen)
 736                        break;
 737                mrp_attrvalue_inc(mrp_cb(skb)->attrvalue,
 738                                  mrp_cb(skb)->mh->attrlen);
 739                vaevents %= __MRP_VECATTR_EVENT_MAX;
 740                vaevent = vaevents;
 741                mrp_pdu_parse_vecattr_event(app, skb, vaevent);
 742        }
 743        return 0;
 744}
 745
 746static int mrp_pdu_parse_msg(struct mrp_applicant *app, struct sk_buff *skb,
 747                             int *offset)
 748{
 749        struct mrp_msg_hdr _mh;
 750
 751        mrp_cb(skb)->mh = skb_header_pointer(skb, *offset, sizeof(_mh), &_mh);
 752        if (!mrp_cb(skb)->mh)
 753                return -1;
 754        *offset += sizeof(_mh);
 755
 756        if (mrp_cb(skb)->mh->attrtype == 0 ||
 757            mrp_cb(skb)->mh->attrtype > app->app->maxattr ||
 758            mrp_cb(skb)->mh->attrlen == 0)
 759                return -1;
 760
 761        while (skb->len > *offset) {
 762                if (mrp_pdu_parse_end_mark(skb, offset) < 0)
 763                        break;
 764                if (mrp_pdu_parse_vecattr(app, skb, offset) < 0)
 765                        return -1;
 766        }
 767        return 0;
 768}
 769
 770static int mrp_rcv(struct sk_buff *skb, struct net_device *dev,
 771                   struct packet_type *pt, struct net_device *orig_dev)
 772{
 773        struct mrp_application *appl = container_of(pt, struct mrp_application,
 774                                                    pkttype);
 775        struct mrp_port *port;
 776        struct mrp_applicant *app;
 777        struct mrp_pdu_hdr _ph;
 778        const struct mrp_pdu_hdr *ph;
 779        int offset = skb_network_offset(skb);
 780
 781        /* If the interface is in promiscuous mode, drop the packet if
 782         * it was unicast to another host.
 783         */
 784        if (unlikely(skb->pkt_type == PACKET_OTHERHOST))
 785                goto out;
 786        skb = skb_share_check(skb, GFP_ATOMIC);
 787        if (unlikely(!skb))
 788                goto out;
 789        port = rcu_dereference(dev->mrp_port);
 790        if (unlikely(!port))
 791                goto out;
 792        app = rcu_dereference(port->applicants[appl->type]);
 793        if (unlikely(!app))
 794                goto out;
 795
 796        ph = skb_header_pointer(skb, offset, sizeof(_ph), &_ph);
 797        if (!ph)
 798                goto out;
 799        offset += sizeof(_ph);
 800
 801        if (ph->version != app->app->version)
 802                goto out;
 803
 804        spin_lock(&app->lock);
 805        while (skb->len > offset) {
 806                if (mrp_pdu_parse_end_mark(skb, &offset) < 0)
 807                        break;
 808                if (mrp_pdu_parse_msg(app, skb, &offset) < 0)
 809                        break;
 810        }
 811        spin_unlock(&app->lock);
 812out:
 813        kfree_skb(skb);
 814        return 0;
 815}
 816
 817static int mrp_init_port(struct net_device *dev)
 818{
 819        struct mrp_port *port;
 820
 821        port = kzalloc(sizeof(*port), GFP_KERNEL);
 822        if (!port)
 823                return -ENOMEM;
 824        rcu_assign_pointer(dev->mrp_port, port);
 825        return 0;
 826}
 827
 828static void mrp_release_port(struct net_device *dev)
 829{
 830        struct mrp_port *port = rtnl_dereference(dev->mrp_port);
 831        unsigned int i;
 832
 833        for (i = 0; i <= MRP_APPLICATION_MAX; i++) {
 834                if (rtnl_dereference(port->applicants[i]))
 835                        return;
 836        }
 837        RCU_INIT_POINTER(dev->mrp_port, NULL);
 838        kfree_rcu(port, rcu);
 839}
 840
 841int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl)
 842{
 843        struct mrp_applicant *app;
 844        int err;
 845
 846        ASSERT_RTNL();
 847
 848        if (!rtnl_dereference(dev->mrp_port)) {
 849                err = mrp_init_port(dev);
 850                if (err < 0)
 851                        goto err1;
 852        }
 853
 854        err = -ENOMEM;
 855        app = kzalloc(sizeof(*app), GFP_KERNEL);
 856        if (!app)
 857                goto err2;
 858
 859        err = dev_mc_add(dev, appl->group_address);
 860        if (err < 0)
 861                goto err3;
 862
 863        app->dev = dev;
 864        app->app = appl;
 865        app->mad = RB_ROOT;
 866        spin_lock_init(&app->lock);
 867        skb_queue_head_init(&app->queue);
 868        rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app);
 869        setup_timer(&app->join_timer, mrp_join_timer, (unsigned long)app);
 870        mrp_join_timer_arm(app);
 871        setup_timer(&app->periodic_timer, mrp_periodic_timer,
 872                    (unsigned long)app);
 873        mrp_periodic_timer_arm(app);
 874        return 0;
 875
 876err3:
 877        kfree(app);
 878err2:
 879        mrp_release_port(dev);
 880err1:
 881        return err;
 882}
 883EXPORT_SYMBOL_GPL(mrp_init_applicant);
 884
 885void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
 886{
 887        struct mrp_port *port = rtnl_dereference(dev->mrp_port);
 888        struct mrp_applicant *app = rtnl_dereference(
 889                port->applicants[appl->type]);
 890
 891        ASSERT_RTNL();
 892
 893        RCU_INIT_POINTER(port->applicants[appl->type], NULL);
 894
 895        /* Delete timer and generate a final TX event to flush out
 896         * all pending messages before the applicant is gone.
 897         */
 898        del_timer_sync(&app->join_timer);
 899        del_timer_sync(&app->periodic_timer);
 900
 901        spin_lock_bh(&app->lock);
 902        mrp_mad_event(app, MRP_EVENT_TX);
 903        mrp_pdu_queue(app);
 904        spin_unlock_bh(&app->lock);
 905
 906        mrp_queue_xmit(app);
 907
 908        dev_mc_del(dev, appl->group_address);
 909        kfree_rcu(app, rcu);
 910        mrp_release_port(dev);
 911}
 912EXPORT_SYMBOL_GPL(mrp_uninit_applicant);
 913
 914int mrp_register_application(struct mrp_application *appl)
 915{
 916        appl->pkttype.func = mrp_rcv;
 917        dev_add_pack(&appl->pkttype);
 918        return 0;
 919}
 920EXPORT_SYMBOL_GPL(mrp_register_application);
 921
 922void mrp_unregister_application(struct mrp_application *appl)
 923{
 924        dev_remove_pack(&appl->pkttype);
 925}
 926EXPORT_SYMBOL_GPL(mrp_unregister_application);
 927