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