]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/lldpd.h
priv: lock BPF interface on BSD
[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 #define _GNU_SOURCE 1
21
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 #ifdef HAVE_VALGRIND_VALGRIND_H
27 # include <valgrind/valgrind.h>
28 #else
29 # define RUNNING_ON_VALGRIND 0
30 #endif
31
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <string.h>
35 #include <sys/queue.h>
36 #include <sys/types.h>
37 #include <netinet/if_ether.h>
38 #include <netinet/in.h>
39 #include <sys/un.h>
40
41 #include "lldp-tlv.h"
42 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
43 # include "cdp.h"
44 #endif
45 #ifdef ENABLE_SONMP
46 # include "sonmp.h"
47 #endif
48 #ifdef ENABLE_EDP
49 # include "edp.h"
50 #endif
51
52 #include "../compat/compat.h"
53 #include "../marshal.h"
54 #include "../log.h"
55 #include "../ctl.h"
56 #include "../lldpd-structs.h"
57
58 /* We don't want to import event2/event.h. We only need those as
59 opaque structs. */
60 struct event;
61 struct event_base;
62
63 #define SYSFS_CLASS_NET "/sys/class/net/"
64 #define SYSFS_CLASS_DMI "/sys/class/dmi/id/"
65 #define LLDPD_TTL 120
66 #define LLDPD_TX_INTERVAL 30
67 #define LLDPD_TX_MSGDELAY 1
68 #define LLDPD_PID_FILE "/var/run/lldpd.pid"
69
70 #define USING_AGENTX_SUBAGENT_MODULE 1
71
72 #define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
73 #define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
74 #define PROTO_GUESS_SIG char *, int
75
76 struct protocol {
77 int mode; /* > 0 mode identifier (unique per protocol) */
78 int enabled; /* Is this protocol enabled? */
79 char *name; /* Name of protocol */
80 char arg; /* Argument to enable this protocol */
81 int(*send)(PROTO_SEND_SIG); /* How to send a frame */
82 int(*decode)(PROTO_DECODE_SIG); /* How to decode a frame */
83 int(*guess)(PROTO_GUESS_SIG); /* Can be NULL, use MAC address in this case */
84 u_int8_t mac[ETHER_ADDR_LEN]; /* Destination MAC address used by this protocol */
85 };
86
87 #define SMART_HIDDEN(port) (port->p_hidden_in)
88
89 struct lldpd {
90 int g_sock;
91 struct event_base *g_base;
92 #ifdef USE_SNMP
93 #endif
94
95 struct lldpd_config g_config;
96
97 struct protocol *g_protocols;
98 int g_lastrid;
99 struct event *g_main_loop;
100 #ifdef USE_SNMP
101 int g_snmp;
102 struct event *g_snmp_timeout;
103 void *g_snmp_fds;
104 char *g_snmp_agentx;
105 #endif /* USE_SNMP */
106
107 /* Unix socket handling */
108 int g_ctl;
109 struct event *g_ctl_event;
110 struct event *g_iface_event; /* Triggered when there is an interface change */
111 struct event *g_iface_timer_event; /* Triggered one second after last interface change */
112
113 char *g_lsb_release;
114
115 #define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
116 TAILQ_HEAD(, lldpd_chassis) g_chassis;
117 TAILQ_HEAD(, lldpd_hardware) g_hardware;
118 };
119
120 /* lldpd.c */
121 struct lldpd_hardware *lldpd_get_hardware(struct lldpd *,
122 char *, int, struct lldpd_ops *);
123 struct lldpd_hardware *lldpd_alloc_hardware(struct lldpd *, char *, int);
124 void lldpd_hardware_cleanup(struct lldpd*, struct lldpd_hardware *);
125 struct lldpd_mgmt *lldpd_alloc_mgmt(int family, void *addr, size_t addrsize, u_int32_t iface);
126 void lldpd_recv(struct lldpd *, struct lldpd_hardware *, int);
127 void lldpd_send(struct lldpd_hardware *);
128 void lldpd_loop(struct lldpd *);
129 int lldpd_main(int, char **);
130 void lldpd_update_localports(struct lldpd *);
131
132 /* frame.c */
133 u_int16_t frame_checksum(const u_int8_t *, int, int);
134
135 /* event.c */
136 void levent_loop(struct lldpd *);
137 void levent_hardware_init(struct lldpd_hardware *);
138 void levent_hardware_add_fd(struct lldpd_hardware *, int);
139 void levent_hardware_release(struct lldpd_hardware *);
140 void levent_ctl_notify(char *, int, struct lldpd_port *);
141 void levent_send_now(struct lldpd *);
142 int levent_iface_subscribe(struct lldpd *, int);
143 void levent_schedule_pdu(struct lldpd_hardware *);
144
145 /* lldp.c */
146 int lldp_send(PROTO_SEND_SIG);
147 int lldp_decode(PROTO_DECODE_SIG);
148
149 /* cdp.c */
150 #ifdef ENABLE_CDP
151 int cdpv1_send(PROTO_SEND_SIG);
152 int cdpv2_send(PROTO_SEND_SIG);
153 int cdpv1_guess(PROTO_GUESS_SIG);
154 int cdpv2_guess(PROTO_GUESS_SIG);
155 #endif
156 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
157 int cdp_decode(PROTO_DECODE_SIG);
158 #endif
159 #ifdef ENABLE_FDP
160 int fdp_send(PROTO_SEND_SIG);
161 #endif
162
163 #ifdef ENABLE_SONMP
164 /* sonmp.c */
165 int sonmp_send(PROTO_SEND_SIG);
166 int sonmp_decode(PROTO_DECODE_SIG);
167 #endif
168
169 #ifdef ENABLE_EDP
170 /* edp.c */
171 int edp_send(PROTO_SEND_SIG);
172 int edp_decode(PROTO_DECODE_SIG);
173 #endif
174
175 /* dmi.c */
176 #ifdef ENABLE_LLDPMED
177 char *dmi_hw(void);
178 char *dmi_fw(void);
179 char *dmi_sn(void);
180 char *dmi_manuf(void);
181 char *dmi_model(void);
182 char *dmi_asset(void);
183 #endif
184
185 #ifdef USE_SNMP
186 /* agent.c */
187 void agent_shutdown(void);
188 void agent_init(struct lldpd *, char *);
189 void agent_notify(struct lldpd_hardware *, int, struct lldpd_port *);
190 #endif
191
192 /* agent_priv.c */
193 void agent_priv_register_domain(void);
194
195 /* client.c */
196 int
197 client_handle_client(struct lldpd *cfg,
198 ssize_t(*send)(void *, int, void *, size_t),
199 void *,
200 enum hmsg_type type, void *buffer, size_t n,
201 int*);
202
203 /* priv.c */
204 void priv_init(char*, int, uid_t, gid_t);
205 void priv_ctl_cleanup(void);
206 char *priv_gethostbyname(void);
207 #ifdef HOST_OS_LINUX
208 int priv_open(char*);
209 int priv_ethtool(char*, void*, size_t);
210 #endif
211 int priv_iface_init(int, char *);
212 int priv_iface_multicast(const char *, u_int8_t *, int);
213 int priv_snmp_socket(struct sockaddr_un *);
214
215 /* privsep_fdpass.c */
216 int receive_fd(int);
217 void send_fd(int, int);
218
219 /* interfaces-*.c */
220
221 /* BPF filter to get revelant information from interfaces */
222 /* LLDP: "ether proto 0x88cc and ether dst 01:80:c2:00:00:0e" */
223 /* FDP: "ether dst 01:e0:52:cc:cc:cc" */
224 /* CDP: "ether dst 01:00:0c:cc:cc:cc" */
225 /* SONMP: "ether dst 01:00:81:00:01:00" */
226 /* EDP: "ether dst 00:e0:2b:00:00:00" */
227 /* For optimization purpose, we first check if the first bit of the
228 first byte is 1. if not, this can only be an EDP packet:
229
230 tcpdump -dd "(ether[0] & 1 = 1 and
231 ((ether proto 0x88cc and ether dst 01:80:c2:00:00:0e) or
232 (ether dst 01:e0:52:cc:cc:cc) or
233 (ether dst 01:00:0c:cc:cc:cc) or
234 (ether dst 01:00:81:00:01:00))) or
235 (ether dst 00:e0:2b:00:00:00)"
236 */
237
238 #define LLDPD_FILTER_F \
239 { 0x30, 0, 0, 0x00000000 }, \
240 { 0x54, 0, 0, 0x00000001 }, \
241 { 0x15, 0, 14, 0x00000001 }, \
242 { 0x28, 0, 0, 0x0000000c }, \
243 { 0x15, 0, 4, 0x000088cc }, \
244 { 0x20, 0, 0, 0x00000002 }, \
245 { 0x15, 0, 2, 0xc200000e }, \
246 { 0x28, 0, 0, 0x00000000 }, \
247 { 0x15, 12, 13, 0x00000180 }, \
248 { 0x20, 0, 0, 0x00000002 }, \
249 { 0x15, 0, 2, 0x52cccccc }, \
250 { 0x28, 0, 0, 0x00000000 }, \
251 { 0x15, 8, 9, 0x000001e0 }, \
252 { 0x15, 1, 0, 0x0ccccccc }, \
253 { 0x15, 0, 2, 0x81000100 }, \
254 { 0x28, 0, 0, 0x00000000 }, \
255 { 0x15, 4, 5, 0x00000100 }, \
256 { 0x20, 0, 0, 0x00000002 }, \
257 { 0x15, 0, 3, 0x2b000000 }, \
258 { 0x28, 0, 0, 0x00000000 }, \
259 { 0x15, 0, 1, 0x000000e0 }, \
260 { 0x6, 0, 0, 0x0000ffff }, \
261 { 0x6, 0, 0, 0x00000000 },
262
263 /* This function is responsible to refresh information about interfaces. It is
264 * OS specific but should be present for each OS. It can use the functions in
265 * `interfaces.c` as helper by providing a list of OS-independent interface
266 * devices. */
267 void interfaces_update(struct lldpd *);
268
269 /* interfaces.c */
270 /* An interface cannot be both physical and (bridge or bond or vlan) */
271 #define IFACE_PHYSICAL_T (1 << 0) /* Physical interface */
272 #define IFACE_BRIDGE_T (1 << 1) /* Bridge interface */
273 #define IFACE_BOND_T (1 << 2) /* Bond interface */
274 #define IFACE_VLAN_T (1 << 3) /* VLAN interface */
275 #define IFACE_WIRELESS_T (1 << 4) /* Wireless interface */
276 struct interfaces_device {
277 TAILQ_ENTRY(interfaces_device) next;
278 int index; /* Index */
279 char *name; /* Name */
280 char *alias; /* Alias */
281 char *address; /* MAC address */
282 char *driver; /* Driver (for whitelisting purpose) */
283 int flags; /* Flags (IFF_*) */
284 int mtu; /* MTU */
285 int type; /* Type (see IFACE_*_T) */
286 int vlanid; /* If a VLAN, what is the VLAN ID? */
287 struct interfaces_device *lower; /* Lower interface (for a VLAN for example) */
288 struct interfaces_device *upper; /* Upper interface (for a bridge or a bond) */
289
290 /* The following are OS specific. Should be static (no free function) */
291 #ifdef HOST_OS_LINUX
292 int lower_idx; /* Index to lower interface */
293 int upper_idx; /* Index to upper interface */
294 int txqueue; /* Transmit queue length */
295 #endif
296 };
297 struct interfaces_address {
298 TAILQ_ENTRY(interfaces_address) next;
299 int index; /* Index */
300 int flags; /* Flags */
301 struct sockaddr_storage address; /* Address */
302
303 /* The following are OS specific. */
304 /* Nothing yet. */
305 };
306 TAILQ_HEAD(interfaces_device_list, interfaces_device);
307 TAILQ_HEAD(interfaces_address_list, interfaces_address);
308 void interfaces_free_device(struct interfaces_device *);
309 void interfaces_free_address(struct interfaces_address *);
310 void interfaces_free_devices(struct interfaces_device_list *);
311 void interfaces_free_addresses(struct interfaces_address_list *);
312 struct interfaces_device* interfaces_indextointerface(
313 struct interfaces_device_list *,
314 int);
315 struct interfaces_device* interfaces_nametointerface(
316 struct interfaces_device_list *,
317 const char *);
318
319 void interfaces_helper_whitelist(struct lldpd *,
320 struct interfaces_device_list *);
321 void interfaces_helper_chassis(struct lldpd *,
322 struct interfaces_device_list *);
323 void interfaces_helper_physical(struct lldpd *,
324 struct interfaces_device_list *,
325 struct lldpd_ops *,
326 int(*init)(struct lldpd *, struct lldpd_hardware *));
327 void interfaces_helper_port_name_desc(struct lldpd_hardware *,
328 struct interfaces_device *);
329 void interfaces_helper_mgmt(struct lldpd *,
330 struct interfaces_address_list *);
331 #ifdef ENABLE_DOT1
332 void interfaces_helper_vlan(struct lldpd *,
333 struct interfaces_device_list *);
334 #endif
335
336 void interfaces_setup_multicast(struct lldpd *, const char *, int);
337
338 #ifdef HOST_OS_LINUX
339 /* netlink.c */
340 struct interfaces_device_list *netlink_get_interfaces(void);
341 struct interfaces_address_list *netlink_get_addresses(void);
342 int netlink_subscribe_changes(void);
343 #endif
344
345 #endif /* _LLDPD_H */