Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
garp.c
Go to the documentation of this file.
1 /*
2  * IEEE 802.1D Generic Attribute Registration Protocol (GARP)
3  *
4  * Copyright (c) 2008 Patrick McHardy <[email protected]>
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  * version 2 as published by the Free Software Foundation.
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/llc.h>
17 #include <linux/slab.h>
18 #include <linux/module.h>
19 #include <net/llc.h>
20 #include <net/llc_pdu.h>
21 #include <net/garp.h>
22 #include <asm/unaligned.h>
23 
24 static unsigned int garp_join_time __read_mostly = 200;
25 module_param(garp_join_time, uint, 0644);
26 MODULE_PARM_DESC(garp_join_time, "Join time in ms (default 200ms)");
27 MODULE_LICENSE("GPL");
28 
29 static const struct garp_state_trans {
30  u8 state;
31  u8 action;
32 } garp_applicant_state_table[GARP_APPLICANT_MAX + 1][GARP_EVENT_MAX + 1] = {
33  [GARP_APPLICANT_VA] = {
35  .action = GARP_ACTION_S_JOIN_IN },
36  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_AA },
38  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VA },
42  [GARP_EVENT_REQ_LEAVE] = { .state = GARP_APPLICANT_LA },
43  },
44  [GARP_APPLICANT_AA] = {
46  .action = GARP_ACTION_S_JOIN_IN },
47  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_QA },
49  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VA },
53  [GARP_EVENT_REQ_LEAVE] = { .state = GARP_APPLICANT_LA },
54  },
55  [GARP_APPLICANT_QA] = {
57  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_QA },
59  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VA },
63  [GARP_EVENT_REQ_LEAVE] = { .state = GARP_APPLICANT_LA },
64  },
65  [GARP_APPLICANT_LA] = {
67  .action = GARP_ACTION_S_LEAVE_EMPTY },
68  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_LA },
70  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_LA },
73  [GARP_EVENT_REQ_JOIN] = { .state = GARP_APPLICANT_VA },
75  },
76  [GARP_APPLICANT_VP] = {
78  .action = GARP_ACTION_S_JOIN_IN },
79  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_AP },
81  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VP },
85  [GARP_EVENT_REQ_LEAVE] = { .state = GARP_APPLICANT_VO },
86  },
87  [GARP_APPLICANT_AP] = {
89  .action = GARP_ACTION_S_JOIN_IN },
90  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_QP },
92  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VP },
96  [GARP_EVENT_REQ_LEAVE] = { .state = GARP_APPLICANT_AO },
97  },
98  [GARP_APPLICANT_QP] = {
100  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_QP },
102  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VP },
103  [GARP_EVENT_R_LEAVE_IN] = { .state = GARP_APPLICANT_VP },
106  [GARP_EVENT_REQ_LEAVE] = { .state = GARP_APPLICANT_QO },
107  },
108  [GARP_APPLICANT_VO] = {
110  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_AO },
112  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VO },
113  [GARP_EVENT_R_LEAVE_IN] = { .state = GARP_APPLICANT_VO },
115  [GARP_EVENT_REQ_JOIN] = { .state = GARP_APPLICANT_VP },
117  },
118  [GARP_APPLICANT_AO] = {
120  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_QO },
122  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VO },
123  [GARP_EVENT_R_LEAVE_IN] = { .state = GARP_APPLICANT_VO },
125  [GARP_EVENT_REQ_JOIN] = { .state = GARP_APPLICANT_AP },
127  },
128  [GARP_APPLICANT_QO] = {
130  [GARP_EVENT_R_JOIN_IN] = { .state = GARP_APPLICANT_QO },
132  [GARP_EVENT_R_EMPTY] = { .state = GARP_APPLICANT_VO },
133  [GARP_EVENT_R_LEAVE_IN] = { .state = GARP_APPLICANT_VO },
135  [GARP_EVENT_REQ_JOIN] = { .state = GARP_APPLICANT_QP },
137  },
138 };
139 
140 static int garp_attr_cmp(const struct garp_attr *attr,
141  const void *data, u8 len, u8 type)
142 {
143  if (attr->type != type)
144  return attr->type - type;
145  if (attr->dlen != len)
146  return attr->dlen - len;
147  return memcmp(attr->data, data, len);
148 }
149 
150 static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app,
151  const void *data, u8 len, u8 type)
152 {
153  struct rb_node *parent = app->gid.rb_node;
154  struct garp_attr *attr;
155  int d;
156 
157  while (parent) {
158  attr = rb_entry(parent, struct garp_attr, node);
159  d = garp_attr_cmp(attr, data, len, type);
160  if (d > 0)
161  parent = parent->rb_left;
162  else if (d < 0)
163  parent = parent->rb_right;
164  else
165  return attr;
166  }
167  return NULL;
168 }
169 
170 static struct garp_attr *garp_attr_create(struct garp_applicant *app,
171  const void *data, u8 len, u8 type)
172 {
173  struct rb_node *parent = NULL, **p = &app->gid.rb_node;
174  struct garp_attr *attr;
175  int d;
176 
177  while (*p) {
178  parent = *p;
179  attr = rb_entry(parent, struct garp_attr, node);
180  d = garp_attr_cmp(attr, data, len, type);
181  if (d > 0)
182  p = &parent->rb_left;
183  else if (d < 0)
184  p = &parent->rb_right;
185  else {
186  /* The attribute already exists; re-use it. */
187  return attr;
188  }
189  }
190  attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
191  if (!attr)
192  return attr;
193  attr->state = GARP_APPLICANT_VO;
194  attr->type = type;
195  attr->dlen = len;
196  memcpy(attr->data, data, len);
197 
198  rb_link_node(&attr->node, parent, p);
199  rb_insert_color(&attr->node, &app->gid);
200  return attr;
201 }
202 
203 static void garp_attr_destroy(struct garp_applicant *app, struct garp_attr *attr)
204 {
205  rb_erase(&attr->node, &app->gid);
206  kfree(attr);
207 }
208 
209 static int garp_pdu_init(struct garp_applicant *app)
210 {
211  struct sk_buff *skb;
212  struct garp_pdu_hdr *gp;
213 
214 #define LLC_RESERVE sizeof(struct llc_pdu_un)
215  skb = alloc_skb(app->dev->mtu + LL_RESERVED_SPACE(app->dev),
216  GFP_ATOMIC);
217  if (!skb)
218  return -ENOMEM;
219 
220  skb->dev = app->dev;
221  skb->protocol = htons(ETH_P_802_2);
222  skb_reserve(skb, LL_RESERVED_SPACE(app->dev) + LLC_RESERVE);
223 
224  gp = (struct garp_pdu_hdr *)__skb_put(skb, sizeof(*gp));
226 
227  app->pdu = skb;
228  return 0;
229 }
230 
231 static int garp_pdu_append_end_mark(struct garp_applicant *app)
232 {
233  if (skb_tailroom(app->pdu) < sizeof(u8))
234  return -1;
235  *(u8 *)__skb_put(app->pdu, sizeof(u8)) = GARP_END_MARK;
236  return 0;
237 }
238 
239 static void garp_pdu_queue(struct garp_applicant *app)
240 {
241  if (!app->pdu)
242  return;
243 
244  garp_pdu_append_end_mark(app);
245  garp_pdu_append_end_mark(app);
246 
247  llc_pdu_header_init(app->pdu, LLC_PDU_TYPE_U, LLC_SAP_BSPAN,
249  llc_pdu_init_as_ui_cmd(app->pdu);
250  llc_mac_hdr_init(app->pdu, app->dev->dev_addr,
251  app->app->proto.group_address);
252 
253  skb_queue_tail(&app->queue, app->pdu);
254  app->pdu = NULL;
255 }
256 
257 static void garp_queue_xmit(struct garp_applicant *app)
258 {
259  struct sk_buff *skb;
260 
261  while ((skb = skb_dequeue(&app->queue)))
262  dev_queue_xmit(skb);
263 }
264 
265 static int garp_pdu_append_msg(struct garp_applicant *app, u8 attrtype)
266 {
267  struct garp_msg_hdr *gm;
268 
269  if (skb_tailroom(app->pdu) < sizeof(*gm))
270  return -1;
271  gm = (struct garp_msg_hdr *)__skb_put(app->pdu, sizeof(*gm));
272  gm->attrtype = attrtype;
273  garp_cb(app->pdu)->cur_type = attrtype;
274  return 0;
275 }
276 
277 static int garp_pdu_append_attr(struct garp_applicant *app,
278  const struct garp_attr *attr,
279  enum garp_attr_event event)
280 {
281  struct garp_attr_hdr *ga;
282  unsigned int len;
283  int err;
284 again:
285  if (!app->pdu) {
286  err = garp_pdu_init(app);
287  if (err < 0)
288  return err;
289  }
290 
291  if (garp_cb(app->pdu)->cur_type != attr->type) {
292  if (garp_cb(app->pdu)->cur_type &&
293  garp_pdu_append_end_mark(app) < 0)
294  goto queue;
295  if (garp_pdu_append_msg(app, attr->type) < 0)
296  goto queue;
297  }
298 
299  len = sizeof(*ga) + attr->dlen;
300  if (skb_tailroom(app->pdu) < len)
301  goto queue;
302  ga = (struct garp_attr_hdr *)__skb_put(app->pdu, len);
303  ga->len = len;
304  ga->event = event;
305  memcpy(ga->data, attr->data, attr->dlen);
306  return 0;
307 
308 queue:
309  garp_pdu_queue(app);
310  goto again;
311 }
312 
313 static void garp_attr_event(struct garp_applicant *app,
314  struct garp_attr *attr, enum garp_event event)
315 {
317 
318  state = garp_applicant_state_table[attr->state][event].state;
319  if (state == GARP_APPLICANT_INVALID)
320  return;
321 
322  switch (garp_applicant_state_table[attr->state][event].action) {
323  case GARP_ACTION_NONE:
324  break;
326  /* When appending the attribute fails, don't update state in
327  * order to retry on next TRANSMIT_PDU event. */
328  if (garp_pdu_append_attr(app, attr, GARP_JOIN_IN) < 0)
329  return;
330  break;
332  garp_pdu_append_attr(app, attr, GARP_LEAVE_EMPTY);
333  /* As a pure applicant, sending a leave message implies that
334  * the attribute was unregistered and can be destroyed. */
335  garp_attr_destroy(app, attr);
336  return;
337  default:
338  WARN_ON(1);
339  }
340 
341  attr->state = state;
342 }
343 
344 int garp_request_join(const struct net_device *dev,
345  const struct garp_application *appl,
346  const void *data, u8 len, u8 type)
347 {
348  struct garp_port *port = rtnl_dereference(dev->garp_port);
349  struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
350  struct garp_attr *attr;
351 
352  spin_lock_bh(&app->lock);
353  attr = garp_attr_create(app, data, len, type);
354  if (!attr) {
355  spin_unlock_bh(&app->lock);
356  return -ENOMEM;
357  }
359  spin_unlock_bh(&app->lock);
360  return 0;
361 }
363 
364 void garp_request_leave(const struct net_device *dev,
365  const struct garp_application *appl,
366  const void *data, u8 len, u8 type)
367 {
368  struct garp_port *port = rtnl_dereference(dev->garp_port);
369  struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
370  struct garp_attr *attr;
371 
372  spin_lock_bh(&app->lock);
373  attr = garp_attr_lookup(app, data, len, type);
374  if (!attr) {
375  spin_unlock_bh(&app->lock);
376  return;
377  }
379  spin_unlock_bh(&app->lock);
380 }
382 
383 static void garp_gid_event(struct garp_applicant *app, enum garp_event event)
384 {
385  struct rb_node *node, *next;
386  struct garp_attr *attr;
387 
388  for (node = rb_first(&app->gid);
389  next = node ? rb_next(node) : NULL, node != NULL;
390  node = next) {
391  attr = rb_entry(node, struct garp_attr, node);
392  garp_attr_event(app, attr, event);
393  }
394 }
395 
396 static void garp_join_timer_arm(struct garp_applicant *app)
397 {
398  unsigned long delay;
399 
400  delay = (u64)msecs_to_jiffies(garp_join_time) * net_random() >> 32;
401  mod_timer(&app->join_timer, jiffies + delay);
402 }
403 
404 static void garp_join_timer(unsigned long data)
405 {
406  struct garp_applicant *app = (struct garp_applicant *)data;
407 
408  spin_lock(&app->lock);
409  garp_gid_event(app, GARP_EVENT_TRANSMIT_PDU);
410  garp_pdu_queue(app);
411  spin_unlock(&app->lock);
412 
413  garp_queue_xmit(app);
414  garp_join_timer_arm(app);
415 }
416 
417 static int garp_pdu_parse_end_mark(struct sk_buff *skb)
418 {
419  if (!pskb_may_pull(skb, sizeof(u8)))
420  return -1;
421  if (*skb->data == GARP_END_MARK) {
422  skb_pull(skb, sizeof(u8));
423  return -1;
424  }
425  return 0;
426 }
427 
428 static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
429  u8 attrtype)
430 {
431  const struct garp_attr_hdr *ga;
432  struct garp_attr *attr;
433  enum garp_event event;
434  unsigned int dlen;
435 
436  if (!pskb_may_pull(skb, sizeof(*ga)))
437  return -1;
438  ga = (struct garp_attr_hdr *)skb->data;
439  if (ga->len < sizeof(*ga))
440  return -1;
441 
442  if (!pskb_may_pull(skb, ga->len))
443  return -1;
444  skb_pull(skb, ga->len);
445  dlen = sizeof(*ga) - ga->len;
446 
447  if (attrtype > app->app->maxattr)
448  return 0;
449 
450  switch (ga->event) {
451  case GARP_LEAVE_ALL:
452  if (dlen != 0)
453  return -1;
454  garp_gid_event(app, GARP_EVENT_R_LEAVE_EMPTY);
455  return 0;
456  case GARP_JOIN_EMPTY:
457  event = GARP_EVENT_R_JOIN_EMPTY;
458  break;
459  case GARP_JOIN_IN:
460  event = GARP_EVENT_R_JOIN_IN;
461  break;
462  case GARP_LEAVE_EMPTY:
463  event = GARP_EVENT_R_LEAVE_EMPTY;
464  break;
465  case GARP_EMPTY:
466  event = GARP_EVENT_R_EMPTY;
467  break;
468  default:
469  return 0;
470  }
471 
472  if (dlen == 0)
473  return -1;
474  attr = garp_attr_lookup(app, ga->data, dlen, attrtype);
475  if (attr == NULL)
476  return 0;
477  garp_attr_event(app, attr, event);
478  return 0;
479 }
480 
481 static int garp_pdu_parse_msg(struct garp_applicant *app, struct sk_buff *skb)
482 {
483  const struct garp_msg_hdr *gm;
484 
485  if (!pskb_may_pull(skb, sizeof(*gm)))
486  return -1;
487  gm = (struct garp_msg_hdr *)skb->data;
488  if (gm->attrtype == 0)
489  return -1;
490  skb_pull(skb, sizeof(*gm));
491 
492  while (skb->len > 0) {
493  if (garp_pdu_parse_attr(app, skb, gm->attrtype) < 0)
494  return -1;
495  if (garp_pdu_parse_end_mark(skb) < 0)
496  break;
497  }
498  return 0;
499 }
500 
501 static void garp_pdu_rcv(const struct stp_proto *proto, struct sk_buff *skb,
502  struct net_device *dev)
503 {
504  struct garp_application *appl = proto->data;
505  struct garp_port *port;
506  struct garp_applicant *app;
507  const struct garp_pdu_hdr *gp;
508 
509  port = rcu_dereference(dev->garp_port);
510  if (!port)
511  goto err;
512  app = rcu_dereference(port->applicants[appl->type]);
513  if (!app)
514  goto err;
515 
516  if (!pskb_may_pull(skb, sizeof(*gp)))
517  goto err;
518  gp = (struct garp_pdu_hdr *)skb->data;
520  goto err;
521  skb_pull(skb, sizeof(*gp));
522 
523  spin_lock(&app->lock);
524  while (skb->len > 0) {
525  if (garp_pdu_parse_msg(app, skb) < 0)
526  break;
527  if (garp_pdu_parse_end_mark(skb) < 0)
528  break;
529  }
530  spin_unlock(&app->lock);
531 err:
532  kfree_skb(skb);
533 }
534 
535 static int garp_init_port(struct net_device *dev)
536 {
537  struct garp_port *port;
538 
539  port = kzalloc(sizeof(*port), GFP_KERNEL);
540  if (!port)
541  return -ENOMEM;
542  rcu_assign_pointer(dev->garp_port, port);
543  return 0;
544 }
545 
546 static void garp_release_port(struct net_device *dev)
547 {
548  struct garp_port *port = rtnl_dereference(dev->garp_port);
549  unsigned int i;
550 
551  for (i = 0; i <= GARP_APPLICATION_MAX; i++) {
552  if (rtnl_dereference(port->applicants[i]))
553  return;
554  }
556  kfree_rcu(port, rcu);
557 }
558 
559 int garp_init_applicant(struct net_device *dev, struct garp_application *appl)
560 {
561  struct garp_applicant *app;
562  int err;
563 
564  ASSERT_RTNL();
565 
566  if (!rtnl_dereference(dev->garp_port)) {
567  err = garp_init_port(dev);
568  if (err < 0)
569  goto err1;
570  }
571 
572  err = -ENOMEM;
573  app = kzalloc(sizeof(*app), GFP_KERNEL);
574  if (!app)
575  goto err2;
576 
577  err = dev_mc_add(dev, appl->proto.group_address);
578  if (err < 0)
579  goto err3;
580 
581  app->dev = dev;
582  app->app = appl;
583  app->gid = RB_ROOT;
584  spin_lock_init(&app->lock);
585  skb_queue_head_init(&app->queue);
586  rcu_assign_pointer(dev->garp_port->applicants[appl->type], app);
587  setup_timer(&app->join_timer, garp_join_timer, (unsigned long)app);
588  garp_join_timer_arm(app);
589  return 0;
590 
591 err3:
592  kfree(app);
593 err2:
594  garp_release_port(dev);
595 err1:
596  return err;
597 }
599 
600 void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl)
601 {
602  struct garp_port *port = rtnl_dereference(dev->garp_port);
603  struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
604 
605  ASSERT_RTNL();
606 
607  RCU_INIT_POINTER(port->applicants[appl->type], NULL);
608 
609  /* Delete timer and generate a final TRANSMIT_PDU event to flush out
610  * all pending messages before the applicant is gone. */
611  del_timer_sync(&app->join_timer);
612  garp_gid_event(app, GARP_EVENT_TRANSMIT_PDU);
613  garp_pdu_queue(app);
614  garp_queue_xmit(app);
615 
616  dev_mc_del(dev, appl->proto.group_address);
617  kfree_rcu(app, rcu);
618  garp_release_port(dev);
619 }
621 
623 {
624  appl->proto.rcv = garp_pdu_rcv;
625  appl->proto.data = appl;
626  return stp_proto_register(&appl->proto);
627 }
629 
631 {
632  stp_proto_unregister(&appl->proto);
633 }