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