]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/lldpd.h
netlink: handle blocking read from netlink socket
[thirdparty/lldpd.git] / src / daemon / lldpd.h
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 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
73
74 #define USING_AGENTX_SUBAGENT_MODULE 1
75
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
79
80 #define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR))
81
82 struct protocol {
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 */
93 };
94
95 #define SMART_HIDDEN(port) (port->p_hidden_in)
96
97 struct lldpd;
98
99 /* lldpd.c */
100 struct lldpd_hardware *lldpd_get_hardware(struct lldpd *,
101 char *, int);
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 *);
112
113 /* frame.c */
114 u_int16_t frame_checksum(const u_int8_t *, int, int);
115
116 /* event.c */
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);
130 #ifdef HOST_OS_LINUX
131 void levent_recv_error(int, const char*);
132 #endif
133
134 /* lldp.c */
135 int lldp_send_shutdown(PROTO_SEND_SIG);
136 int lldp_send(PROTO_SEND_SIG);
137 int lldp_decode(PROTO_DECODE_SIG);
138
139 /* cdp.c */
140 #ifdef ENABLE_CDP
141 int cdpv1_send(PROTO_SEND_SIG);
142 int cdpv2_send(PROTO_SEND_SIG);
143 int cdpv1_guess(PROTO_GUESS_SIG);
144 int cdpv2_guess(PROTO_GUESS_SIG);
145 #endif
146 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
147 int cdp_decode(PROTO_DECODE_SIG);
148 #endif
149 #ifdef ENABLE_FDP
150 int fdp_send(PROTO_SEND_SIG);
151 #endif
152
153 #ifdef ENABLE_SONMP
154 /* sonmp.c */
155 int sonmp_send(PROTO_SEND_SIG);
156 int sonmp_decode(PROTO_DECODE_SIG);
157 #endif
158
159 #ifdef ENABLE_EDP
160 /* edp.c */
161 int edp_send(PROTO_SEND_SIG);
162 int edp_decode(PROTO_DECODE_SIG);
163 #endif
164
165 /* dmi.c */
166 #ifdef ENABLE_LLDPMED
167 char *dmi_hw(void);
168 char *dmi_fw(void);
169 char *dmi_sn(void);
170 char *dmi_manuf(void);
171 char *dmi_model(void);
172 char *dmi_asset(void);
173 #endif
174
175 #ifdef USE_SNMP
176 /* agent.c */
177 void agent_shutdown(void);
178 void agent_init(struct lldpd *, const char *);
179 void agent_notify(struct lldpd_hardware *, int, struct lldpd_port *);
180 #endif
181
182 #ifdef ENABLE_PRIVSEP
183 /* agent_priv.c */
184 void agent_priv_register_domain(void);
185 #endif
186
187 /* client.c */
188 int
189 client_handle_client(struct lldpd *cfg,
190 ssize_t(*send)(void *, int, void *, size_t),
191 void *,
192 enum hmsg_type type, void *buffer, size_t n,
193 int*);
194
195 /* priv.c */
196 void priv_init(const char*, int, uid_t, gid_t);
197 void priv_wait(void);
198 void priv_ctl_cleanup(const char *ctlname);
199 char *priv_gethostname(void);
200 #ifdef HOST_OS_LINUX
201 int priv_open(char*);
202 void asroot_open(void);
203 #endif
204 int priv_iface_init(int, char *);
205 int asroot_iface_init_os(int, char *, int *);
206 int priv_iface_multicast(const char *, const u_int8_t *, int);
207 int priv_iface_description(const char *, const char *);
208 int asroot_iface_description_os(const char *, const char *);
209 int priv_iface_promisc(const char*);
210 int asroot_iface_promisc_os(const char *);
211 int priv_snmp_socket(struct sockaddr_un *);
212
213 enum priv_cmd {
214 PRIV_PING,
215 PRIV_DELETE_CTL_SOCKET,
216 PRIV_GET_HOSTNAME,
217 PRIV_OPEN,
218 PRIV_IFACE_INIT,
219 PRIV_IFACE_MULTICAST,
220 PRIV_IFACE_DESCRIPTION,
221 PRIV_IFACE_PROMISC,
222 PRIV_SNMP_SOCKET,
223 };
224
225 /* priv-seccomp.c */
226 #if defined USE_SECCOMP && defined ENABLE_PRIVSEP
227 int priv_seccomp_init(int, int);
228 #endif
229
230 /* privsep_io.c */
231 enum priv_context {
232 PRIV_PRIVILEGED,
233 PRIV_UNPRIVILEGED
234 };
235 int may_read(enum priv_context, void *, size_t);
236 void must_read(enum priv_context, void *, size_t);
237 void must_write(enum priv_context, const void *, size_t);
238 void priv_privileged_fd(int);
239 void priv_unprivileged_fd(int);
240 int priv_fd(enum priv_context);
241 int receive_fd(enum priv_context);
242 void send_fd(enum priv_context, int);
243
244 /* interfaces-*.c */
245
246 /* BPF filter to get revelant information from interfaces */
247 /* LLDP: "ether proto 0x88cc and ether dst 01:80:c2:00:00:0e" */
248 /* FDP: "ether dst 01:e0:52:cc:cc:cc" */
249 /* CDP: "ether dst 01:00:0c:cc:cc:cc" */
250 /* SONMP: "ether dst 01:00:81:00:01:00" */
251 /* EDP: "ether dst 00:e0:2b:00:00:00" */
252 /* For optimization purpose, we first check if the first bit of the
253 first byte is 1. if not, this can only be an EDP packet:
254
255 tcpdump -dd "(ether[0] & 1 = 1 and
256 ((ether proto 0x88cc and (ether dst 01:80:c2:00:00:0e or
257 ether dst 01:80:c2:00:00:03 or
258 ether dst 01:80:c2:00:00:00)) or
259 (ether dst 01:e0:52:cc:cc:cc) or
260 (ether dst 01:00:0c:cc:cc:cc) or
261 (ether dst 01:00:81:00:01:00))) or
262 (ether dst 00:e0:2b:00:00:00)"
263 */
264
265 #define LLDPD_FILTER_F \
266 { 0x30, 0, 0, 0x00000000 }, \
267 { 0x54, 0, 0, 0x00000001 }, \
268 { 0x15, 0, 16, 0x00000001 }, \
269 { 0x28, 0, 0, 0x0000000c }, \
270 { 0x15, 0, 6, 0x000088cc }, \
271 { 0x20, 0, 0, 0x00000002 }, \
272 { 0x15, 2, 0, 0xc200000e }, \
273 { 0x15, 1, 0, 0xc2000003 }, \
274 { 0x15, 0, 2, 0xc2000000 }, \
275 { 0x28, 0, 0, 0x00000000 }, \
276 { 0x15, 12, 13, 0x00000180 }, \
277 { 0x20, 0, 0, 0x00000002 }, \
278 { 0x15, 0, 2, 0x52cccccc }, \
279 { 0x28, 0, 0, 0x00000000 }, \
280 { 0x15, 8, 9, 0x000001e0 }, \
281 { 0x15, 1, 0, 0x0ccccccc }, \
282 { 0x15, 0, 2, 0x81000100 }, \
283 { 0x28, 0, 0, 0x00000000 }, \
284 { 0x15, 4, 5, 0x00000100 }, \
285 { 0x20, 0, 0, 0x00000002 }, \
286 { 0x15, 0, 3, 0x2b000000 }, \
287 { 0x28, 0, 0, 0x00000000 }, \
288 { 0x15, 0, 1, 0x000000e0 }, \
289 { 0x6, 0, 0, 0x00040000 }, \
290 { 0x6, 0, 0, 0x00000000 }
291
292 /* This function is responsible to refresh information about interfaces. It is
293 * OS specific but should be present for each OS. It can use the functions in
294 * `interfaces.c` as helper by providing a list of OS-independent interface
295 * devices. */
296 void interfaces_update(struct lldpd *);
297
298 /* interfaces.c */
299 /* An interface cannot be both physical and (bridge or bond or vlan) */
300 #define IFACE_PHYSICAL_T (1 << 0) /* Physical interface */
301 #define IFACE_BRIDGE_T (1 << 1) /* Bridge interface */
302 #define IFACE_BOND_T (1 << 2) /* Bond interface */
303 #define IFACE_VLAN_T (1 << 3) /* VLAN interface */
304 #define IFACE_WIRELESS_T (1 << 4) /* Wireless interface */
305 struct interfaces_device {
306 TAILQ_ENTRY(interfaces_device) next;
307 int ignore; /* Ignore this interface */
308 int index; /* Index */
309 char *name; /* Name */
310 char *alias; /* Alias */
311 char *address; /* MAC address */
312 char *driver; /* Driver (for whitelisting purpose) */
313 int flags; /* Flags (IFF_*) */
314 int mtu; /* MTU */
315 int type; /* Type (see IFACE_*_T) */
316 int vlanid; /* If a VLAN, what is the VLAN ID? */
317 struct interfaces_device *lower; /* Lower interface (for a VLAN for example) */
318 struct interfaces_device *upper; /* Upper interface (for a bridge or a bond) */
319
320 /* The following are OS specific. Should be static (no free function) */
321 #ifdef HOST_OS_LINUX
322 int lower_idx; /* Index to lower interface */
323 int upper_idx; /* Index to upper interface */
324 #endif
325 };
326 struct interfaces_address {
327 TAILQ_ENTRY(interfaces_address) next;
328 int index; /* Index */
329 int flags; /* Flags */
330 struct sockaddr_storage address; /* Address */
331
332 /* The following are OS specific. */
333 /* Nothing yet. */
334 };
335 TAILQ_HEAD(interfaces_device_list, interfaces_device);
336 TAILQ_HEAD(interfaces_address_list, interfaces_address);
337 void interfaces_free_device(struct interfaces_device *);
338 void interfaces_free_address(struct interfaces_address *);
339 void interfaces_free_devices(struct interfaces_device_list *);
340 void interfaces_free_addresses(struct interfaces_address_list *);
341 struct interfaces_device* interfaces_indextointerface(
342 struct interfaces_device_list *,
343 int);
344 struct interfaces_device* interfaces_nametointerface(
345 struct interfaces_device_list *,
346 const char *);
347
348 void interfaces_helper_promisc(struct lldpd *,
349 struct lldpd_hardware *);
350 void interfaces_helper_whitelist(struct lldpd *,
351 struct interfaces_device_list *);
352 void interfaces_helper_chassis(struct lldpd *,
353 struct interfaces_device_list *);
354 void interfaces_helper_add_hardware(struct lldpd *,
355 struct lldpd_hardware *);
356 void interfaces_helper_physical(struct lldpd *,
357 struct interfaces_device_list *,
358 struct lldpd_ops *,
359 int(*init)(struct lldpd *, struct lldpd_hardware *));
360 void interfaces_helper_port_name_desc(struct lldpd *,
361 struct lldpd_hardware *,
362 struct interfaces_device *);
363 void interfaces_helper_mgmt(struct lldpd *,
364 struct interfaces_address_list *);
365 #ifdef ENABLE_DOT1
366 void interfaces_helper_vlan(struct lldpd *,
367 struct interfaces_device_list *);
368 #endif
369 int interfaces_send_helper(struct lldpd *,
370 struct lldpd_hardware *, char *, size_t);
371
372 void interfaces_setup_multicast(struct lldpd *, const char *, int);
373 int interfaces_routing_enabled(struct lldpd *);
374 void interfaces_cleanup(struct lldpd *);
375
376 #ifdef HOST_OS_LINUX
377 /* netlink.c */
378 struct interfaces_device_list *netlink_get_interfaces(struct lldpd *);
379 struct interfaces_address_list *netlink_get_addresses(struct lldpd *);
380 void netlink_cleanup(struct lldpd *);
381 struct lldpd_netlink;
382 #endif
383
384 #ifndef HOST_OS_LINUX
385 int ifbpf_phys_init(struct lldpd *, struct lldpd_hardware *);
386 #endif
387
388 /* pattern.c */
389 int pattern_match(char *, char *, int);
390
391 struct lldpd {
392 int g_sock;
393 struct event_base *g_base;
394 #ifdef USE_SNMP
395 #endif
396
397 struct lldpd_config g_config;
398
399 struct protocol *g_protocols;
400 int g_lastrid;
401 struct event *g_main_loop;
402 struct event *g_cleanup_timer;
403 #ifdef USE_SNMP
404 int g_snmp;
405 struct event *g_snmp_timeout;
406 void *g_snmp_fds;
407 const char *g_snmp_agentx;
408 #endif /* USE_SNMP */
409
410 /* Unix socket handling */
411 const char *g_ctlname;
412 int g_ctl;
413 struct event *g_iface_event; /* Triggered when there is an interface change */
414 struct event *g_iface_timer_event; /* Triggered one second after last interface change */
415 void(*g_iface_cb)(struct lldpd *); /* Called when there is an interface change */
416
417 char *g_lsb_release;
418
419 #ifdef HOST_OS_LINUX
420 struct lldpd_netlink *g_netlink;
421 #endif
422
423 struct lldpd_port *g_default_local_port;
424 #define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
425 TAILQ_HEAD(, lldpd_chassis) g_chassis;
426 TAILQ_HEAD(, lldpd_hardware) g_hardware;
427 };
428
429 #endif /* _LLDPD_H */