]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/lldpd.c
Also check for VLAN on bridges.
[thirdparty/lldpd.git] / src / lldpd.c
1 /*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "lldpd.h"
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <signal.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <fnmatch.h>
26 #include <time.h>
27 #include <libgen.h>
28 #include <sys/utsname.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/select.h>
32 #include <sys/time.h>
33 #include <sys/ioctl.h>
34 #include <arpa/inet.h>
35 #include <ifaddrs.h>
36 #include <net/if_arp.h>
37 #include <linux/filter.h>
38 #include <linux/if_vlan.h>
39 #include <linux/if_packet.h>
40 #include <linux/sockios.h>
41
42 #ifdef USE_SNMP
43 #include <net-snmp/net-snmp-config.h>
44 #include <net-snmp/net-snmp-includes.h>
45 #include <net-snmp/agent/net-snmp-agent-includes.h>
46 #include <net-snmp/agent/snmp_vars.h>
47 #endif /* USE_SNMP */
48
49 static void usage(void);
50
51 static int lldpd_iface_init(struct lldpd *, struct lldpd_hardware *);
52 static int lldpd_iface_init_vlan(struct lldpd *, struct lldpd_vif *);
53 static void lldpd_iface_init_mtu(struct lldpd *, struct lldpd_hardware *);
54 static int lldpd_iface_close(struct lldpd *, struct lldpd_hardware *);
55 static void lldpd_iface_multicast(struct lldpd *, const char *, int);
56
57 /* "ether proto 0x88cc and ether dst 01:80:c2:00:00:0e" */
58 #define LLDPD_FILTER_LLDP_F \
59 { 0x28, 0, 0, 0x0000000c }, \
60 { 0x15, 0, 5, 0x000088cc }, \
61 { 0x20, 0, 0, 0x00000002 }, \
62 { 0x15, 0, 3, 0xc200000e }, \
63 { 0x28, 0, 0, 0x00000000 }, \
64 { 0x15, 0, 1, 0x00000180 }, \
65 { 0x6, 0, 0, 0x0000ffff }, \
66 { 0x6, 0, 0, 0x00000000 },
67 static struct sock_filter lldpd_filter_lldp_f[] = { LLDPD_FILTER_LLDP_F };
68 #ifdef ENABLE_FDP
69 /* "ether dst 01:e0:52:cc:cc:cc" */
70 #define LLDPD_FILTER_FDP_F \
71 { 0x20, 0, 0, 0x00000002 }, \
72 { 0x15, 0, 3, 0x52cccccc }, \
73 { 0x28, 0, 0, 0x00000000 }, \
74 { 0x15, 0, 1, 0x000001e0 }, \
75 { 0x6, 0, 0, 0x0000ffff }, \
76 { 0x6, 0, 0, 0x00000000 },
77 static struct sock_filter lldpd_filter_fdp_f[] = { LLDPD_FILTER_FDP_F };
78 #endif /* ENABLE_FDP */
79 #ifdef ENABLE_CDP
80 /* "ether dst 01:00:0c:cc:cc:cc" */
81 #define LLDPD_FILTER_CDP_F \
82 { 0x20, 0, 0, 0x00000002 }, \
83 { 0x15, 0, 3, 0x0ccccccc }, \
84 { 0x28, 0, 0, 0x00000000 }, \
85 { 0x15, 0, 1, 0x00000100 }, \
86 { 0x6, 0, 0, 0x0000ffff }, \
87 { 0x6, 0, 0, 0x00000000 },
88 static struct sock_filter lldpd_filter_cdp_f[] = { LLDPD_FILTER_CDP_F };
89 #endif /* ENABLE_CDP */
90 #ifdef ENABLE_SONMP
91 /* "ether dst 01:00:81:00:01:00" */
92 #define LLDPD_FILTER_SONMP_F \
93 { 0x20, 0, 0, 0x00000002 }, \
94 { 0x15, 0, 3, 0x81000100 }, \
95 { 0x28, 0, 0, 0x00000000 }, \
96 { 0x15, 0, 1, 0x00000100 }, \
97 { 0x6, 0, 0, 0x0000ffff }, \
98 { 0x6, 0, 0, 0x00000000 },
99 static struct sock_filter lldpd_filter_sonmp_f[] = { LLDPD_FILTER_SONMP_F };
100 #endif /* ENABLE_SONMP */
101 #ifdef ENABLE_EDP
102 /* "ether dst 00:e0:2b:00:00:00" */
103 #define LLDPD_FILTER_EDP_F \
104 { 0x20, 0, 0, 0x00000002 }, \
105 { 0x15, 0, 3, 0x2b000000 }, \
106 { 0x28, 0, 0, 0x00000000 }, \
107 { 0x15, 0, 1, 0x000000e0 }, \
108 { 0x6, 0, 0, 0x0000ffff }, \
109 { 0x6, 0, 0, 0x00000000 },
110 static struct sock_filter lldpd_filter_edp_f[] = { LLDPD_FILTER_EDP_F };
111 #endif /* ENABLE_EDP */
112 #define LLDPD_FILTER_ANY_F \
113 { 0x28, 0, 0, 0x0000000c }, \
114 { 0x15, 0, 4, 0x000088cc }, \
115 { 0x20, 0, 0, 0x00000002 }, \
116 { 0x15, 0, 2, 0xc200000e }, \
117 { 0x28, 0, 0, 0x00000000 }, \
118 { 0x15, 11, 12, 0x00000180 }, \
119 { 0x20, 0, 0, 0x00000002 }, \
120 { 0x15, 0, 2, 0x2b000000 }, \
121 { 0x28, 0, 0, 0x00000000 }, \
122 { 0x15, 7, 8, 0x000000e0 }, \
123 { 0x15, 1, 0, 0x0ccccccc }, \
124 { 0x15, 0, 2, 0x81000100 }, \
125 { 0x28, 0, 0, 0x00000000 }, \
126 { 0x15, 3, 4, 0x00000100 }, \
127 { 0x15, 0, 3, 0x52cccccc }, \
128 { 0x28, 0, 0, 0x00000000 }, \
129 { 0x15, 0, 1, 0x000001e0 }, \
130 { 0x6, 0, 0, 0x0000ffff }, \
131 { 0x6, 0, 0, 0x00000000 },
132 static struct sock_filter lldpd_filter_any_f[] = { LLDPD_FILTER_ANY_F };
133
134 static struct protocol protos[] =
135 {
136 { LLDPD_MODE_LLDP, 1, "LLDP", ' ', lldp_send, lldp_decode, NULL,
137 LLDP_MULTICAST_ADDR, lldpd_filter_lldp_f, sizeof(lldpd_filter_lldp_f) },
138 #ifdef ENABLE_CDP
139 { LLDPD_MODE_CDPV1, 0, "CDPv1", 'c', cdpv1_send, cdp_decode, cdpv1_guess,
140 CDP_MULTICAST_ADDR, lldpd_filter_cdp_f, sizeof(lldpd_filter_cdp_f) },
141 { LLDPD_MODE_CDPV2, 0, "CDPv2", 'c', cdpv2_send, cdp_decode, cdpv2_guess,
142 CDP_MULTICAST_ADDR, lldpd_filter_cdp_f, sizeof(lldpd_filter_cdp_f) },
143 #endif
144 #ifdef ENABLE_SONMP
145 { LLDPD_MODE_SONMP, 0, "SONMP", 's', sonmp_send, sonmp_decode, NULL,
146 SONMP_MULTICAST_ADDR, lldpd_filter_sonmp_f, sizeof(lldpd_filter_sonmp_f) },
147 #endif
148 #ifdef ENABLE_EDP
149 { LLDPD_MODE_EDP, 0, "EDP", 'e', edp_send, edp_decode, NULL,
150 EDP_MULTICAST_ADDR, lldpd_filter_edp_f, sizeof(lldpd_filter_edp_f) },
151 #endif
152 #ifdef ENABLE_FDP
153 { LLDPD_MODE_FDP, 0, "FDP", 'f', fdp_send, cdp_decode, NULL,
154 FDP_MULTICAST_ADDR, lldpd_filter_fdp_f, sizeof(lldpd_filter_fdp_f) },
155 #endif
156 { 0, 0, "any", ' ', NULL, NULL, NULL,
157 {0,0,0,0,0,0}, lldpd_filter_any_f, sizeof(lldpd_filter_any_f) }
158 };
159
160 static int lldpd_iface_switchto(struct lldpd *, short int,
161 struct lldpd_hardware *);
162 static
163 struct lldpd_hardware *lldpd_port_add(struct lldpd *, struct ifaddrs *);
164 static void lldpd_loop(struct lldpd *);
165 static void lldpd_shutdown(int);
166 static void lldpd_exit();
167 static void lldpd_send_all(struct lldpd *);
168 static void lldpd_recv_all(struct lldpd *);
169 static int lldpd_guess_type(struct lldpd *, char *, int);
170 static void lldpd_decode(struct lldpd *, char *, int,
171 struct lldpd_hardware *, int);
172 #ifdef ENABLE_LLDPMED
173 static void lldpd_med(struct lldpd_chassis *);
174 #endif
175
176 static char **saved_argv;
177
178 static void
179 usage(void)
180 {
181 extern const char *__progname;
182 fprintf(stderr, "usage: %s [options]\n", __progname);
183 fprintf(stderr, "see manual page lldpd(8) for more information\n");
184 exit(1);
185 }
186
187 static void
188 lldpd_iface_init_mtu(struct lldpd *global, struct lldpd_hardware *hardware)
189 {
190 struct ifreq ifr;
191
192 /* get MTU */
193 memset(&ifr, 0, sizeof(ifr));
194 strlcpy(ifr.ifr_name, hardware->h_ifname, sizeof(ifr.ifr_name));
195 if (ioctl(global->g_sock, SIOCGIFMTU, (char*)&ifr) == -1) {
196 LLOG_WARN("unable to get MTU of %s, using 1500", hardware->h_ifname);
197 hardware->h_mtu = 1500;
198 } else
199 hardware->h_mtu = hardware->h_lport.p_mfs = ifr.ifr_mtu;
200 }
201
202 static int
203 lldpd_iface_init_vlan(struct lldpd *global, struct lldpd_vif *vif)
204 {
205 int status;
206 short int filter;
207
208 lldpd_iface_init_mtu(global, (struct lldpd_hardware*)vif);
209 status = priv_iface_init((struct lldpd_hardware*)vif, -1);
210 if (status != 0)
211 return status;
212
213 if (global->g_multi)
214 filter = LLDPD_MODE_ANY;
215 else
216 filter = LLDPD_MODE_LLDP;
217
218 if (lldpd_iface_switchto(global, filter,
219 (struct lldpd_hardware*)vif) == -1) {
220 LLOG_WARNX("unable to apply filter");
221 return ENETDOWN;
222 }
223
224 lldpd_iface_multicast(global, vif->vif_ifname, 0);
225
226 LLOG_DEBUG("vlan interface %s initialized (fd=%d)", vif->vif_ifname,
227 vif->vif_raw);
228 return 0;
229 }
230
231 static int
232 lldpd_iface_init(struct lldpd *global, struct lldpd_hardware *hardware)
233 {
234 int master; /* Bond device */
235 char if_bond[IFNAMSIZ];
236 int status;
237 short int filter;
238
239 lldpd_iface_init_mtu(global, hardware);
240 status = priv_iface_init(hardware, -1);
241 if (status != 0)
242 return status;
243
244 if ((master = iface_is_enslaved(global, hardware->h_ifname)) != -1) {
245 /* With bonding device, we need to listen on the bond ! */
246 if (if_indextoname(master, if_bond) == NULL) {
247 LLOG_WARN("unable to get index for interface %d (master of %s)",
248 master, hardware->h_ifname);
249 return ENETDOWN;
250 }
251 hardware->h_raw_real = hardware->h_raw;
252 hardware->h_master = master;
253 hardware->h_raw = -1;
254 status = priv_iface_init(hardware, master);
255 if (status != 0) {
256 close(hardware->h_raw_real);
257 if (hardware->h_raw != -1)
258 close(hardware->h_raw);
259 return status;
260 }
261 }
262
263 if (global->g_multi)
264 filter = LLDPD_MODE_ANY;
265 else
266 filter = LLDPD_MODE_LLDP;
267 if (lldpd_iface_switchto(global, filter, hardware) == -1) {
268 LLOG_WARNX("unable to apply filter");
269 return ENETDOWN;
270 }
271
272 if (master != -1)
273 lldpd_iface_multicast(global, if_bond, 0);
274 lldpd_iface_multicast(global, hardware->h_ifname, 0);
275
276 LLOG_DEBUG("interface %s initialized (fd=%d)", hardware->h_ifname,
277 hardware->h_raw);
278 return 0;
279 }
280
281 static void
282 lldpd_iface_multicast(struct lldpd *global, const char *name, int remove)
283 {
284 int i, rc;
285
286 for (i=0; global->g_protocols[i].mode != 0; i++) {
287 if (!global->g_protocols[i].enabled) continue;
288 if ((rc = priv_iface_multicast(name,
289 global->g_protocols[i].mac, !remove)) != 0) {
290 errno = rc;
291 if (errno != ENOENT)
292 LLOG_INFO("unable to %s %s address to multicast filter for %s",
293 (remove)?"delete":"add",
294 global->g_protocols[i].name,
295 name);
296 }
297 }
298 }
299
300 static int
301 lldpd_iface_close(struct lldpd *global, struct lldpd_hardware *hardware)
302 {
303 char listen[IFNAMSIZ];
304
305 close(hardware->h_raw);
306 hardware->h_raw = -1;
307
308 if (hardware->h_raw_real > 0) {
309 if (if_indextoname(hardware->h_master, listen) == NULL) {
310 LLOG_WARN("unable to get index for interface %d",
311 hardware->h_master);
312 strlcpy(listen, hardware->h_ifname, sizeof(listen));
313 }
314 close(hardware->h_raw_real);
315 lldpd_iface_multicast(global, listen, 1);
316 }
317 memcpy(listen, hardware->h_ifname, IFNAMSIZ);
318 lldpd_iface_multicast(global, listen, 1);
319
320 hardware->h_raw_real = -1;
321 return 0;
322 }
323
324 static int
325 lldpd_iface_switchto(struct lldpd *cfg, short int filter, struct lldpd_hardware *hardware)
326 {
327 struct sock_fprog prog;
328 int i;
329
330 memset(&prog, 0, sizeof(prog));
331 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
332 if (!cfg->g_protocols[i].enabled) continue;
333 if (cfg->g_protocols[i].mode == filter)
334 break;
335 }
336 prog.filter = cfg->g_protocols[i].filter;
337 prog.len = cfg->g_protocols[i].filterlen / sizeof(struct sock_filter);
338 if (setsockopt(hardware->h_raw, SOL_SOCKET, SO_ATTACH_FILTER,
339 &prog, sizeof(prog)) < 0) {
340 LLOG_WARN("unable to change filter for %s", hardware->h_ifname);
341 return -1;
342 }
343 if ((hardware->h_raw_real > 0) &&
344 (setsockopt(hardware->h_raw_real, SOL_SOCKET, SO_ATTACH_FILTER,
345 &prog, sizeof(prog)) < 0)) {
346 LLOG_WARN("unable to change filter for real device %s", hardware->h_ifname);
347 return -1;
348 }
349 return 0;
350 }
351
352 #ifdef ENABLE_DOT1
353 void
354 lldpd_vlan_cleanup(struct lldpd_port *port)
355 {
356 struct lldpd_vlan *vlan, *vlan_next;
357 for (vlan = TAILQ_FIRST(&port->p_vlans);
358 vlan != NULL;
359 vlan = vlan_next) {
360 free(vlan->v_name);
361 vlan_next = TAILQ_NEXT(vlan, v_entries);
362 TAILQ_REMOVE(&port->p_vlans, vlan, v_entries);
363 free(vlan);
364 }
365 }
366 #endif
367
368 /* If `all' is true, clear all information, including information that
369 are not refreshed periodically. If `all' is true, also free the
370 port. */
371 void
372 lldpd_port_cleanup(struct lldpd_port *port, int all)
373 {
374 #ifdef ENABLE_LLDPMED
375 int i;
376 if (all)
377 for (i=0; i < LLDPMED_LOCFORMAT_LAST; i++)
378 free(port->p_med_location[i].data);
379 #endif
380 #ifdef ENABLE_DOT1
381 lldpd_vlan_cleanup(port);
382 #endif
383 free(port->p_id);
384 free(port->p_descr);
385 if (all)
386 free(port);
387 }
388
389 void
390 lldpd_chassis_cleanup(struct lldpd_chassis *chassis)
391 {
392 #ifdef ENABLE_LLDPMED
393 free(chassis->c_med_hw);
394 free(chassis->c_med_sw);
395 free(chassis->c_med_fw);
396 free(chassis->c_med_sn);
397 free(chassis->c_med_manuf);
398 free(chassis->c_med_model);
399 free(chassis->c_med_asset);
400 #endif
401 free(chassis->c_id);
402 free(chassis->c_name);
403 free(chassis->c_descr);
404 free(chassis);
405 }
406
407 void
408 lldpd_remote_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware, int reset)
409 {
410 if (hardware->h_rport != NULL) {
411 lldpd_port_cleanup(hardware->h_rport, 1);
412 hardware->h_rport = NULL;
413 }
414 if (hardware->h_rchassis != NULL) {
415 lldpd_chassis_cleanup(hardware->h_rchassis);
416 hardware->h_rchassis = NULL;
417 }
418 hardware->h_rlastchange = hardware->h_rlastupdate = 0;
419 free(hardware->h_rlastframe);
420 hardware->h_rlastframe = NULL;
421 if (reset && cfg->g_multi) {
422 hardware->h_mode = LLDPD_MODE_ANY;
423 memset(hardware->h_proto_macs, 0, ETH_ALEN*(cfg->g_multi+1));
424 hardware->h_start_probe = 0;
425 lldpd_iface_switchto(cfg, LLDPD_MODE_ANY, hardware);
426 }
427 }
428
429 void
430 lldpd_hardware_cleanup(struct lldpd_hardware *hardware)
431 {
432 lldpd_port_cleanup(&hardware->h_lport, 1);
433 free(hardware->h_proto_macs);
434 free(hardware->h_llastframe);
435 free(hardware);
436 }
437
438 void
439 lldpd_cleanup(struct lldpd *cfg)
440 {
441 struct lldpd_hardware *hardware, *hardware_next;
442 struct lldpd_vif *vif, *vif_next;
443
444 for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
445 hardware = hardware_next) {
446 hardware_next = TAILQ_NEXT(hardware, h_entries);
447 if (hardware->h_flags == 0) {
448 TAILQ_REMOVE(&cfg->g_hardware, hardware, h_entries);
449 lldpd_iface_close(cfg, hardware);
450 lldpd_remote_cleanup(cfg, hardware, 0);
451 lldpd_hardware_cleanup(hardware);
452 } else if (hardware->h_rchassis != NULL) {
453 if (time(NULL) - hardware->h_rlastupdate >
454 hardware->h_rchassis->c_ttl) {
455 lldpd_remote_cleanup(cfg, hardware, 1);
456 hardware->h_rx_ageout_cnt++;
457 }
458 }
459 }
460 for (vif = TAILQ_FIRST(&cfg->g_vif); vif != NULL;
461 vif = vif_next) {
462 vif_next = TAILQ_NEXT(vif, vif_entries);
463 if (vif->vif_flags == 0) {
464 TAILQ_REMOVE(&cfg->g_vif, vif, vif_entries);
465 lldpd_iface_close(cfg, (struct lldpd_hardware*)vif);
466 free(vif);
467 }
468 }
469 }
470
471 static struct lldpd_vif *
472 lldpd_port_add_vlan(struct lldpd *cfg, struct ifaddrs *ifa)
473 {
474 struct lldpd_vif *vif;
475 struct lldpd_hardware *hardware;
476 struct vlan_ioctl_args ifv;
477
478 TAILQ_FOREACH(vif, &cfg->g_vif, vif_entries) {
479 if (strcmp(vif->vif_ifname, ifa->ifa_name) == 0)
480 break;
481 }
482
483 if (vif == NULL) {
484 if ((vif = (struct lldpd_vif *)
485 calloc(1, sizeof(struct lldpd_vif))) == NULL)
486 return NULL;
487 vif->vif_raw = -1;
488 vif->vif_raw_real = -1;
489 }
490 strlcpy(vif->vif_ifname, ifa->ifa_name, sizeof(vif->vif_ifname));
491 vif->vif_flags = ifa->ifa_flags;
492
493 if (vif->vif_raw == -1) {
494
495 if (lldpd_iface_init_vlan(cfg, vif) != 0) {
496 free(vif);
497 return NULL;
498 }
499
500 /* Find the real interface */
501 vif->vif_real = NULL;
502 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
503 memset(&ifv, 0, sizeof(ifv));
504 ifv.cmd = GET_VLAN_REALDEV_NAME_CMD;
505 strlcpy(ifv.device1, ifa->ifa_name, sizeof(ifv.device1));
506 if ((ioctl(cfg->g_sock, SIOCGIFVLAN, &ifv) >= 0) &&
507 (strncmp(hardware->h_ifname,
508 ifv.u.device2,
509 sizeof(ifv.u.device2)) == 0))
510 vif->vif_real = hardware;
511 }
512 if (vif->vif_real == NULL) {
513 LLOG_WARNX("unable to find real interface for %s",
514 ifa->ifa_name);
515 free(vif);
516 return NULL;
517 }
518
519 TAILQ_INSERT_TAIL(&cfg->g_vif, vif, vif_entries);
520 }
521
522 return vif;
523 }
524
525 static struct lldpd_hardware *
526 lldpd_port_add(struct lldpd *cfg, struct ifaddrs *ifa)
527 {
528 #if defined (ENABLE_DOT1) || defined (ENABLE_DOT3)
529 struct ifaddrs *oifap, *oifa;
530 #endif
531 struct lldpd_hardware *hardware;
532 struct lldpd_port *port;
533 #ifdef ENABLE_DOT1
534 struct lldpd_vlan *vlan;
535 struct vlan_ioctl_args ifv;
536 #endif
537 #ifdef ENABLE_DOT3
538 struct ethtool_cmd ethc;
539 #endif
540 u_int8_t *lladdr;
541
542 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
543 if (strcmp(hardware->h_ifname, ifa->ifa_name) == 0)
544 break;
545 }
546
547 if (hardware == NULL) {
548 if ((hardware = (struct lldpd_hardware *)
549 calloc(1, sizeof(struct lldpd_hardware))) == NULL)
550 return (NULL);
551 hardware->h_raw = -1;
552 hardware->h_raw_real = -1;
553 hardware->h_start_probe = 0;
554 hardware->h_proto_macs = (u_int8_t*)calloc(cfg->g_multi+1, ETH_ALEN);
555 #ifdef ENABLE_LLDPMED
556 hardware->h_lport.p_med_cap_enabled = LLDPMED_CAP_CAP;
557 if (!cfg->g_noinventory)
558 hardware->h_lport.p_med_cap_enabled |= LLDPMED_CAP_IV;
559 #endif
560 #ifdef ENABLE_DOT1
561 TAILQ_INIT(&hardware->h_lport.p_vlans);
562 } else {
563 lldpd_port_cleanup(&hardware->h_lport, 0);
564 #endif
565 }
566
567 port = &hardware->h_lport;
568 hardware->h_flags = ifa->ifa_flags;
569
570 strlcpy(hardware->h_ifname, ifa->ifa_name, sizeof(hardware->h_ifname));
571 lladdr = (u_int8_t*)(((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr);
572 memcpy(&hardware->h_lladdr, lladdr, sizeof(hardware->h_lladdr));
573 iface_get_permanent_mac(cfg, hardware);
574 port->p_id_subtype = LLDP_PORTID_SUBTYPE_LLADDR;
575 if ((port->p_id = calloc(1, sizeof(hardware->h_lladdr))) == NULL)
576 fatal(NULL);
577 memcpy(port->p_id, hardware->h_lladdr, sizeof(hardware->h_lladdr));
578 port->p_id_len = sizeof(hardware->h_lladdr);
579 port->p_descr = strdup(hardware->h_ifname);
580
581 if (cfg->g_lchassis.c_id == NULL) {
582 /* Use the first port's l2 addr as the chassis ID */
583 if ((cfg->g_lchassis.c_id = malloc(sizeof(hardware->h_lladdr))) == NULL)
584 fatal(NULL);
585 cfg->g_lchassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
586 cfg->g_lchassis.c_id_len = sizeof(hardware->h_lladdr);
587 memcpy(cfg->g_lchassis.c_id,
588 hardware->h_lladdr, sizeof(hardware->h_lladdr));
589 }
590
591 /* Get VLANS and aggregation status */
592 #if defined (ENABLE_DOT3) || defined (ENABLE_DOT1)
593 if (getifaddrs(&oifap) != 0)
594 fatal("lldpd_port_add: failed to get interface list");
595 for (oifa = oifap; oifa != NULL; oifa = oifa->ifa_next) {
596 #ifdef ENABLE_DOT1
597 /* Check if we already have checked this one */
598 int skip = 0;
599 TAILQ_FOREACH(vlan, &port->p_vlans, v_entries) {
600 if (strcmp(vlan->v_name, oifa->ifa_name) == 0) {
601 skip = 1;
602 break;
603 }
604 }
605 if (skip) continue;
606 #endif
607
608 /* Aggregation check */
609 #ifdef ENABLE_DOT3
610 if (iface_is_bond_slave(cfg, hardware->h_ifname, oifa->ifa_name, NULL))
611 port->p_aggregid = if_nametoindex(oifa->ifa_name);
612 #endif
613
614 #ifdef ENABLE_DOT1
615 /* VLAN check */
616 memset(&ifv, 0, sizeof(ifv));
617 ifv.cmd = GET_VLAN_REALDEV_NAME_CMD;
618 strlcpy(ifv.device1, oifa->ifa_name, sizeof(ifv.device1));
619 if ((ioctl(cfg->g_sock, SIOCGIFVLAN, &ifv) >= 0) &&
620 ((iface_is_bond_slave(cfg, hardware->h_ifname, ifv.u.device2, NULL)) ||
621 (iface_is_bridged_to(cfg, hardware->h_ifname, ifv.u.device2)) ||
622 (strncmp(hardware->h_ifname, ifv.u.device2, sizeof(ifv.u.device2)) == 0))) {
623 if ((vlan = (struct lldpd_vlan *)
624 calloc(1, sizeof(struct lldpd_vlan))) == NULL)
625 continue;
626 if ((vlan->v_name = strdup(oifa->ifa_name)) == NULL) {
627 free(vlan);
628 continue;
629 }
630 memset(&ifv, 0, sizeof(ifv));
631 ifv.cmd = GET_VLAN_VID_CMD;
632 strlcpy(ifv.device1, oifa->ifa_name, sizeof(ifv.device1));
633 if (ioctl(cfg->g_sock, SIOCGIFVLAN, &ifv) < 0) {
634 /* Dunno what happened */
635 free(vlan->v_name);
636 free(vlan);
637 } else {
638 vlan->v_vid = ifv.u.VID;
639 TAILQ_INSERT_TAIL(&port->p_vlans, vlan, v_entries);
640 }
641 }
642 #endif
643 }
644 freeifaddrs(oifap);
645 #endif
646
647 #ifdef ENABLE_DOT3
648 /* MAC/PHY */
649 if (priv_ethtool(hardware->h_ifname, &ethc) == 0) {
650 int j;
651 int advertised_ethtool_to_rfc3636[][2] = {
652 {ADVERTISED_10baseT_Half, LLDP_DOT3_LINK_AUTONEG_10BASE_T},
653 {ADVERTISED_10baseT_Full, LLDP_DOT3_LINK_AUTONEG_10BASET_FD},
654 {ADVERTISED_100baseT_Half, LLDP_DOT3_LINK_AUTONEG_100BASE_TX},
655 {ADVERTISED_100baseT_Full, LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD},
656 {ADVERTISED_1000baseT_Half, LLDP_DOT3_LINK_AUTONEG_1000BASE_T},
657 {ADVERTISED_1000baseT_Full, LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD},
658 {ADVERTISED_10000baseT_Full, LLDP_DOT3_LINK_AUTONEG_OTHER},
659 {ADVERTISED_Pause, LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE},
660 {ADVERTISED_Asym_Pause, LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE},
661 {ADVERTISED_2500baseX_Full, LLDP_DOT3_LINK_AUTONEG_OTHER},
662 {0,0}};
663
664 port->p_autoneg_support = (ethc.supported & SUPPORTED_Autoneg) ? 1 : 0;
665 port->p_autoneg_enabled = (ethc.autoneg == AUTONEG_DISABLE) ? 0 : 1;
666 for (j=0; advertised_ethtool_to_rfc3636[j][0]; j++) {
667 if (ethc.advertising & advertised_ethtool_to_rfc3636[j][0])
668 port->p_autoneg_advertised |= advertised_ethtool_to_rfc3636[j][1];
669 }
670 switch (ethc.speed) {
671 case SPEED_10:
672 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
673 LLDP_DOT3_MAU_10BASETFD : LLDP_DOT3_MAU_10BASETHD;
674 if (ethc.port == PORT_BNC) port->p_mau_type = LLDP_DOT3_MAU_10BASE2;
675 if (ethc.port == PORT_FIBRE)
676 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
677 LLDP_DOT3_MAU_10BASEFLDF : LLDP_DOT3_MAU_10BASEFLHD;
678 break;
679 case SPEED_100:
680 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
681 LLDP_DOT3_MAU_100BASETXFD : LLDP_DOT3_MAU_100BASETXHD;
682 if (ethc.port == PORT_BNC)
683 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
684 LLDP_DOT3_MAU_100BASET2DF : LLDP_DOT3_MAU_100BASET2HD;
685 if (ethc.port == PORT_FIBRE)
686 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
687 LLDP_DOT3_MAU_100BASEFXFD : LLDP_DOT3_MAU_100BASEFXHD;
688 break;
689 case SPEED_1000:
690 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
691 LLDP_DOT3_MAU_1000BASETFD : LLDP_DOT3_MAU_1000BASETHD;
692 if (ethc.port == PORT_FIBRE)
693 port->p_mau_type = (ethc.duplex == DUPLEX_FULL) ? \
694 LLDP_DOT3_MAU_1000BASEXFD : LLDP_DOT3_MAU_1000BASEXHD;
695 break;
696 case SPEED_10000:
697 port->p_mau_type = (ethc.port == PORT_FIBRE) ? \
698 LLDP_DOT3_MAU_10GIGBASEX : LLDP_DOT3_MAU_10GIGBASER;
699 break;
700 }
701 if (ethc.port == PORT_AUI) port->p_mau_type = LLDP_DOT3_MAU_AUI;
702 } else
703 LLOG_DEBUG("unable to get eth info for %s", hardware->h_ifname);
704 #endif
705
706 if (!INTERFACE_OPENED(hardware)) {
707
708 if (lldpd_iface_init(cfg, hardware) != 0) {
709 LLOG_WARN("unable to initialize %s", hardware->h_ifname);
710 lldpd_hardware_cleanup(hardware);
711 return (NULL);
712 }
713
714 TAILQ_INSERT_TAIL(&cfg->g_hardware, hardware, h_entries);
715 }
716
717 return (hardware);
718 }
719
720 static int
721 lldpd_guess_type(struct lldpd *cfg, char *frame, int s)
722 {
723 int i;
724 if (s < ETH_ALEN)
725 return -1;
726 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
727 if (!cfg->g_protocols[i].enabled)
728 continue;
729 if (cfg->g_protocols[i].guess == NULL) {
730 if (memcmp(frame, cfg->g_protocols[i].mac, ETH_ALEN) == 0)
731 return cfg->g_protocols[i].mode;
732 } else {
733 if (cfg->g_protocols[i].guess(frame, s))
734 return cfg->g_protocols[i].mode;
735 }
736 }
737 return -1;
738 }
739
740 static void
741 lldpd_decode(struct lldpd *cfg, char *frame, int s,
742 struct lldpd_hardware *hardware, int bond)
743 {
744 int result = 0, i, j, candidatetonull;
745 u_int8_t nullmac[ETH_ALEN] = {0,0,0,0,0,0};
746 u_int8_t broadcastmac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
747 struct lldpd_chassis *chassis;
748 struct lldpd_port *port;
749 struct lldpd_hardware *ohardware, *firstnull = NULL, *older = NULL;
750 int guess = LLDPD_MODE_LLDP;
751
752 /* Discard VLAN frames */
753 if ((s >= sizeof(struct ethhdr)) &&
754 (((struct ethhdr*)frame)->h_proto == htons(ETHERTYPE_VLAN)))
755 return;
756
757 if ((hardware->h_rlastframe != NULL) &&
758 (hardware->h_rlastframe->size == s) &&
759 (memcmp(hardware->h_rlastframe->frame, frame, s) == 0)) {
760 /* Already received the same frame */
761 hardware->h_rlastupdate = time(NULL);
762 return;
763 }
764
765 if (cfg->g_multi) {
766 if (hardware->h_mode == LLDPD_MODE_ANY)
767 guess = lldpd_guess_type(cfg, frame, s);
768 else
769 guess = hardware->h_mode;
770 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
771 if (!cfg->g_protocols[i].enabled)
772 continue;
773 if (cfg->g_protocols[i].mode == guess) {
774 if ((result = cfg->g_protocols[i].decode(cfg, frame,
775 s, hardware, &chassis, &port)) == -1)
776 return;
777 break;
778 }
779 }
780 if (cfg->g_protocols[i].mode == 0) {
781 LLOG_INFO("unable to guess frame type");
782 return;
783 }
784 } else if (cfg->g_protocols[0].decode(cfg, frame, s, hardware,
785 &chassis, &port) == -1)
786 /* Nothing has been received */
787 return;
788
789 if (bond) {
790 /* Eh, wait ! The frame we just received was for a bonding
791 * device. We need to attach it to a real device. What is the
792 * best candidate? Drum rolling... */
793 TAILQ_FOREACH(ohardware, &cfg->g_hardware, h_entries) {
794 if (ohardware->h_master == hardware->h_master) {
795 /* Same bond */
796 if (ohardware->h_rchassis == NULL) {
797 candidatetonull = 1;
798 if (cfg->g_multi &&
799 (ohardware->h_mode == LLDPD_MODE_ANY)) {
800 for (i=j=0;
801 cfg->g_protocols[i].mode != 0;
802 i++) {
803 if (!cfg->g_protocols[i].enabled)
804 continue;
805 if ((cfg->g_protocols[i].mode == guess) &&
806 (memcmp(frame + ETH_ALEN,
807 ohardware->h_proto_macs + ETH_ALEN*j,
808 ETH_ALEN) == 0)) {
809 hardware = ohardware;
810 bond = 0;
811 break;
812 }
813 j++;
814 }
815 if (!bond) break;
816 if (firstnull != NULL) {
817 for (i=j=0;
818 cfg->g_protocols[i].mode != 0;
819 i++) {
820 if (!cfg->g_protocols[i].enabled)
821 continue;
822 if ((cfg->g_protocols[i].mode == guess) &&
823 (memcmp(nullmac,
824 ohardware->h_proto_macs +
825 ETH_ALEN*j,
826 ETH_ALEN) != 0)) {
827 /* We need to
828 * find a better
829 * candidate */
830 candidatetonull = 0;
831 break;
832 }
833 j++;
834 }
835 }
836 }
837 /* Ok, this is the first candidate if we
838 * don't find a matching chassis/port */
839 if (candidatetonull) firstnull = ohardware;
840 continue;
841 }
842 if ((older == NULL) ||
843 (older->h_rlastupdate > ohardware->h_rlastupdate))
844 /* If there is no matching chassis/port
845 * and no free hardware, we will use
846 * this one. */
847 older = ohardware;
848 if ((chassis->c_id_subtype !=
849 ohardware->h_rchassis->c_id_subtype) ||
850 (chassis->c_id_len != ohardware->h_rchassis->c_id_len) ||
851 (memcmp(chassis->c_id, ohardware->h_rchassis->c_id,
852 chassis->c_id_len) != 0) ||
853 (port->p_id_subtype != ohardware->h_rport->p_id_subtype) ||
854 (port->p_id_len != ohardware->h_rport->p_id_len) ||
855 (memcmp(port->p_id, ohardware->h_rport->p_id,
856 port->p_id_len) != 0))
857 continue;
858 /* We got a match! */
859 hardware = ohardware; /* We switch hardware */
860 bond = 0;
861 break;
862 }
863 }
864 if (bond) {
865 /* No match found */
866 if (firstnull != NULL)
867 hardware = firstnull;
868 else hardware = older;
869 }
870 }
871
872 if (cfg->g_multi &&
873 (hardware->h_mode == LLDPD_MODE_ANY)) {
874 u_int8_t *mac;
875 char *modename;
876 int filter;
877
878 for (i=j=0; cfg->g_protocols[i].mode != 0; i++) {
879 if (!cfg->g_protocols[i].enabled)
880 continue;
881 if (cfg->g_protocols[i].mode == guess) {
882 mac = hardware->h_proto_macs + ETH_ALEN*j;
883 modename = cfg->g_protocols[i].name;
884 filter = cfg->g_protocols[i].mode;
885 break;
886 }
887 j++;
888 }
889 if (cfg->g_protocols[i].mode == 0) {
890 LLOG_WARNX("should not be there");
891 goto cleanup;
892 }
893
894 if (hardware->h_start_probe == 0)
895 hardware->h_start_probe = time(NULL) - 1;
896 /* Handle switching respecting probe time */
897 if ((memcmp(mac, frame + ETH_ALEN, ETH_ALEN) == 0) &&
898 ((time(NULL) - hardware->h_start_probe) > cfg->g_probe_time) &&
899 /* Don't switch to this protocol if not LLDP and LLDP is
900 * a valid candidate */
901 ((filter == LLDPD_MODE_LLDP) ||
902 (memcmp(hardware->h_proto_macs,
903 broadcastmac, ETH_ALEN) == 0) ||
904 (memcmp(hardware->h_proto_macs,
905 nullmac, ETH_ALEN) == 0))) {
906 LLOG_INFO("switching to %s on port %s", modename,
907 hardware->h_ifname);
908 hardware->h_mode = guess;
909 lldpd_iface_switchto(cfg, filter, hardware);
910 } else {
911 /* Wait twice probe time to be able to receive packets of all kind */
912 if ((time(NULL) - hardware->h_start_probe) > cfg->g_probe_time * 2) {
913 LLOG_DEBUG("probe expired on %s, retry", hardware->h_ifname);
914 hardware->h_start_probe = 0;
915 memset(hardware->h_proto_macs, 0, ETH_ALEN*(cfg->g_multi+1));
916 goto cleanup;
917 }
918 if (memcmp(mac, broadcastmac, ETH_ALEN) == 0)
919 goto cleanup;
920 LLOG_INFO("received a %s frame on %s but wait for %d sec",
921 modename, hardware->h_ifname, cfg->g_probe_time - time(NULL) +
922 hardware->h_start_probe);
923 if (memcmp(mac, frame + ETH_ALEN, ETH_ALEN) == 0)
924 goto cleanup;
925 if (memcmp(mac, nullmac, ETH_ALEN) == 0) {
926 memcpy(mac, frame + ETH_ALEN, ETH_ALEN);
927 goto cleanup;
928 }
929 LLOG_INFO("several MAC for %s on %s, discarding %s for this interface",
930 modename, hardware->h_ifname, modename);
931 memcpy(mac, broadcastmac, ETH_ALEN);
932 goto cleanup;
933 }
934 }
935
936 result = 0;
937 if ((hardware->h_rchassis == NULL) ||
938 (chassis->c_id_subtype != hardware->h_rchassis->c_id_subtype) ||
939 (chassis->c_id_len != hardware->h_rchassis->c_id_len) ||
940 (memcmp(chassis->c_id, hardware->h_rchassis->c_id,
941 chassis->c_id_len) != 0))
942 result = 1;
943
944 /* We have our new frame */
945 lldpd_remote_cleanup(cfg, hardware, 0);
946 hardware->h_rport = port;
947 hardware->h_rchassis = chassis;
948 hardware->h_rlastchange = hardware->h_rlastupdate = time(NULL);
949
950 /* We remember this frame */
951 free(hardware->h_rlastframe);
952 if ((hardware->h_rlastframe = (struct lldpd_frame *)malloc(s +
953 sizeof(int))) != NULL) {
954 hardware->h_rlastframe->size = s;
955 memcpy(hardware->h_rlastframe->frame, frame, s);
956 }
957
958 if (result) {
959 /* This is a new remote system */
960 LLOG_DEBUG("we discovered a new remote system on %s",
961 hardware->h_ifname);
962 /* Do we already know this remote system? */
963 TAILQ_FOREACH(ohardware, &cfg->g_hardware, h_entries) {
964 if ((ohardware->h_ifname != hardware->h_ifname) &&
965 (ohardware->h_rchassis != NULL) &&
966 (ohardware->h_rchassis->c_id_subtype ==
967 chassis->c_id_subtype) &&
968 (ohardware->h_rchassis->c_id_len ==
969 chassis->c_id_len) &&
970 (memcmp(ohardware->h_rchassis->c_id,
971 chassis->c_id, chassis->c_id_len) == 0)) {
972 LLOG_DEBUG("but it was already on %s",
973 ohardware->h_ifname);
974 hardware->h_rid = ohardware->h_rid;
975 return;
976 }
977 }
978 hardware->h_rid = ++cfg->g_lastrid;
979 }
980 return;
981
982 cleanup:
983 lldpd_chassis_cleanup(chassis);
984 lldpd_port_cleanup(port, 1);
985 return;
986 }
987
988 static void
989 lldpd_recv_all(struct lldpd *cfg)
990 {
991 struct lldpd_hardware *hardware;
992 struct lldpd_vif *vif;
993 struct lldpd_client *client, *client_next;
994 fd_set rfds;
995 struct timeval tv;
996 struct sockaddr_ll from;
997 socklen_t fromlen;
998 int onreal;
999 #ifdef USE_SNMP
1000 int fakeblock = 0;
1001 struct timeval *tvp = &tv;
1002 #endif
1003 int rc, nfds, n, bond;
1004 char *buffer;
1005
1006 do {
1007 tv.tv_sec = cfg->g_delay - (time(NULL) - cfg->g_lastsent);
1008 if (tv.tv_sec < 0)
1009 tv.tv_sec = LLDPD_TX_DELAY;
1010 if (tv.tv_sec >= cfg->g_delay)
1011 tv.tv_sec = cfg->g_delay;
1012 tv.tv_usec = 0;
1013
1014 FD_ZERO(&rfds);
1015 nfds = -1;
1016
1017 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
1018 /* Ignore if interface is down */
1019 if (((hardware->h_flags & IFF_UP) == 0) ||
1020 ((hardware->h_flags & IFF_RUNNING) == 0))
1021 continue;
1022 FD_SET(hardware->h_raw, &rfds);
1023 if (nfds < hardware->h_raw)
1024 nfds = hardware->h_raw;
1025 /* Listen to real interface too. In 2.6.27, we can
1026 * receive packets if this is the slave interface. */
1027 if (hardware->h_raw_real > 0) {
1028 FD_SET(hardware->h_raw_real, &rfds);
1029 if (nfds < hardware->h_raw_real)
1030 nfds = hardware->h_raw_real;
1031 }
1032 }
1033 TAILQ_FOREACH(vif, &cfg->g_vif, vif_entries) {
1034 if (((vif->vif_flags & IFF_UP) == 0) ||
1035 ((vif->vif_flags & IFF_RUNNING) == 0))
1036 continue;
1037 FD_SET(vif->vif_raw, &rfds);
1038 if (nfds < vif->vif_raw)
1039 nfds = vif->vif_raw;
1040 }
1041 TAILQ_FOREACH(client, &cfg->g_clients, next) {
1042 FD_SET(client->fd, &rfds);
1043 if (nfds < client->fd)
1044 nfds = client->fd;
1045 }
1046 FD_SET(cfg->g_ctl, &rfds);
1047 if (nfds < cfg->g_ctl)
1048 nfds = cfg->g_ctl;
1049
1050 #ifdef USE_SNMP
1051 if (cfg->g_snmp)
1052 snmp_select_info(&nfds, &rfds, tvp, &fakeblock);
1053 #endif /* USE_SNMP */
1054 if (nfds == -1) {
1055 sleep(cfg->g_delay);
1056 return;
1057 }
1058
1059 rc = select(nfds + 1, &rfds, NULL, NULL, &tv);
1060 if (rc == -1) {
1061 if (errno == EINTR)
1062 continue;
1063 LLOG_WARN("failure on select");
1064 break;
1065 }
1066 #ifdef USE_SNMP
1067 if (cfg->g_snmp) {
1068 if (rc > 0)
1069 snmp_read(&rfds);
1070 else if (rc == 0)
1071 snmp_timeout();
1072 }
1073 #endif /* USE_SNMP */
1074 TAILQ_FOREACH(vif, &cfg->g_vif, vif_entries) {
1075 if (!FD_ISSET(vif->vif_raw, &rfds))
1076 continue;
1077 if ((buffer = (char *)malloc(
1078 vif->vif_mtu)) == NULL) {
1079 LLOG_WARN("failed to alloc reception buffer");
1080 continue;
1081 }
1082 fromlen = sizeof(from);
1083 if ((n = recvfrom(vif->vif_raw,
1084 buffer,
1085 vif->vif_mtu, 0,
1086 (struct sockaddr *)&from,
1087 &fromlen)) == -1) {
1088 LLOG_WARN("error while receiving frame on vlan %s",
1089 vif->vif_ifname);
1090 vif->vif_real->h_rx_discarded_cnt++;
1091 free(buffer);
1092 continue;
1093 }
1094 if (from.sll_pkttype == PACKET_OUTGOING) {
1095 free(buffer);
1096 continue;
1097 }
1098 if (!((cfg->g_multi) &&
1099 (vif->vif_real->h_mode != LLDPD_MODE_ANY) &&
1100 (lldpd_guess_type(cfg, buffer, n) !=
1101 vif->vif_real->h_mode))) {
1102 vif->vif_real->h_rx_cnt++;
1103 lldpd_decode(cfg, buffer, n, vif->vif_real, 0);
1104 }
1105
1106 free(buffer);
1107 }
1108 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
1109 /* We could have received something on _real_
1110 * interface. However, even in this case, this could be
1111 * just an outgoing packet. We will try to handle both
1112 * cases, but maybe not in the same select. */
1113 onreal = ((hardware->h_raw_real > 0) &&
1114 (FD_ISSET(hardware->h_raw_real, &rfds)));
1115 if (onreal || (FD_ISSET(hardware->h_raw, &rfds))) {
1116 if ((buffer = (char *)malloc(
1117 hardware->h_mtu)) == NULL) {
1118 LLOG_WARN("failed to alloc reception buffer");
1119 continue;
1120 }
1121 fromlen = sizeof(from);
1122 if ((n = recvfrom(
1123 onreal?hardware->h_raw_real:hardware->h_raw,
1124 buffer,
1125 hardware->h_mtu, 0,
1126 (struct sockaddr *)&from,
1127 &fromlen)) == -1) {
1128 LLOG_WARN("error while receiving frame on %s",
1129 hardware->h_ifname);
1130 hardware->h_rx_discarded_cnt++;
1131 free(buffer);
1132 continue;
1133 }
1134 if (from.sll_pkttype == PACKET_OUTGOING) {
1135 free(buffer);
1136 continue;
1137 }
1138 bond = 0;
1139 /* If received on real interface, we act like if
1140 * this is not a bond! */
1141 if (!onreal && (hardware->h_raw_real > 0)) {
1142 /* Bonding. Is it for the correct
1143 * physical interface ? */
1144 if (from.sll_ifindex == hardware->h_master) {
1145 /* It seems that we don't know from
1146 which physical interface it comes
1147 (kernel < 2.6.24 ?) */
1148 bond = 1;
1149 } else if (from.sll_ifindex !=
1150 if_nametoindex(hardware->h_ifname)) {
1151 free(buffer);
1152 continue;
1153 }
1154 }
1155 hardware->h_rx_cnt++;
1156 lldpd_decode(cfg, buffer, n, hardware, bond);
1157 free(buffer);
1158 }
1159
1160 }
1161 if (FD_ISSET(cfg->g_ctl, &rfds)) {
1162 if (ctl_accept(cfg, cfg->g_ctl) == -1)
1163 LLOG_WARN("unable to accept new client");
1164 }
1165 for (client = TAILQ_FIRST(&cfg->g_clients);
1166 client != NULL;
1167 client = client_next) {
1168 client_next = TAILQ_NEXT(client, next);
1169 if (FD_ISSET(client->fd, &rfds)) {
1170 /* Got a message */
1171 if ((buffer = (char *)malloc(MAX_HMSGSIZE)) ==
1172 NULL) {
1173 LLOG_WARN("failed to alloc reception buffer");
1174 continue;
1175 }
1176 if ((n = recv(client->fd, buffer,
1177 MAX_HMSGSIZE, 0)) == -1) {
1178 LLOG_WARN("error while receiving message");
1179 free(buffer);
1180 continue;
1181 }
1182 if (n > 0)
1183 client_handle_client(cfg, client, buffer, n);
1184 else
1185 ctl_close(cfg, client->fd); /* Will use TAILQ_REMOVE ! */
1186 free(buffer);
1187 }
1188 }
1189
1190 #ifdef USE_SNMP
1191 if (cfg->g_snmp) {
1192 run_alarms();
1193 netsnmp_check_outstanding_agent_requests();
1194 }
1195 #endif /* USE_SNMP */
1196 } while ((rc != 0) || (time(NULL) - cfg->g_lastsent < cfg->g_delay));
1197 }
1198
1199 static void
1200 lldpd_send_all(struct lldpd *cfg)
1201 {
1202 struct lldpd_hardware *hardware;
1203 u_int8_t saved_lladdr[ETHER_ADDR_LEN];
1204 int i, altermac;
1205
1206 cfg->g_lastsent = time(NULL);
1207 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
1208 /* Ignore if interface is down */
1209 if (((hardware->h_flags & IFF_UP) == 0) ||
1210 ((hardware->h_flags & IFF_RUNNING) == 0))
1211 continue;
1212
1213 /* When sending on inactive slaves, just send using a 0:0:0:0:0:0 address */
1214 altermac = 0;
1215 if ((hardware->h_raw_real > 0) &&
1216 (!iface_is_slave_active(cfg, hardware->h_master,
1217 hardware->h_ifname))) {
1218 altermac = 1;
1219 memcpy(saved_lladdr, hardware->h_lladdr, ETHER_ADDR_LEN);
1220 memset(hardware->h_lladdr, 0, ETHER_ADDR_LEN);
1221 }
1222
1223 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
1224 if (!cfg->g_protocols[i].enabled)
1225 continue;
1226 if ((hardware->h_mode == cfg->g_protocols[i].mode) ||
1227 (cfg->g_protocols[i].mode == LLDPD_MODE_LLDP))
1228 cfg->g_protocols[i].send(cfg, &cfg->g_lchassis, hardware);
1229 }
1230 /* Restore MAC if needed */
1231 if (altermac)
1232 memcpy(hardware->h_lladdr, saved_lladdr, ETHER_ADDR_LEN);
1233 }
1234 }
1235
1236 #ifdef ENABLE_LLDPMED
1237 static void
1238 lldpd_med(struct lldpd_chassis *chassis)
1239 {
1240 free(chassis->c_med_hw);
1241 free(chassis->c_med_fw);
1242 free(chassis->c_med_sn);
1243 free(chassis->c_med_manuf);
1244 free(chassis->c_med_model);
1245 free(chassis->c_med_asset);
1246 chassis->c_med_hw = dmi_hw();
1247 chassis->c_med_fw = dmi_fw();
1248 chassis->c_med_sn = dmi_sn();
1249 chassis->c_med_manuf = dmi_manuf();
1250 chassis->c_med_model = dmi_model();
1251 chassis->c_med_asset = dmi_asset();
1252 }
1253 #endif
1254
1255 static void
1256 lldpd_loop(struct lldpd *cfg)
1257 {
1258 struct ifaddrs *ifap, *ifa;
1259 struct sockaddr_ll *sdl;
1260 struct lldpd_hardware *hardware;
1261 struct lldpd_vif *vif;
1262 int f;
1263 char status;
1264 struct utsname *un;
1265 char *hp;
1266
1267 /* Set system name and description */
1268 if ((un = (struct utsname*)malloc(sizeof(struct utsname))) == NULL)
1269 fatal(NULL);
1270 if (uname(un) != 0)
1271 fatal("failed to get system information");
1272 if ((hp = priv_gethostbyname()) == NULL)
1273 fatal("failed to get system name");
1274 free(cfg->g_lchassis.c_name);
1275 free(cfg->g_lchassis.c_descr);
1276 if ((cfg->g_lchassis.c_name = strdup(hp)) == NULL)
1277 fatal(NULL);
1278 if (asprintf(&cfg->g_lchassis.c_descr, "%s %s %s %s",
1279 un->sysname, un->release, un->version, un->machine) == -1)
1280 fatal("failed to set system description");
1281
1282 /* Check forwarding */
1283 cfg->g_lchassis.c_cap_enabled = 0;
1284 if ((f = priv_open("/proc/sys/net/ipv4/ip_forward")) >= 0) {
1285 if ((read(f, &status, 1) == 1) && (status == '1')) {
1286 cfg->g_lchassis.c_cap_enabled = LLDP_CAP_ROUTER;
1287 }
1288 close(f);
1289 }
1290 #ifdef ENABLE_LLDPMED
1291 if (cfg->g_lchassis.c_cap_available & LLDP_CAP_TELEPHONE)
1292 cfg->g_lchassis.c_cap_enabled |= LLDP_CAP_TELEPHONE;
1293 lldpd_med(&cfg->g_lchassis);
1294 free(cfg->g_lchassis.c_med_sw);
1295 cfg->g_lchassis.c_med_sw = strdup(un->release);
1296 #endif
1297 free(un);
1298
1299 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
1300 hardware->h_flags = 0;
1301 TAILQ_FOREACH(vif, &cfg->g_vif, vif_entries)
1302 vif->vif_flags = 0;
1303
1304 if (getifaddrs(&ifap) != 0)
1305 fatal("lldpd_loop: failed to get interface list");
1306
1307 cfg->g_lchassis.c_mgmt.s_addr = INADDR_ANY;
1308 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
1309 if (cfg->g_lchassis.c_mgmt.s_addr == INADDR_ANY)
1310 /* Get management address, if available */
1311 if ((ifa->ifa_addr != NULL) &&
1312 (ifa->ifa_addr->sa_family == AF_INET)) {
1313 struct sockaddr_in *sa;
1314 sa = (struct sockaddr_in *)ifa->ifa_addr;
1315 if ((ntohl(*(u_int32_t*)&sa->sin_addr) != INADDR_LOOPBACK) &&
1316 (cfg->g_mgmt_pattern == NULL)) {
1317 memcpy(&cfg->g_lchassis.c_mgmt,
1318 &sa->sin_addr,
1319 sizeof(struct in_addr));
1320 cfg->g_lchassis.c_mgmt_if = if_nametoindex(ifa->ifa_name);
1321 }
1322 else if (cfg->g_mgmt_pattern != NULL) {
1323 char *ip;
1324 ip = inet_ntoa(sa->sin_addr);
1325 if (fnmatch(cfg->g_mgmt_pattern,
1326 ip, 0) == 0) {
1327 memcpy(&cfg->g_lchassis.c_mgmt,
1328 &sa->sin_addr,
1329 sizeof(struct in_addr));
1330 cfg->g_lchassis.c_mgmt_if =
1331 if_nametoindex(ifa->ifa_name);
1332 }
1333 }
1334 }
1335
1336 if (ifa->ifa_addr == NULL ||
1337 ifa->ifa_addr->sa_family != PF_PACKET)
1338 continue;
1339
1340 sdl = (struct sockaddr_ll *)ifa->ifa_addr;
1341 if (sdl->sll_hatype != ARPHRD_ETHER || !sdl->sll_halen)
1342 continue;
1343
1344 if (iface_is_bridge(cfg, ifa->ifa_name)) {
1345 cfg->g_lchassis.c_cap_enabled |= LLDP_CAP_BRIDGE;
1346 continue;
1347 }
1348
1349 if ((iface_is_vlan(cfg, ifa->ifa_name)) ||
1350 (iface_is_bond(cfg, ifa->ifa_name)))
1351 continue;
1352
1353 if (!(ifa->ifa_flags & (IFF_MULTICAST|IFF_BROADCAST)))
1354 continue;
1355
1356 if (iface_is_wireless(cfg, ifa->ifa_name))
1357 cfg->g_lchassis.c_cap_enabled |= LLDP_CAP_WLAN;
1358
1359 if (lldpd_port_add(cfg, ifa) == NULL)
1360 LLOG_WARNX("failed to allocate port %s, skip it",
1361 ifa->ifa_name);
1362 }
1363
1364 /* Handle VLAN */
1365 if (cfg->g_listen_vlans) {
1366 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
1367 if ((iface_is_vlan(cfg, ifa->ifa_name)) &&
1368 (lldpd_port_add_vlan(cfg, ifa) == NULL)) {
1369 LLOG_WARNX("unable to allocate vlan %s, skip it",
1370 ifa->ifa_name);
1371 }
1372 }
1373 }
1374
1375 freeifaddrs(ifap);
1376
1377 lldpd_cleanup(cfg);
1378
1379 lldpd_send_all(cfg);
1380 lldpd_recv_all(cfg);
1381 }
1382
1383 static void
1384 lldpd_shutdown(int sig)
1385 {
1386 LLOG_INFO("signal received, exiting");
1387 exit(0);
1388 }
1389
1390 /* For signal handling */
1391 static struct lldpd *gcfg = NULL;
1392
1393 static void
1394 lldpd_exit()
1395 {
1396 struct lldpd_hardware *hardware;
1397 struct lldpd_vif *vif;
1398 close(gcfg->g_ctl);
1399 priv_ctl_cleanup();
1400 TAILQ_FOREACH(hardware, &gcfg->g_hardware, h_entries) {
1401 if (INTERFACE_OPENED(hardware))
1402 lldpd_iface_close(gcfg, hardware);
1403 }
1404 TAILQ_FOREACH(vif, &gcfg->g_vif, vif_entries) {
1405 if (vif->vif_raw != -1)
1406 lldpd_iface_close(gcfg, (struct lldpd_hardware*)vif);
1407 }
1408 #ifdef USE_SNMP
1409 if (gcfg->g_snmp)
1410 agent_shutdown();
1411 #endif /* USE_SNMP */
1412 }
1413
1414 int
1415 main(int argc, char *argv[])
1416 {
1417 struct lldpd *cfg;
1418 int ch, debug = 0;
1419 #ifdef USE_SNMP
1420 int snmp = 0;
1421 #endif
1422 char *mgmtp = NULL;
1423 char *popt, opts[] = "vdxm:p:M:i@ ";
1424 int probe = 0, i, found, vlan = 0;
1425 #ifdef ENABLE_LLDPMED
1426 int lldpmed = 0, noinventory = 0;
1427 #endif
1428
1429 saved_argv = argv;
1430
1431 /*
1432 * Get and parse command line options
1433 */
1434 popt = index(opts, '@');
1435 for (i=0; protos[i].mode != 0; i++) {
1436 if (protos[i].enabled == 1) continue;
1437 *(popt++) = protos[i].arg;
1438 }
1439 *popt = '\0';
1440 while ((ch = getopt(argc, argv, opts)) != -1) {
1441 switch (ch) {
1442 case 'v':
1443 vlan = 1;
1444 break;
1445 case 'd':
1446 debug++;
1447 break;
1448 case 'm':
1449 mgmtp = optarg;
1450 break;
1451 #ifdef ENABLE_LLDPMED
1452 case 'M':
1453 lldpmed = atoi(optarg);
1454 if ((lldpmed < 1) || (lldpmed > 4)) {
1455 fprintf(stderr, "-M requires an argument between 1 and 4\n");
1456 usage();
1457 }
1458 break;
1459 case 'i':
1460 noinventory = 1;
1461 break;
1462 #else
1463 case 'M':
1464 case 'i':
1465 case 'P':
1466 fprintf(stderr, "LLDP-MED support is not built-in\n");
1467 usage();
1468 break;
1469 #endif
1470 case 'p':
1471 probe = atoi(optarg);
1472 break;
1473 case 'x':
1474 #ifdef USE_SNMP
1475 snmp = 1;
1476 #else
1477 fprintf(stderr, "SNMP support is not built-in\n");
1478 usage();
1479 #endif
1480 break;
1481 default:
1482 found = 0;
1483 for (i=0; protos[i].mode != 0; i++) {
1484 if (protos[i].enabled) continue;
1485 if (ch == protos[i].arg) {
1486 protos[i].enabled = 1;
1487 found = 1;
1488 }
1489 }
1490 if (!found)
1491 usage();
1492 }
1493 }
1494
1495 log_init(debug);
1496
1497 if (!debug) {
1498 int pid;
1499 char *spid;
1500 if (daemon(0, 0) != 0)
1501 fatal("failed to detach daemon");
1502 if ((pid = open(LLDPD_PID_FILE,
1503 O_TRUNC | O_CREAT | O_WRONLY, 0644)) == -1)
1504 fatal("unable to open pid file " LLDPD_PID_FILE);
1505 if (asprintf(&spid, "%d\n", getpid()) == -1)
1506 fatal("unable to create pid file " LLDPD_PID_FILE);
1507 if (write(pid, spid, strlen(spid)) == -1)
1508 fatal("unable to write pid file " LLDPD_PID_FILE);
1509 free(spid);
1510 close(pid);
1511 }
1512
1513 priv_init(PRIVSEP_CHROOT);
1514
1515 if (probe == 0) probe = LLDPD_TTL;
1516
1517 if ((cfg = (struct lldpd *)
1518 calloc(1, sizeof(struct lldpd))) == NULL)
1519 fatal(NULL);
1520
1521 cfg->g_mgmt_pattern = mgmtp;
1522 cfg->g_listen_vlans = vlan;
1523
1524 /* Get ioctl socket */
1525 if ((cfg->g_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1526 fatal("failed to get ioctl socket");
1527 cfg->g_delay = LLDPD_TX_DELAY;
1528
1529 /* Set system capabilities */
1530 cfg->g_lchassis.c_cap_available = LLDP_CAP_BRIDGE | LLDP_CAP_WLAN |
1531 LLDP_CAP_ROUTER;
1532 #ifdef ENABLE_LLDPMED
1533 if (lldpmed > 0) {
1534 if (lldpmed == LLDPMED_CLASS_III)
1535 cfg->g_lchassis.c_cap_available |= LLDP_CAP_TELEPHONE;
1536 cfg->g_lchassis.c_med_type = lldpmed;
1537 cfg->g_lchassis.c_med_cap_available = LLDPMED_CAP_CAP |
1538 LLDPMED_CAP_IV | LLDPMED_CAP_LOCATION;
1539 cfg->g_noinventory = noinventory;
1540 }
1541 #endif
1542
1543 /* Set TTL */
1544 cfg->g_lchassis.c_ttl = LLDPD_TTL;
1545
1546 cfg->g_protocols = protos;
1547 cfg->g_probe_time = probe;
1548 for (i=0; protos[i].mode != 0; i++)
1549 if (protos[i].enabled) {
1550 cfg->g_multi++;
1551 LLOG_INFO("protocol %s enabled", protos[i].name);
1552 } else
1553 LLOG_INFO("protocol %s disabled", protos[i].name);
1554 cfg->g_multi--;
1555
1556 TAILQ_INIT(&cfg->g_hardware);
1557 TAILQ_INIT(&cfg->g_vif);
1558
1559 #ifdef USE_SNMP
1560 if (snmp) {
1561 cfg->g_snmp = 1;
1562 agent_init(cfg, debug);
1563 }
1564 #endif /* USE_SNMP */
1565
1566 /* Create socket */
1567 if ((cfg->g_ctl = priv_ctl_create(cfg)) == -1)
1568 fatalx("unable to create control socket " LLDPD_CTL_SOCKET);
1569 TAILQ_INIT(&cfg->g_clients);
1570
1571 gcfg = cfg;
1572 if (atexit(lldpd_exit) != 0) {
1573 close(cfg->g_ctl);
1574 priv_ctl_cleanup();
1575 fatal("unable to set exit function");
1576 }
1577
1578 /* Signal handling */
1579 signal(SIGHUP, lldpd_shutdown);
1580 signal(SIGINT, lldpd_shutdown);
1581 signal(SIGTERM, lldpd_shutdown);
1582
1583 for (;;)
1584 lldpd_loop(cfg);
1585
1586 return (0);
1587 }