]>
git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/lldpd.h
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #ifdef HAVE_VALGRIND_VALGRIND_H
26 # include <valgrind/valgrind.h>
28 # define RUNNING_ON_VALGRIND 0
34 #include <sys/queue.h>
35 #include <sys/types.h>
36 #include <netinet/if_ether.h>
37 #include <netinet/in.h>
41 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
42 # include "protocols/cdp.h"
45 # include "protocols/sonmp.h"
48 # include "protocols/edp.h"
53 #include "../compat/compat.h"
54 #include "../marshal.h"
57 #include "../lldpd-structs.h"
59 /* We don't want to import event2/event.h. We only need those as
64 #define SYSFS_CLASS_NET "/sys/class/net/"
65 #define SYSFS_CLASS_DMI "/sys/class/dmi/id/"
66 #define LLDPD_TX_INTERVAL 30
67 #define LLDPD_TX_HOLD 4
68 #define LLDPD_TTL LLDPD_TX_INTERVAL * LLDPD_TX_HOLD
69 #define LLDPD_TX_MSGDELAY 1
70 #define LLDPD_MAX_NEIGHBORS 32
71 #define LLDPD_FAST_TX_INTERVAL 1
72 #define LLDPD_FAST_INIT 4
74 #define USING_AGENTX_SUBAGENT_MODULE 1
76 #define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
77 #define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
78 #define PROTO_GUESS_SIG char *, int
80 #define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR))
83 int mode
; /* > 0 mode identifier (unique per protocol) */
84 int enabled
; /* Is this protocol enabled? */
85 char *name
; /* Name of protocol */
86 char arg
; /* Argument to enable this protocol */
87 int(*send
)(PROTO_SEND_SIG
); /* How to send a frame */
88 int(*decode
)(PROTO_DECODE_SIG
); /* How to decode a frame */
89 int(*guess
)(PROTO_GUESS_SIG
); /* Can be NULL, use MAC address in this case */
90 u_int8_t mac1
[ETHER_ADDR_LEN
]; /* Destination MAC address used by this protocol */
91 u_int8_t mac2
[ETHER_ADDR_LEN
]; /* Destination MAC address used by this protocol */
92 u_int8_t mac3
[ETHER_ADDR_LEN
]; /* Destination MAC address used by this protocol */
95 #define SMART_HIDDEN(port) (port->p_hidden_in)
100 struct lldpd_hardware
*lldpd_get_hardware(struct lldpd
*,
102 struct lldpd_hardware
*lldpd_alloc_hardware(struct lldpd
*, char *, int);
103 void lldpd_hardware_cleanup(struct lldpd
*, struct lldpd_hardware
*);
104 struct lldpd_mgmt
*lldpd_alloc_mgmt(int family
, void *addr
, size_t addrsize
, u_int32_t iface
);
105 void lldpd_recv(struct lldpd
*, struct lldpd_hardware
*, int);
106 void lldpd_send(struct lldpd_hardware
*);
107 void lldpd_loop(struct lldpd
*);
108 int lldpd_main(int, char **, char **);
109 void lldpd_update_localports(struct lldpd
*);
110 void lldpd_update_localchassis(struct lldpd
*);
111 void lldpd_cleanup(struct lldpd
*);
114 u_int16_t
frame_checksum(const u_int8_t
*, int, int);
117 void levent_loop(struct lldpd
*);
118 void levent_shutdown(struct lldpd
*);
119 void levent_hardware_init(struct lldpd_hardware
*);
120 void levent_hardware_add_fd(struct lldpd_hardware
*, int);
121 void levent_hardware_release(struct lldpd_hardware
*);
122 void levent_ctl_notify(char *, int, struct lldpd_port
*);
123 void levent_send_now(struct lldpd
*);
124 void levent_update_now(struct lldpd
*);
125 int levent_iface_subscribe(struct lldpd
*, int);
126 void levent_schedule_pdu(struct lldpd_hardware
*);
127 void levent_schedule_cleanup(struct lldpd
*);
128 int levent_make_socket_nonblocking(int);
129 int levent_make_socket_blocking(int);
132 int lldp_send_shutdown(PROTO_SEND_SIG
);
133 int lldp_send(PROTO_SEND_SIG
);
134 int lldp_decode(PROTO_DECODE_SIG
);
138 int cdpv1_send(PROTO_SEND_SIG
);
139 int cdpv2_send(PROTO_SEND_SIG
);
140 int cdpv1_guess(PROTO_GUESS_SIG
);
141 int cdpv2_guess(PROTO_GUESS_SIG
);
143 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
144 int cdp_decode(PROTO_DECODE_SIG
);
147 int fdp_send(PROTO_SEND_SIG
);
152 int sonmp_send(PROTO_SEND_SIG
);
153 int sonmp_decode(PROTO_DECODE_SIG
);
158 int edp_send(PROTO_SEND_SIG
);
159 int edp_decode(PROTO_DECODE_SIG
);
163 #ifdef ENABLE_LLDPMED
167 char *dmi_manuf(void);
168 char *dmi_model(void);
169 char *dmi_asset(void);
174 void agent_shutdown(void);
175 void agent_init(struct lldpd
*, const char *);
176 void agent_notify(struct lldpd_hardware
*, int, struct lldpd_port
*);
179 #ifdef ENABLE_PRIVSEP
181 void agent_priv_register_domain(void);
186 client_handle_client(struct lldpd
*cfg
,
187 ssize_t(*send
)(void *, int, void *, size_t),
189 enum hmsg_type type
, void *buffer
, size_t n
,
193 void priv_init(const char*, int, uid_t
, gid_t
);
194 void priv_wait(void);
195 void priv_ctl_cleanup(const char *ctlname
);
196 char *priv_gethostname(void);
198 int priv_open(char*);
199 void asroot_open(void);
201 int priv_iface_init(int, char *);
202 int asroot_iface_init_os(int, char *, int *);
203 int priv_iface_multicast(const char *, const u_int8_t
*, int);
204 int priv_iface_description(const char *, const char *);
205 int asroot_iface_description_os(const char *, const char *);
206 int priv_iface_promisc(const char*);
207 int asroot_iface_promisc_os(const char *);
208 int priv_snmp_socket(struct sockaddr_un
*);
212 PRIV_DELETE_CTL_SOCKET
,
216 PRIV_IFACE_MULTICAST
,
217 PRIV_IFACE_DESCRIPTION
,
223 #if defined USE_SECCOMP && defined ENABLE_PRIVSEP
224 int priv_seccomp_init(int, int);
232 int may_read(enum priv_context
, void *, size_t);
233 void must_read(enum priv_context
, void *, size_t);
234 void must_write(enum priv_context
, const void *, size_t);
235 void priv_privileged_fd(int);
236 void priv_unprivileged_fd(int);
237 int priv_fd(enum priv_context
);
238 int receive_fd(enum priv_context
);
239 void send_fd(enum priv_context
, int);
243 /* BPF filter to get revelant information from interfaces */
244 /* LLDP: "ether proto 0x88cc and ether dst 01:80:c2:00:00:0e" */
245 /* FDP: "ether dst 01:e0:52:cc:cc:cc" */
246 /* CDP: "ether dst 01:00:0c:cc:cc:cc" */
247 /* SONMP: "ether dst 01:00:81:00:01:00" */
248 /* EDP: "ether dst 00:e0:2b:00:00:00" */
249 /* For optimization purpose, we first check if the first bit of the
250 first byte is 1. if not, this can only be an EDP packet:
252 tcpdump -dd "(ether[0] & 1 = 1 and
253 ((ether proto 0x88cc and (ether dst 01:80:c2:00:00:0e or
254 ether dst 01:80:c2:00:00:03 or
255 ether dst 01:80:c2:00:00:00)) or
256 (ether dst 01:e0:52:cc:cc:cc) or
257 (ether dst 01:00:0c:cc:cc:cc) or
258 (ether dst 01:00:81:00:01:00))) or
259 (ether dst 00:e0:2b:00:00:00)"
262 #define LLDPD_FILTER_F \
263 { 0x30, 0, 0, 0x00000000 }, \
264 { 0x54, 0, 0, 0x00000001 }, \
265 { 0x15, 0, 16, 0x00000001 }, \
266 { 0x28, 0, 0, 0x0000000c }, \
267 { 0x15, 0, 6, 0x000088cc }, \
268 { 0x20, 0, 0, 0x00000002 }, \
269 { 0x15, 2, 0, 0xc200000e }, \
270 { 0x15, 1, 0, 0xc2000003 }, \
271 { 0x15, 0, 2, 0xc2000000 }, \
272 { 0x28, 0, 0, 0x00000000 }, \
273 { 0x15, 12, 13, 0x00000180 }, \
274 { 0x20, 0, 0, 0x00000002 }, \
275 { 0x15, 0, 2, 0x52cccccc }, \
276 { 0x28, 0, 0, 0x00000000 }, \
277 { 0x15, 8, 9, 0x000001e0 }, \
278 { 0x15, 1, 0, 0x0ccccccc }, \
279 { 0x15, 0, 2, 0x81000100 }, \
280 { 0x28, 0, 0, 0x00000000 }, \
281 { 0x15, 4, 5, 0x00000100 }, \
282 { 0x20, 0, 0, 0x00000002 }, \
283 { 0x15, 0, 3, 0x2b000000 }, \
284 { 0x28, 0, 0, 0x00000000 }, \
285 { 0x15, 0, 1, 0x000000e0 }, \
286 { 0x6, 0, 0, 0x00040000 }, \
287 { 0x6, 0, 0, 0x00000000 }
289 /* This function is responsible to refresh information about interfaces. It is
290 * OS specific but should be present for each OS. It can use the functions in
291 * `interfaces.c` as helper by providing a list of OS-independent interface
293 void interfaces_update(struct lldpd
*);
296 /* An interface cannot be both physical and (bridge or bond or vlan) */
297 #define IFACE_PHYSICAL_T (1 << 0) /* Physical interface */
298 #define IFACE_BRIDGE_T (1 << 1) /* Bridge interface */
299 #define IFACE_BOND_T (1 << 2) /* Bond interface */
300 #define IFACE_VLAN_T (1 << 3) /* VLAN interface */
301 #define IFACE_WIRELESS_T (1 << 4) /* Wireless interface */
302 struct interfaces_device
{
303 TAILQ_ENTRY(interfaces_device
) next
;
304 int ignore
; /* Ignore this interface */
305 int index
; /* Index */
306 char *name
; /* Name */
307 char *alias
; /* Alias */
308 char *address
; /* MAC address */
309 char *driver
; /* Driver (for whitelisting purpose) */
310 int flags
; /* Flags (IFF_*) */
312 int type
; /* Type (see IFACE_*_T) */
313 int vlanid
; /* If a VLAN, what is the VLAN ID? */
314 struct interfaces_device
*lower
; /* Lower interface (for a VLAN for example) */
315 struct interfaces_device
*upper
; /* Upper interface (for a bridge or a bond) */
317 /* The following are OS specific. Should be static (no free function) */
319 int lower_idx
; /* Index to lower interface */
320 int upper_idx
; /* Index to upper interface */
323 struct interfaces_address
{
324 TAILQ_ENTRY(interfaces_address
) next
;
325 int index
; /* Index */
326 int flags
; /* Flags */
327 struct sockaddr_storage address
; /* Address */
329 /* The following are OS specific. */
332 TAILQ_HEAD(interfaces_device_list
, interfaces_device
);
333 TAILQ_HEAD(interfaces_address_list
, interfaces_address
);
334 void interfaces_free_device(struct interfaces_device
*);
335 void interfaces_free_address(struct interfaces_address
*);
336 void interfaces_free_devices(struct interfaces_device_list
*);
337 void interfaces_free_addresses(struct interfaces_address_list
*);
338 struct interfaces_device
* interfaces_indextointerface(
339 struct interfaces_device_list
*,
341 struct interfaces_device
* interfaces_nametointerface(
342 struct interfaces_device_list
*,
345 void interfaces_helper_promisc(struct lldpd
*,
346 struct lldpd_hardware
*);
347 void interfaces_helper_whitelist(struct lldpd
*,
348 struct interfaces_device_list
*);
349 void interfaces_helper_chassis(struct lldpd
*,
350 struct interfaces_device_list
*);
351 void interfaces_helper_add_hardware(struct lldpd
*,
352 struct lldpd_hardware
*);
353 void interfaces_helper_physical(struct lldpd
*,
354 struct interfaces_device_list
*,
356 int(*init
)(struct lldpd
*, struct lldpd_hardware
*));
357 void interfaces_helper_port_name_desc(struct lldpd
*,
358 struct lldpd_hardware
*,
359 struct interfaces_device
*);
360 void interfaces_helper_mgmt(struct lldpd
*,
361 struct interfaces_address_list
*);
363 void interfaces_helper_vlan(struct lldpd
*,
364 struct interfaces_device_list
*);
366 int interfaces_send_helper(struct lldpd
*,
367 struct lldpd_hardware
*, char *, size_t);
369 void interfaces_setup_multicast(struct lldpd
*, const char *, int);
370 int interfaces_routing_enabled(struct lldpd
*);
371 void interfaces_cleanup(struct lldpd
*);
375 struct interfaces_device_list
*netlink_get_interfaces(struct lldpd
*);
376 struct interfaces_address_list
*netlink_get_addresses(struct lldpd
*);
377 void netlink_cleanup(struct lldpd
*);
378 struct lldpd_netlink
;
381 #ifndef HOST_OS_LINUX
382 int ifbpf_phys_init(struct lldpd
*, struct lldpd_hardware
*);
386 int pattern_match(char *, char *, int);
390 struct event_base
*g_base
;
394 struct lldpd_config g_config
;
396 struct protocol
*g_protocols
;
398 struct event
*g_main_loop
;
399 struct event
*g_cleanup_timer
;
402 struct event
*g_snmp_timeout
;
404 const char *g_snmp_agentx
;
405 #endif /* USE_SNMP */
407 /* Unix socket handling */
408 const char *g_ctlname
;
410 struct event
*g_iface_event
; /* Triggered when there is an interface change */
411 struct event
*g_iface_timer_event
; /* Triggered one second after last interface change */
412 void(*g_iface_cb
)(struct lldpd
*); /* Called when there is an interface change */
417 struct lldpd_netlink
*g_netlink
;
420 struct lldpd_port
*g_default_local_port
;
421 #define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
422 TAILQ_HEAD(, lldpd_chassis
) g_chassis
;
423 TAILQ_HEAD(, lldpd_hardware
) g_hardware
;
426 #endif /* _LLDPD_H */