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