auto-attach: Add auto-attach support to ofproto layer
[cascardo/ovs.git] / lib / lldp / lldpd.c
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3  * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <config.h>
19 #include "lldpd.h"
20 #include <arpa/inet.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <inttypes.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <sys/ioctl.h>
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <time.h>
33 #include <unistd.h>
34 #ifndef _WIN32
35 #include <grp.h>
36 #include <libgen.h>
37 #include <netinet/if_ether.h>
38 #include <pwd.h>
39 #include <sys/select.h>
40 #include <sys/utsname.h>
41 #endif
42 #include "compiler.h"
43 #include "list.h"
44 #include "packets.h"
45
46 VLOG_DEFINE_THIS_MODULE(lldpd);
47
48 static struct protocol protos[] =
49 {
50     { LLDPD_MODE_LLDP, 1, "LLDP", 'l', lldp_send, lldp_decode, NULL,
51       LLDP_MULTICAST_ADDR },
52     { 0, 0, "any", ' ', NULL, NULL, NULL,
53     { 0,0,0,0,0,0 } }
54 };
55
56 void lldpd_assign_cfg_to_protocols(struct lldpd *cfg)
57 {
58     cfg->g_protocols = protos;
59 }
60
61 struct lldpd_hardware *
62 lldpd_get_hardware(struct lldpd *cfg, char *name, int index,
63                    struct lldpd_ops *ops)
64 {
65     struct lldpd_hardware *hw;
66
67     LIST_FOR_EACH (hw, h_entries, &cfg->g_hardware.h_entries) {
68         if ((strcmp(hw->h_ifname, name) == 0) &&
69             (hw->h_ifindex == index) &&
70             ((!ops) || (ops == hw->h_ops))) {
71             return hw;
72         }
73     }
74
75     return NULL;
76 }
77
78 struct lldpd_hardware *
79 lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
80 {
81     struct lldpd_hardware *hw;
82
83     VLOG_DBG("allocate a new local hardware interface (%s)", name);
84
85     if ((hw = (struct lldpd_hardware *) calloc(1, sizeof *hw)) == NULL) {
86         return NULL;
87     }
88
89     hw->h_cfg = cfg;
90     ovs_strlcpy(hw->h_ifname, name, sizeof hw->h_ifname);
91     hw->h_ifindex = index;
92     hw->h_lport.p_chassis = (struct lldpd_chassis *)
93     list_front(&cfg->g_chassis.list);
94     hw->h_lport.p_chassis->c_refcount++;
95     list_init(&hw->h_rports.p_entries);
96
97     return hw;
98 }
99
100 struct lldpd_mgmt *
101 lldpd_alloc_mgmt(int family, void *addrptr, size_t addrsize, u_int32_t iface)
102 {
103     struct lldpd_mgmt *mgmt;
104
105     VLOG_DBG("allocate a new management address (family: %d)", family);
106
107     if (family <= LLDPD_AF_UNSPEC || family >= LLDPD_AF_LAST) {
108         errno = EAFNOSUPPORT;
109         return NULL;
110     }
111     if (addrsize > LLDPD_MGMT_MAXADDRSIZE) {
112         errno = EOVERFLOW;
113         return NULL;
114     }
115     mgmt = calloc(1, sizeof *mgmt);
116     if (mgmt == NULL) {
117         errno = ENOMEM;
118         return NULL;
119     }
120     mgmt->m_family = family;
121     memcpy(&mgmt->m_addr, addrptr, addrsize);
122     mgmt->m_addrsize = addrsize;
123     mgmt->m_iface = iface;
124
125     return mgmt;
126 }
127
128 void
129 lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware)
130 {
131     VLOG_DBG("cleanup hardware port %s", hardware->h_ifname);
132
133     lldpd_port_cleanup(&hardware->h_lport, 1);
134     if (hardware->h_ops && hardware->h_ops->cleanup) {
135         hardware->h_ops->cleanup(cfg, hardware);
136     }
137     free(hardware);
138 }
139
140 void
141 lldpd_cleanup(struct lldpd *cfg)
142 {
143     struct lldpd_hardware *hw, *hw_next;
144     struct lldpd_chassis *chassis, *chassis_next;
145
146     VLOG_DBG("cleanup all ports");
147
148     LIST_FOR_EACH_SAFE (hw, hw_next, h_entries, &cfg->g_hardware.h_entries) {
149         if (!hw->h_flags) {
150             list_remove(&hw->h_entries);
151             lldpd_remote_cleanup(hw, NULL, 1);
152             lldpd_hardware_cleanup(cfg, hw);
153         } else {
154             lldpd_remote_cleanup(hw, NULL, 0);
155         }
156     }
157
158     VLOG_DBG("cleanup all chassis");
159
160     LIST_FOR_EACH_SAFE (chassis, chassis_next, list, &cfg->g_chassis.list) {
161         if (chassis->c_refcount == 0) {
162             list_remove(&chassis->list);
163             lldpd_chassis_cleanup(chassis, 1);
164         }
165     }
166 }
167
168 /* Update chassis `ochassis' with values from `chassis'. The later one is not
169  * expected to be part of a list! It will also be wiped from memory.
170  */
171 static void
172 lldpd_move_chassis(struct lldpd_chassis *ochassis,
173     struct lldpd_chassis *chassis)
174 {
175     struct lldpd_mgmt *mgmt, *mgmt_next;
176     int refcount = ochassis->c_refcount;
177     int index = ochassis->c_index;
178     struct ovs_list listcopy;
179
180     /* We want to keep refcount, index and list stuff from the current chassis
181      */
182     memcpy(&listcopy, &ochassis->list, sizeof listcopy);
183     lldpd_chassis_cleanup(ochassis, 0);
184
185     /* Make the copy. */
186     /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
187      * marshaling.
188      */
189     memcpy(ochassis, chassis, sizeof *ochassis);
190     list_init(&ochassis->c_mgmt.m_entries);
191
192     /* Copy of management addresses */
193     LIST_FOR_EACH_SAFE (mgmt,
194                         mgmt_next,
195                         m_entries,
196                         &chassis->c_mgmt.m_entries) {
197         list_remove(&mgmt->m_entries);
198         list_insert(&ochassis->c_mgmt.m_entries, &mgmt->m_entries);
199     }
200
201     /* Restore saved values */
202     ochassis->c_refcount = refcount;
203     ochassis->c_index = index;
204     memcpy(&ochassis->list, &listcopy, sizeof ochassis->list);
205
206     /* Get rid of the new chassis */
207     free(chassis);
208 }
209
210 static int
211 lldpd_guess_type(struct lldpd *cfg, char *frame, int s)
212 {
213     int i;
214
215     if (s < ETH_ADDR_LEN) {
216         return -1;
217     }
218
219     for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
220         if (!cfg->g_protocols[i].enabled) {
221             continue;
222         }
223         if (cfg->g_protocols[i].guess == NULL) {
224             if (memcmp(frame, cfg->g_protocols[i].mac, ETH_ADDR_LEN) == 0) {
225                 VLOG_DBG("guessed protocol is %s (from MAC address)",
226                     cfg->g_protocols[i].name);
227                 return cfg->g_protocols[i].mode;
228             }
229         } else {
230             if (cfg->g_protocols[i].guess(frame, s)) {
231                 VLOG_DBG("guessed protocol is %s (from detector function)",
232                     cfg->g_protocols[i].name);
233                 return cfg->g_protocols[i].mode;
234             }
235         }
236     }
237
238     return -1;
239 }
240
241 static void
242 lldpd_decode(struct lldpd *cfg, char *frame, int s,
243              struct lldpd_hardware *hw)
244 {
245     size_t listsize, i;
246     struct lldpd_chassis *chassis, *ochassis = NULL;
247     struct lldpd_port *port, *oport;
248     int guess = LLDPD_MODE_LLDP;
249     struct eth_header eheader;
250     int count = 0;
251     int found = 0;
252
253     VLOG_DBG("decode a received frame on %s size %d", hw->h_ifname,s);
254
255     if (s < sizeof(struct eth_header) + 4) {
256         /* Too short, just discard it */
257         return;
258     }
259
260     /* Decapsulate VLAN frames */
261     memcpy(&eheader, frame, sizeof eheader);
262     if (eheader.eth_type == htons(ETH_TYPE_VLAN)) {
263         /* VLAN decapsulation means to shift 4 bytes left the frame from
264          * offset 2 * ETH_ADDR_LEN
265          */
266         memmove(frame + 2 * ETH_ADDR_LEN, frame + 2 * ETH_ADDR_LEN + 4,
267                 s - 2 * ETH_ADDR_LEN);
268         s -= 4;
269     }
270
271     LIST_FOR_EACH (oport, p_entries, &hw->h_rports.p_entries) {
272         if ((oport->p_lastframe != NULL) &&
273             (oport->p_lastframe->size == s) &&
274             (memcmp(oport->p_lastframe->frame, frame, s) == 0)) {
275             /* Already received the same frame */
276             VLOG_DBG("duplicate frame, no need to decode");
277             oport->p_lastupdate = time(NULL);
278             return;
279         }
280     }
281
282     guess = lldpd_guess_type(cfg, frame, s);
283     VLOG_DBG("guessed %d enabled:%d", guess, cfg->g_protocols[0].enabled);
284
285     for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
286         if (!cfg->g_protocols[i].enabled) {
287             continue;
288         }
289         if (cfg->g_protocols[i].mode == guess) {
290             VLOG_DBG("using decode function for %s protocol",
291                 cfg->g_protocols[i].name);
292             if (cfg->g_protocols[i].decode(cfg, frame, s, hw, &chassis, &port)
293                     == -1) {
294                 VLOG_DBG("function for %s protocol did not "
295                          "decode this frame",
296                          cfg->g_protocols[i].name);
297                 return;
298             }
299             chassis->c_protocol = port->p_protocol = cfg->g_protocols[i].mode;
300             break;
301       }
302       VLOG_DBG(" %"PRIuSIZE "mode:%d enabled:%d",
303                i, cfg->g_protocols[i].mode, cfg->g_protocols[i].enabled);
304     }
305     if (cfg->g_protocols[i].mode == 0) {
306         VLOG_DBG("unable to guess frame type on %s", hw->h_ifname);
307         return;
308     }
309
310     /* Do we already have the same MSAP somewhere? */
311     VLOG_DBG("search for the same MSAP");
312
313     LIST_FOR_EACH (oport, p_entries, &hw->h_rports.p_entries) {
314         if (port->p_protocol == oport->p_protocol) {
315             count++;
316             if ((port->p_id_subtype == oport->p_id_subtype) &&
317                 (port->p_id_len == oport->p_id_len) &&
318                 (memcmp(port->p_id, oport->p_id, port->p_id_len) == 0) &&
319                 (chassis->c_id_subtype == oport->p_chassis->c_id_subtype) &&
320                 (chassis->c_id_len == oport->p_chassis->c_id_len) &&
321                 (memcmp(chassis->c_id, oport->p_chassis->c_id,
322                 chassis->c_id_len) == 0)) {
323                 ochassis = oport->p_chassis;
324                 VLOG_DBG("MSAP is already known");
325                 found = 1;
326                 break;
327             }
328         }
329     }
330
331     if (!found) {
332        oport = NULL;
333     }
334
335     /* Do we have room for a new MSAP? */
336     if (!oport && cfg->g_config.c_max_neighbors) {
337         if (count == (cfg->g_config.c_max_neighbors - 1)) {
338             VLOG_DBG("max neighbors %d reached for port %s, "
339                      "dropping any new ones silently",
340                      cfg->g_config.c_max_neighbors,
341                      hw->h_ifname);
342         } else if (count > cfg->g_config.c_max_neighbors - 1) {
343             VLOG_DBG("too many neighbors for port %s, drop this new one",
344                      hw->h_ifname);
345             lldpd_port_cleanup(port, 1);
346             lldpd_chassis_cleanup(chassis, 1);
347             free(port);
348             return;
349         }
350     }
351
352     /* No, but do we already know the system? */
353     if (!oport) {
354         int found = 0;
355         VLOG_DBG("MSAP is unknown, search for the chassis");
356
357         LIST_FOR_EACH (ochassis, list, &cfg->g_chassis.list) {
358                 if ((chassis->c_protocol == ochassis->c_protocol) &&
359                     (chassis->c_id_subtype == ochassis->c_id_subtype) &&
360                     (chassis->c_id_len == ochassis->c_id_len) &&
361                     (memcmp(chassis->c_id, ochassis->c_id,
362                     chassis->c_id_len) == 0)) {
363                     found=1;
364                     break;
365                 }
366         }
367
368         if (!found) {
369             ochassis = NULL;
370         }
371     }
372
373     if (oport) {
374         /* The port is known, remove it before adding it back */
375         list_remove(&oport->p_entries);
376         lldpd_port_cleanup(oport, 1);
377         free(oport);
378     }
379
380     if (ochassis) {
381         lldpd_move_chassis(ochassis, chassis);
382         chassis = ochassis;
383     } else {
384         /* Chassis not known, add it */
385         VLOG_DBG("unknown chassis, add it to the list");
386         chassis->c_index = ++cfg->g_lastrid;
387         chassis->c_refcount = 0;
388         list_push_back(&cfg->g_chassis.list, &chassis->list);
389         listsize = list_size(&cfg->g_chassis.list);
390         VLOG_DBG("%"PRIuSIZE " different systems are known", listsize);
391     }
392
393     /* Add port */
394     port->p_lastchange = port->p_lastupdate = time(NULL);
395     if ((port->p_lastframe = malloc(s + sizeof(struct lldpd_frame))) != NULL) {
396         port->p_lastframe->size = s;
397         memcpy(port->p_lastframe->frame, frame, s);
398     }
399     list_insert(&hw->h_rports.p_entries, &port->p_entries);
400
401     port->p_chassis = chassis;
402     port->p_chassis->c_refcount++;
403     /* Several cases are possible :
404      *   1. chassis is new, its refcount was 0. It is now attached
405      *      to this port, its refcount is 1.
406      *   2. chassis already exists and was attached to another
407      *      port, we increase its refcount accordingly.
408      *   3. chassis already exists and was attached to the same
409      *      port, its refcount was decreased with
410      *      lldpd_port_cleanup() and is now increased again.
411      *
412      * In all cases, if the port already existed, it has been
413      * freed with lldpd_port_cleanup() and therefore, the refcount
414      * of the chassis that was attached to it is decreased.
415      */
416     /* coverity[use_after_free] TAILQ_REMOVE does the right thing */
417     i = list_size((struct ovs_list *) &hw->h_rports);
418     VLOG_DBG("%"PRIuSIZE " neighbors for %s", i, hw->h_ifname);
419
420     if (!oport)  {
421         hw->h_insert_cnt++;
422     }
423
424     return;
425 }
426
427 static void
428 lldpd_hide_ports(struct lldpd *cfg,
429                  struct lldpd_hardware *hw,
430                  int mask) {
431     struct lldpd_port *port;
432     int protocols[LLDPD_MODE_MAX + 1];
433     char buffer[256];
434     int i, j, k, found = 0;
435     unsigned int min;
436
437     VLOG_DBG("apply smart filter for port %s", hw->h_ifname);
438
439     /* Compute the number of occurrences of each protocol */
440     for (i = 0; i <= LLDPD_MODE_MAX; i++) {
441         protocols[i] = 0;
442     }
443
444     LIST_FOR_EACH (port, p_entries, &hw->h_rports.p_entries) {
445         protocols[port->p_protocol]++;
446     }
447
448     /* Turn the protocols[] array into an array of
449      * enabled/disabled protocols. 1 means enabled, 0
450      * means disabled.
451      */
452     min = (unsigned int) - 1;
453     for (i = 0; i <= LLDPD_MODE_MAX; i++) {
454         if (protocols[i] && (protocols[i] < min)) {
455             min = protocols[i];
456         }
457     }
458     for (i = 0; i <= LLDPD_MODE_MAX; i++) {
459         if ((protocols[i] == min) && !found) {
460             /* If we need a tie breaker, we take the first protocol only */
461             if (cfg->g_config.c_smart & mask &
462                 (SMART_OUTGOING_ONE_PROTO | SMART_INCOMING_ONE_PROTO)) {
463                 found = 1;
464             }
465             protocols[i] = 1;
466         } else {
467             protocols[i] = 0;
468         }
469     }
470
471     /* We set the p_hidden flag to 1 if the protocol is disabled */
472     LIST_FOR_EACH (port, p_entries, &hw->h_rports.p_entries) {
473         if (mask == SMART_OUTGOING) {
474             port->p_hidden_out = protocols[port->p_protocol] ? 0 : 1;
475         } else {
476             port->p_hidden_in = protocols[port->p_protocol] ? 0 : 1;
477         }
478     }
479
480     /* If we want only one neighbor, we take the first one */
481     if (cfg->g_config.c_smart & mask &
482         (SMART_OUTGOING_ONE_NEIGH | SMART_INCOMING_ONE_NEIGH)) {
483         found = 0;
484
485         LIST_FOR_EACH (port, p_entries, &hw->h_rports.p_entries) {
486             if (mask == SMART_OUTGOING) {
487                 if (found) {
488                     port->p_hidden_out = 1;
489                 }
490                 if (!port->p_hidden_out) {
491                     found = 1;
492                 }
493             }
494             if (mask == SMART_INCOMING) {
495                 if (found) {
496                     port->p_hidden_in = 1;
497                 }
498                 if (!port->p_hidden_in) {
499                     found = 1;
500                 }
501             }
502         }
503     }
504
505     /* Print a debug message summarizing the operation */
506     for (i = 0; i <= LLDPD_MODE_MAX; i++) {
507         protocols[i] = 0;
508     }
509
510     k = j = 0;
511     LIST_FOR_EACH (port, p_entries, &hw->h_rports.p_entries) {
512         if (!(((mask == SMART_OUTGOING) && port->p_hidden_out) ||
513               ((mask == SMART_INCOMING) && port->p_hidden_in))) {
514             k++;
515             protocols[port->p_protocol] = 1;
516         }
517         j++;
518     }
519
520     buffer[0] = '\0';
521     for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
522         if (cfg->g_protocols[i].enabled &&
523             protocols[cfg->g_protocols[i].mode]) {
524             if (strlen(buffer) +
525                 strlen(cfg->g_protocols[i].name) + 3 > sizeof(buffer)) {
526                 /* Unlikely, our buffer is too small */
527                 memcpy(buffer + sizeof(buffer) - 4, "...", 4);
528                 break;
529             }
530             if (buffer[0]) {
531                 strncat(buffer, ", ", 2);
532                 strncat(buffer, cfg->g_protocols[i].name,
533                 strlen(cfg->g_protocols[i].name));
534             }
535         }
536     }
537     VLOG_DBG("%s: %s: %d visible neighbors (out of %d)",
538              hw->h_ifname,
539              (mask == SMART_OUTGOING) ? "out filter" : "in filter",
540              k, j);
541     VLOG_DBG("%s: protocols: %s",
542              hw->h_ifname, buffer[0] ? buffer : "(none)");
543 }
544
545 /* Hide unwanted ports depending on smart mode set by the user */
546 static void
547 lldpd_hide_all(struct lldpd *cfg)
548 {
549     struct lldpd_hardware *hw;
550
551     if (!cfg->g_config.c_smart) {
552         return;
553     }
554
555     VLOG_DBG("apply smart filter results on all ports");
556
557     LIST_FOR_EACH (hw, h_entries, &cfg->g_hardware.h_entries) {
558         if (cfg->g_config.c_smart & SMART_INCOMING_FILTER) {
559             lldpd_hide_ports(cfg, hw, SMART_INCOMING);
560         }
561         if (cfg->g_config.c_smart & SMART_OUTGOING_FILTER) {
562             lldpd_hide_ports(cfg, hw, SMART_OUTGOING);
563         }
564     }
565 }
566
567 void
568 lldpd_recv(struct lldpd *cfg,
569            struct lldpd_hardware *hw,
570            char *buffer,
571            size_t bufSize)
572 {
573     int n = bufSize;
574
575     VLOG_DBG("receive a frame on %s", hw->h_ifname);
576     if (cfg->g_config.c_paused) {
577         VLOG_DBG("paused, ignore the frame on %s", hw->h_ifname);
578         return;
579     }
580     hw->h_rx_cnt++;
581     VLOG_DBG("decode received frame on %s h_rx_cnt=%" PRIu64,
582              hw->h_ifname, hw->h_rx_cnt);
583     lldpd_decode(cfg, buffer, n, hw);
584     lldpd_hide_all(cfg); /* Immediatly hide */
585 }
586
587 uint32_t
588 lldpd_send(struct lldpd_hardware *hw, struct dp_packet *p)
589 {
590     struct lldpd *cfg = hw->h_cfg;
591     struct lldpd_port *port;
592     int i, sent = 0;
593     int lldp_size = 0;
594
595     if (cfg->g_config.c_receiveonly || cfg->g_config.c_paused) {
596         return 0;
597     }
598 #ifndef _WIN32
599     if ((hw->h_flags & IFF_RUNNING) == 0) {
600         return 0;
601     }
602 #endif
603
604     for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
605         if (!cfg->g_protocols[i].enabled) {
606             continue;
607         }
608
609         /* We send only if we have at least one remote system
610          * speaking this protocol or if the protocol is forced */
611         if (cfg->g_protocols[i].enabled > 1) {
612             if ((lldp_size = cfg->g_protocols[i].send(cfg, hw, p)) != E2BIG) {
613                 sent++;
614                 continue;
615             } else {
616                 VLOG_DBG("send PDU on %s failed E2BIG", hw->h_ifname);
617                 continue;
618             }
619         }
620
621         LIST_FOR_EACH (port, p_entries, &hw->h_rports.p_entries) {
622             /* If this remote port is disabled, we don't consider it */
623             if (port->p_hidden_out) {
624                 continue;
625             }
626             if (port->p_protocol == cfg->g_protocols[i].mode) {
627                 VLOG_DBG("send PDU on %s with protocol %s",
628                          hw->h_ifname, cfg->g_protocols[i].name);
629                 lldp_size = cfg->g_protocols[i].send(cfg, hw, p);
630                 sent++;
631                 break;
632             }
633         }
634     }
635
636     if (!sent) {
637         /* Nothing was sent for this port, let's speak the first
638          * available protocol.
639          */
640         for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
641             if (!cfg->g_protocols[i].enabled) {
642                 continue;
643             }
644             VLOG_DBG("fallback to protocol %s for %s",
645                      cfg->g_protocols[i].name, hw->h_ifname);
646             lldp_size = cfg->g_protocols[i].send(cfg, hw, p);
647             break;
648         }
649         if (cfg->g_protocols[i].mode == 0) {
650             VLOG_WARN("no protocol enabled, dunno what to send");
651         }
652     }
653
654     return lldp_size;
655 }