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