~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/802/mrp.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php