2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 #include <sys/queue.h>
28 #ifndef INCLUDE_LINUX_IF_H
31 #include <arpa/inet.h>
35 #include <net/ethernet.h>
36 #include <netinet/in.h>
37 #include <linux/ethtool.h>
41 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
51 #define SYSFS_CLASS_NET "/sys/class/net/"
52 #define SYSFS_CLASS_DMI "/sys/class/dmi/id/"
54 #define LLDPD_TX_DELAY 30
55 #define LLDPD_TX_MSGDELAY 1
56 #define LLDPD_CTL_SOCKET "/var/run/lldpd.socket"
57 #define LLDPD_PID_FILE "/var/run/lldpd.pid"
59 #define UNIX_PATH_MAX 108
61 #define USING_AGENTX_SUBAGENT_MODULE 1
65 TAILQ_ENTRY(lldpd_vlan
) v_entries
;
69 #define STRUCT_LLDPD_VLAN "(Lsw)"
73 #define STRUCT_LLDPD_MED_POLICY "(bbbwbb)"
74 struct lldpd_med_policy
{
83 #define STRUCT_LLDPD_MED_LOC "(bC)"
84 struct lldpd_med_loc
{
91 struct lldpd_chassis
{
92 TAILQ_ENTRY(lldpd_chassis
) c_entries
;
93 u_int16_t c_refcount
; /* Reference count by ports */
94 u_int16_t c_index
; /* Monotonic index */
95 u_int8_t c_protocol
; /* Protocol used to get this chassis */
96 u_int8_t c_id_subtype
;
102 u_int16_t c_cap_available
;
103 u_int16_t c_cap_enabled
;
107 struct in_addr c_mgmt
;
110 #ifdef ENABLE_LLDPMED
111 #define STRUCT_LLDPD_CHASSIS_MED "wbsssssss"
112 u_int16_t c_med_cap_available
;
122 #define STRUCT_LLDPD_CHASSIS_MED ""
126 #define STRUCT_LLDPD_CHASSIS "(LwwbbCsswwwll" STRUCT_LLDPD_CHASSIS_MED ")"
129 TAILQ_ENTRY(lldpd_port
) p_entries
;
130 struct lldpd_chassis
*p_chassis
; /* Attached chassis */
131 time_t p_lastchange
; /* Time of last change of values */
132 time_t p_lastupdate
; /* Time of last update received */
133 struct lldpd_frame
*p_lastframe
; /* Frame received during last update */
134 u_int8_t p_protocol
; /* Protocol used to get this port */
135 u_int8_t p_id_subtype
;
142 #define STRUCT_LLDPD_PORT_DOT3 "lbbww"
144 u_int32_t p_aggregid
;
145 u_int8_t p_autoneg_support
;
146 u_int8_t p_autoneg_enabled
;
147 u_int16_t p_autoneg_advertised
;
148 u_int16_t p_mau_type
;
150 #define STRUCT_LLDPD_PORT_DOT3 ""
153 #ifdef ENABLE_LLDPMED
154 #define STRUCT_LLDPD_PORT_MED "w" \
155 STRUCT_LLDPD_MED_POLICY \
156 STRUCT_LLDPD_MED_POLICY \
157 STRUCT_LLDPD_MED_POLICY \
158 STRUCT_LLDPD_MED_POLICY \
159 STRUCT_LLDPD_MED_POLICY \
160 STRUCT_LLDPD_MED_POLICY \
161 STRUCT_LLDPD_MED_POLICY \
162 STRUCT_LLDPD_MED_POLICY \
163 STRUCT_LLDPD_MED_LOC \
164 STRUCT_LLDPD_MED_LOC \
165 STRUCT_LLDPD_MED_LOC \
167 u_int16_t p_med_cap_enabled
;
168 struct lldpd_med_policy p_med_policy
[LLDPMED_APPTYPE_LAST
];
169 struct lldpd_med_loc p_med_location
[LLDPMED_LOCFORMAT_LAST
];
170 u_int8_t p_med_pow_devicetype
; /* PD or PSE */
171 u_int8_t p_med_pow_source
;
172 u_int8_t p_med_pow_priority
;
173 u_int16_t p_med_pow_val
;
175 #define STRUCT_LLDPD_PORT_MED ""
179 #define STRUCT_LLDPD_PORT_DOT1 "wPP"
181 TAILQ_HEAD(, lldpd_vlan
) p_vlans
;
183 #define STRUCT_LLDPD_PORT_DOT1 ""
187 #define STRUCT_LLDPD_PORT "(LPttPbbCsw" \
188 STRUCT_LLDPD_PORT_DOT3 \
189 STRUCT_LLDPD_PORT_MED \
190 STRUCT_LLDPD_PORT_DOT1 ")"
194 unsigned char frame
[];
197 struct lldpd_hardware
;
200 int(*send
)(struct lldpd
*,
201 struct lldpd_hardware
*,
202 char *, size_t); /* Function to send a frame */
203 int(*recv
)(struct lldpd
*,
204 struct lldpd_hardware
*,
205 int, char *, size_t); /* Function to receive a frame */
206 int(*cleanup
)(struct lldpd
*, struct lldpd_hardware
*); /* Cleanup function. */
209 struct lldpd_hardware
{
210 TAILQ_ENTRY(lldpd_hardware
) h_entries
;
212 fd_set h_recvfds
; /* FD for reception */
213 int h_sendfd
; /* FD for sending, only used by h_ops */
214 struct lldpd_ops
*h_ops
; /* Hardware-dependent functions */
215 void *h_data
; /* Hardware-dependent data */
218 int h_flags
; /* Packets will be sent only
219 if IFF_RUNNING. Will be
220 removed if this is left
222 int h_ifindex
; /* Interface index, used by SNMP */
223 char h_ifname
[IFNAMSIZ
]; /* Should be unique */
224 u_int8_t h_lladdr
[ETHER_ADDR_LEN
];
228 u_int64_t h_rx_discarded_cnt
;
229 u_int64_t h_rx_ageout_cnt
;
230 u_int64_t h_rx_unrecognized_cnt
;
232 struct lldpd_port h_lport
; /* Port attached to this hardware port */
233 TAILQ_HEAD(, lldpd_port
) h_rports
; /* Remote ports */
236 struct lldpd_interface
{
237 TAILQ_ENTRY(lldpd_interface
) next
;
240 #define STRUCT_LLDPD_INTERFACE "(Ls)"
242 struct lldpd_client
{
243 TAILQ_ENTRY(lldpd_client
) next
;
247 #define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
248 #define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
249 #define PROTO_GUESS_SIG char *, int
252 #define LLDPD_MODE_LLDP 1
253 #define LLDPD_MODE_CDPV1 2
254 #define LLDPD_MODE_CDPV2 3
255 #define LLDPD_MODE_SONMP 4
256 #define LLDPD_MODE_EDP 5
257 #define LLDPD_MODE_FDP 6
258 int mode
; /* > 0 mode identifier (unique per protocol) */
259 int enabled
; /* Is this protocol enabled? */
260 char *name
; /* Name of protocol */
261 char arg
; /* Argument to enable this protocol */
262 int(*send
)(PROTO_SEND_SIG
); /* How to send a frame */
263 int(*decode
)(PROTO_DECODE_SIG
); /* How to decode a frame */
264 int(*guess
)(PROTO_GUESS_SIG
); /* Can be NULL, use MAC address in this case */
265 u_int8_t mac
[ETH_ALEN
]; /* Destination MAC address used by this protocol */
266 struct sock_filter
*filter
; /* BPF filter */
267 size_t filterlen
; /* Size of BPF filter */
274 struct protocol
*g_protocols
;
275 #ifdef ENABLE_LLDPMED
283 #endif /* USE_SNMP */
285 /* Unix socket handling */
287 TAILQ_HEAD(, lldpd_client
) g_clients
;
289 char *g_mgmt_pattern
;
291 #define LOCAL_CHASSIS(cfg) ((struct lldpd_chassis *)(TAILQ_FIRST(&cfg->g_chassis)))
292 TAILQ_HEAD(, lldpd_chassis
) g_chassis
;
293 TAILQ_HEAD(, lldpd_hardware
) g_hardware
;
296 typedef void(*lldpd_ifhandlers
)(struct lldpd
*, struct ifaddrs
*);
313 } __attribute__ ((__packed__
));
318 } __attribute__ ((__packed__
));
320 #define HMSG_HEADER_SIZE sizeof(struct hmsg_hdr)
321 #define MAX_HMSGSIZE 8192
324 struct lldpd_hardware
*lldpd_get_hardware(struct lldpd
*, char *);
325 struct lldpd_hardware
*lldpd_alloc_hardware(struct lldpd
*, char *);
326 void lldpd_hardware_cleanup(struct lldpd
*, struct lldpd_hardware
*);
328 void lldpd_vlan_cleanup(struct lldpd_port
*);
330 void lldpd_remote_cleanup(struct lldpd
*, struct lldpd_hardware
*, int);
331 void lldpd_port_cleanup(struct lldpd_port
*, int);
332 void lldpd_chassis_cleanup(struct lldpd_chassis
*, int);
335 int lldp_send(PROTO_SEND_SIG
);
336 int lldp_decode(PROTO_DECODE_SIG
);
340 int cdpv1_send(PROTO_SEND_SIG
);
341 int cdpv2_send(PROTO_SEND_SIG
);
342 int cdpv1_guess(PROTO_GUESS_SIG
);
343 int cdpv2_guess(PROTO_GUESS_SIG
);
345 #if defined (ENABLE_CDP) || defined (ENABLE_FDP)
346 int cdp_decode(PROTO_DECODE_SIG
);
349 int fdp_send(PROTO_SEND_SIG
);
354 int sonmp_send(PROTO_SEND_SIG
);
355 int sonmp_decode(PROTO_DECODE_SIG
);
360 int edp_send(PROTO_SEND_SIG
);
361 int edp_decode(PROTO_DECODE_SIG
);
365 int ctl_create(char *);
366 int ctl_connect(char *);
367 void ctl_cleanup(char *);
368 int ctl_accept(struct lldpd
*, int);
369 int ctl_close(struct lldpd
*, int);
370 void ctl_msg_init(struct hmsg
*, enum hmsg_type
);
371 int ctl_msg_send(int, struct hmsg
*);
372 int ctl_msg_recv(int, struct hmsg
*);
373 int ctl_msg_pack_list(char *, void *, unsigned int, struct hmsg
*, void **);
374 int ctl_msg_unpack_list(char *, void *, unsigned int, struct hmsg
*, void **);
375 int ctl_msg_pack_structure(char *, void *, unsigned int, struct hmsg
*, void **);
376 int ctl_msg_unpack_structure(char *, void *, unsigned int, struct hmsg
*, void **);
379 void lldpd_ifh_eth(struct lldpd
*, struct ifaddrs
*);
380 void lldpd_ifh_vlan(struct lldpd
*, struct ifaddrs
*);
381 void lldpd_ifh_mgmt(struct lldpd
*, struct ifaddrs
*);
384 #ifdef ENABLE_LLDPMED
395 void log_warn(const char *, ...);
396 #define LLOG_WARN(x,...) log_warn("%s: " x, __FUNCTION__, ##__VA_ARGS__)
397 void log_warnx(const char *, ...);
398 #define LLOG_WARNX(x,...) log_warnx("%s: " x, __FUNCTION__, ##__VA_ARGS__)
399 void log_info(const char *, ...);
400 #define LLOG_INFO(x,...) log_info("%s: " x, __FUNCTION__, ##__VA_ARGS__)
401 void log_debug(const char *, ...);
402 #define LLOG_DEBUG(x,...) log_debug("%s: " x, __FUNCTION__, ##__VA_ARGS__)
403 void fatal(const char *);
404 void fatalx(const char *);
407 void agent_shutdown();
408 void agent_init(struct lldpd
*, int);
411 void agent_priv_register_domain();
414 size_t strlcpy(char *, const char *, size_t);
417 struct client_handle
{
419 void (*handle
)(struct lldpd
*, struct hmsg
*, struct hmsg
*);
422 void client_handle_client(struct lldpd
*, struct lldpd_client
*,
424 void client_handle_none(struct lldpd
*, struct hmsg
*,
426 void client_handle_get_interfaces(struct lldpd
*, struct hmsg
*,
428 void client_handle_port_related(struct lldpd
*, struct hmsg
*,
430 void client_handle_shutdown(struct lldpd
*, struct hmsg
*,
434 void priv_init(char*);
435 int priv_ctl_create();
436 void priv_ctl_cleanup();
437 char *priv_gethostbyname();
438 int priv_open(char*);
439 int priv_ethtool(char*, struct ethtool_cmd
*);
440 int priv_iface_eth_init(struct lldpd_hardware
*);
441 int priv_iface_multicast(const char *, u_int8_t
*, int);
442 int priv_snmp_socket(struct sockaddr_un
*);
444 /* privsep_fdpass.c */
446 void send_fd(int, int);
448 #endif /* _LLDPD_H */