1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3  * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #ifndef _LLDPD_H
19 #define _LLDPD_H
20 
21 #if HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24 
25 #ifdef HAVE_VALGRIND_VALGRIND_H
26 # include <valgrind/valgrind.h>
27 #else
28 # define RUNNING_ON_VALGRIND 0
29 #endif
30 
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <string.h>
34 #include <sys/queue.h>
35 #include <sys/types.h>
36 #include <netinet/if_ether.h>
37 #include <netinet/in.h>
38 #include <sys/un.h>
39 
40 #include "lldp-tlv.h"
41 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
42 #  include "protocols/cdp.h"
43 #endif
44 #ifdef ENABLE_SONMP
45 #  include "protocols/sonmp.h"
46 #endif
47 #ifdef ENABLE_EDP
48 #  include "protocols/edp.h"
49 #endif
50 
51 
52 
53 #include "../compat/compat.h"
54 #include "../marshal.h"
55 #include "../log.h"
56 #include "../ctl.h"
57 #include "../lldpd-structs.h"
58 
59 /* We don't want to import event2/event.h. We only need those as
60    opaque structs. */
61 struct event;
62 struct event_base;
63 
64 #define PROCFS_SYS_NET	"/proc/sys/net/"
65 #define SYSFS_CLASS_NET "/sys/class/net/"
66 #define SYSFS_CLASS_DMI "/sys/class/dmi/id/"
67 #define LLDPD_TX_INTERVAL	30
68 #define LLDPD_TX_HOLD          4
69 #define LLDPD_TTL              LLDPD_TX_INTERVAL * LLDPD_TX_HOLD
70 #define LLDPD_TX_MSGDELAY	1
71 #define LLDPD_MAX_NEIGHBORS	32
72 #define LLDPD_FAST_TX_INTERVAL	1
73 #define LLDPD_FAST_INIT	4
74 
75 #define USING_AGENTX_SUBAGENT_MODULE 1
76 
77 #define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
78 #define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
79 #define PROTO_GUESS_SIG char *, int
80 
81 #define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR))
82 
83 struct protocol {
84 	int		 mode;		/* > 0 mode identifier (unique per protocol) */
85 	int		 enabled;	/* Is this protocol enabled? */
86 	char		*name;		/* Name of protocol */
87 	char		 arg;		/* Argument to enable this protocol */
88 	int(*send)(PROTO_SEND_SIG);	/* How to send a frame */
89 	int(*decode)(PROTO_DECODE_SIG); /* How to decode a frame */
90 	int(*guess)(PROTO_GUESS_SIG);   /* Can be NULL, use MAC address in this case */
91 	u_int8_t	 mac1[ETHER_ADDR_LEN];  /* Destination MAC address used by this protocol */
92 	u_int8_t	 mac2[ETHER_ADDR_LEN];  /* Destination MAC address used by this protocol */
93 	u_int8_t	 mac3[ETHER_ADDR_LEN];  /* Destination MAC address used by this protocol */
94 };
95 
96 #define SMART_HIDDEN(port) (port->p_hidden_in)
97 
98 struct lldpd;
99 
100 /* lldpd.c */
101 struct lldpd_hardware	*lldpd_get_hardware(struct lldpd *,
102     char *, int);
103 struct lldpd_hardware	*lldpd_alloc_hardware(struct lldpd *, char *, int);
104 void	 lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
105 struct lldpd_mgmt *lldpd_alloc_mgmt(int family, void *addr, size_t addrsize, u_int32_t iface);
106 void	 lldpd_recv(struct lldpd *, struct lldpd_hardware *, int);
107 void	 lldpd_send(struct lldpd_hardware *);
108 void	 lldpd_loop(struct lldpd *);
109 int	 lldpd_main(int, char **, char **);
110 void	 lldpd_update_localports(struct lldpd *);
111 void	 lldpd_update_localchassis(struct lldpd *);
112 void	 lldpd_cleanup(struct lldpd *);
113 
114 /* frame.c */
115 u_int16_t frame_checksum(const u_int8_t *, int, int);
116 
117 /* event.c */
118 void	 levent_loop(struct lldpd *);
119 void	 levent_shutdown(struct lldpd *);
120 void	 levent_hardware_init(struct lldpd_hardware *);
121 void	 levent_hardware_add_fd(struct lldpd_hardware *, int);
122 void	 levent_hardware_release(struct lldpd_hardware *);
123 void	 levent_ctl_notify(char *, int, struct lldpd_port *);
124 void	 levent_send_now(struct lldpd *);
125 void	 levent_update_now(struct lldpd *);
126 int	 levent_iface_subscribe(struct lldpd *, int);
127 void	 levent_schedule_pdu(struct lldpd_hardware *);
128 void	 levent_schedule_cleanup(struct lldpd *);
129 int	 levent_make_socket_nonblocking(int);
130 int	 levent_make_socket_blocking(int);
131 #ifdef HOST_OS_LINUX
132 void	 levent_recv_error(int, const char*);
133 #endif
134 
135 /* lldp.c */
136 int	 lldp_send_shutdown(PROTO_SEND_SIG);
137 int	 lldp_send(PROTO_SEND_SIG);
138 int	 lldp_decode(PROTO_DECODE_SIG);
139 
140 /* cdp.c */
141 #ifdef ENABLE_CDP
142 int	 cdpv1_send(PROTO_SEND_SIG);
143 int	 cdpv2_send(PROTO_SEND_SIG);
144 int	 cdpv1_guess(PROTO_GUESS_SIG);
145 int	 cdpv2_guess(PROTO_GUESS_SIG);
146 #endif
147 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
148 int	 cdp_decode(PROTO_DECODE_SIG);
149 #endif
150 #ifdef ENABLE_FDP
151 int	 fdp_send(PROTO_SEND_SIG);
152 #endif
153 
154 #ifdef ENABLE_SONMP
155 /* sonmp.c */
156 int	 sonmp_send(PROTO_SEND_SIG);
157 int	 sonmp_decode(PROTO_DECODE_SIG);
158 #endif
159 
160 #ifdef ENABLE_EDP
161 /* edp.c */
162 int	 edp_send(PROTO_SEND_SIG);
163 int	 edp_decode(PROTO_DECODE_SIG);
164 #endif
165 
166 /* dmi.c */
167 #ifdef ENABLE_LLDPMED
168 char	*dmi_hw(void);
169 char	*dmi_fw(void);
170 char	*dmi_sn(void);
171 char	*dmi_manuf(void);
172 char	*dmi_model(void);
173 char	*dmi_asset(void);
174 #endif
175 
176 #ifdef USE_SNMP
177 /* agent.c */
178 void		 agent_shutdown(void);
179 void		 agent_init(struct lldpd *, const char *);
180 void		 agent_notify(struct lldpd_hardware *, int, struct lldpd_port *);
181 #endif
182 
183 #ifdef ENABLE_PRIVSEP
184 /* agent_priv.c */
185 void		 agent_priv_register_domain(void);
186 #endif
187 
188 /* client.c */
189 int
190 client_handle_client(struct lldpd *cfg,
191     ssize_t(*send)(void *, int, void *, size_t),
192     void *,
193     enum hmsg_type type, void *buffer, size_t n,
194     int*);
195 
196 /* priv.c */
197 void	 priv_init(const char*, int, uid_t, gid_t);
198 void	 priv_wait(void);
199 void	 priv_ctl_cleanup(const char *ctlname);
200 char   	*priv_gethostname(void);
201 #ifdef HOST_OS_LINUX
202 int    	 priv_open(char*);
203 void	 asroot_open(void);
204 #endif
205 int    	 priv_iface_init(int, char *);
206 int	 asroot_iface_init_os(int, char *, int *);
207 int	 priv_iface_multicast(const char *, const u_int8_t *, int);
208 int	 priv_iface_description(const char *, const char *);
209 int	 asroot_iface_description_os(const char *, const char *);
210 int	 priv_iface_promisc(const char*);
211 int	 asroot_iface_promisc_os(const char *);
212 int	 priv_snmp_socket(struct sockaddr_un *);
213 
214 enum priv_cmd {
215 	PRIV_PING,
216 	PRIV_DELETE_CTL_SOCKET,
217 	PRIV_GET_HOSTNAME,
218 	PRIV_OPEN,
219 	PRIV_IFACE_INIT,
220 	PRIV_IFACE_MULTICAST,
221 	PRIV_IFACE_DESCRIPTION,
222 	PRIV_IFACE_PROMISC,
223 	PRIV_SNMP_SOCKET,
224 };
225 
226 /* priv-seccomp.c */
227 #if defined USE_SECCOMP && defined ENABLE_PRIVSEP
228 int priv_seccomp_init(int, int);
229 #endif
230 
231 /* privsep_io.c */
232 enum priv_context {
233 	PRIV_PRIVILEGED,
234 	PRIV_UNPRIVILEGED
235 };
236 int	 may_read(enum priv_context, void *, size_t);
237 void	 must_read(enum priv_context, void *, size_t);
238 void	 must_write(enum priv_context, const void *, size_t);
239 void	 priv_privileged_fd(int);
240 void	 priv_unprivileged_fd(int);
241 int	 priv_fd(enum priv_context);
242 int	 receive_fd(enum priv_context);
243 void	 send_fd(enum priv_context, int);
244 
245 /* interfaces-*.c */
246 
247 /* BPF filter to get revelant information from interfaces */
248 /* LLDP: "ether proto 0x88cc and ether dst 01:80:c2:00:00:0e" */
249 /* FDP: "ether dst 01:e0:52:cc:cc:cc" */
250 /* CDP: "ether dst 01:00:0c:cc:cc:cc" */
251 /* SONMP: "ether dst 01:00:81:00:01:00" */
252 /* EDP: "ether dst 00:e0:2b:00:00:00" */
253 /* For optimization purpose, we first check if the first bit of the
254    first byte is 1. if not, this can only be an EDP packet:
255 
256    tcpdump -dd "(ether[0] & 1 = 1 and
257                  ((ether proto 0x88cc and (ether dst 01:80:c2:00:00:0e or
258                                            ether dst 01:80:c2:00:00:03 or
259                                            ether dst 01:80:c2:00:00:00)) or
260                   (ether dst 01:e0:52:cc:cc:cc) or
261                   (ether dst 01:00:0c:cc:cc:cc) or
262                   (ether dst 01:00:81:00:01:00))) or
263                 (ether dst 00:e0:2b:00:00:00)"
264 */
265 
266 #define ETH_P_LLDP 0x88cc
267 #define LLDPD_FILTER_F				\
268 	{ 0x30, 0, 0, 0x00000000 },		\
269 	{ 0x54, 0, 0, 0x00000001 },		\
270 	{ 0x15, 0, 16, 0x00000001 },		\
271 	{ 0x28, 0, 0, 0x0000000c },		\
272 	{ 0x15, 0, 6, ETH_P_LLDP },		\
273 	{ 0x20, 0, 0, 0x00000002 },		\
274 	{ 0x15, 2, 0, 0xc200000e },		\
275 	{ 0x15, 1, 0, 0xc2000003 },		\
276 	{ 0x15, 0, 2, 0xc2000000 },		\
277 	{ 0x28, 0, 0, 0x00000000 },		\
278 	{ 0x15, 12, 13, 0x00000180 },		\
279 	{ 0x20, 0, 0, 0x00000002 },		\
280 	{ 0x15, 0, 2, 0x52cccccc },		\
281 	{ 0x28, 0, 0, 0x00000000 },		\
282 	{ 0x15, 8, 9, 0x000001e0 },		\
283 	{ 0x15, 1, 0, 0x0ccccccc },		\
284 	{ 0x15, 0, 2, 0x81000100 },		\
285 	{ 0x28, 0, 0, 0x00000000 },		\
286 	{ 0x15, 4, 5, 0x00000100 },		\
287 	{ 0x20, 0, 0, 0x00000002 },		\
288 	{ 0x15, 0, 3, 0x2b000000 },		\
289 	{ 0x28, 0, 0, 0x00000000 },		\
290 	{ 0x15, 0, 1, 0x000000e0 },		\
291 	{ 0x6, 0, 0, 0x00040000 },		\
292 	{ 0x6, 0, 0, 0x00000000 }
293 
294 /* This function is responsible to refresh information about interfaces. It is
295  * OS specific but should be present for each OS. It can use the functions in
296  * `interfaces.c` as helper by providing a list of OS-independent interface
297  * devices. */
298 void     interfaces_update(struct lldpd *);
299 
300 /* interfaces.c */
301 /* An interface cannot be both physical and (bridge or bond or vlan) */
302 #define IFACE_PHYSICAL_T    (1 << 0) /* Physical interface */
303 #define IFACE_BRIDGE_T      (1 << 1) /* Bridge interface */
304 #define IFACE_BOND_T        (1 << 2) /* Bond interface */
305 #define IFACE_VLAN_T        (1 << 3) /* VLAN interface */
306 #define IFACE_WIRELESS_T    (1 << 4) /* Wireless interface */
307 #define IFACE_BRIDGE_VLAN_T (1 << 5) /* Bridge-aware VLAN interface */
308 
309 #define MAX_VLAN 4096
310 #define VLAN_BITMAP_LEN (MAX_VLAN / 32)
311 struct interfaces_device {
312 	TAILQ_ENTRY(interfaces_device) next;
313 	int   ignore;		/* Ignore this interface */
314 	int   index;		/* Index */
315 	char *name;		/* Name */
316 	char *alias;		/* Alias */
317 	char *address;		/* MAC address */
318 	char *driver;		/* Driver */
319 	int   flags;		/* Flags (IFF_*) */
320 	int   mtu;		/* MTU */
321 	int   type;		/* Type (see IFACE_*_T) */
322 	uint32_t vlan_bmap[VLAN_BITMAP_LEN];	/* If a VLAN, what are the VLAN ID? */
323 	int   pvid;		/* If a VLAN, what is the default VLAN? */
324 	struct interfaces_device *lower; /* Lower interface (for a VLAN for example) */
325 	struct interfaces_device *upper; /* Upper interface (for a bridge or a bond) */
326 
327 	/* The following are OS specific. Should be static (no free function) */
328 #ifdef HOST_OS_LINUX
329 	int lower_idx;		/* Index to lower interface */
330 	int upper_idx;		/* Index to upper interface */
331 #endif
332 };
333 struct interfaces_address {
334 	TAILQ_ENTRY(interfaces_address) next;
335 	int index;			 /* Index */
336 	int flags;			 /* Flags */
337 	struct sockaddr_storage address; /* Address */
338 
339 	/* The following are OS specific. */
340 	/* Nothing yet. */
341 };
342 TAILQ_HEAD(interfaces_device_list,  interfaces_device);
343 TAILQ_HEAD(interfaces_address_list, interfaces_address);
344 void interfaces_free_device(struct interfaces_device *);
345 void interfaces_free_address(struct interfaces_address *);
346 void interfaces_free_devices(struct interfaces_device_list *);
347 void interfaces_free_addresses(struct interfaces_address_list *);
348 struct interfaces_device* interfaces_indextointerface(
349 	struct interfaces_device_list *,
350 	int);
351 struct interfaces_device* interfaces_nametointerface(
352 	struct interfaces_device_list *,
353 	const char *);
354 
355 void interfaces_helper_promisc(struct lldpd *,
356     struct lldpd_hardware *);
357 void interfaces_helper_allowlist(struct lldpd *,
358     struct interfaces_device_list *);
359 void interfaces_helper_chassis(struct lldpd *,
360     struct interfaces_device_list *);
361 void interfaces_helper_add_hardware(struct lldpd *,
362     struct lldpd_hardware *);
363 void interfaces_helper_physical(struct lldpd *,
364     struct interfaces_device_list *,
365     struct lldpd_ops *,
366     int(*init)(struct lldpd *, struct lldpd_hardware *));
367 void interfaces_helper_port_name_desc(struct lldpd *,
368     struct lldpd_hardware *,
369     struct interfaces_device *);
370 void interfaces_helper_mgmt(struct lldpd *,
371     struct interfaces_address_list *,
372     struct interfaces_device_list *);
373 #ifdef ENABLE_DOT1
374 void interfaces_helper_vlan(struct lldpd *,
375     struct interfaces_device_list *);
376 #endif
377 int interfaces_send_helper(struct lldpd *,
378     struct lldpd_hardware *, char *, size_t);
379 
380 void interfaces_setup_multicast(struct lldpd *, const char *, int);
381 int interfaces_routing_enabled(struct lldpd *);
382 void interfaces_cleanup(struct lldpd *);
383 
384 #ifdef HOST_OS_LINUX
385 /* netlink.c */
386 struct interfaces_device_list  *netlink_get_interfaces(struct lldpd *);
387 struct interfaces_address_list *netlink_get_addresses(struct lldpd *);
388 void netlink_cleanup(struct lldpd *);
389 struct lldpd_netlink;
390 #endif
391 
392 #ifndef HOST_OS_LINUX
393 /* interfaces-bpf.c */
394 int ifbpf_phys_init(struct lldpd *, struct lldpd_hardware *);
395 #endif
396 
397 /* pattern.c */
398 int pattern_match(char *, char *, int);
399 
400 /* bitmap.c */
401 void bitmap_set(uint32_t *bmap, uint16_t vlan_id);
402 int bitmap_isempty(uint32_t *bmap);
403 unsigned int bitmap_numbits(uint32_t *bmap);
404 
405 struct lldpd {
406 	int			 g_sock;
407 	struct event_base	*g_base;
408 #ifdef USE_SNMP
409 #endif
410 
411 	struct lldpd_config	 g_config;
412 
413 	struct protocol		*g_protocols;
414 	int			 g_lastrid;
415 	struct event		*g_main_loop;
416 	struct event		*g_cleanup_timer;
417 #ifdef USE_SNMP
418 	int			 g_snmp;
419 	struct event		*g_snmp_timeout;
420 	void			*g_snmp_fds;
421 	const char		*g_snmp_agentx;
422 #endif /* USE_SNMP */
423 
424 	/* Unix socket handling */
425 	const char		*g_ctlname;
426 	int			 g_ctl;
427 	struct event		*g_iface_event; /* Triggered when there is an interface change */
428 	struct event		*g_iface_timer_event; /* Triggered one second after last interface change */
429 	void(*g_iface_cb)(struct lldpd *);	      /* Called when there is an interface change */
430 
431 	char			*g_lsb_release;
432 
433 #ifdef HOST_OS_LINUX
434 	struct lldpd_netlink	*g_netlink;
435 #endif
436 
437 	struct lldpd_port	*g_default_local_port;
438 #define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
439 	TAILQ_HEAD(, lldpd_chassis) g_chassis;
440 	TAILQ_HEAD(, lldpd_hardware) g_hardware;
441 };
442 
443 #endif /* _LLDPD_H */
444