1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
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.
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.
18 #ifndef _LLDPD_STRUCTS_H
19 #define _LLDPD_STRUCTS_H
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 /* This is not very convenient, but we need net/if.h for IFNAMSIZ and others but
29 * we may also need linux/if.h in some modules. And they conflict each others.
32 # include <linux/if.h>
37 #include <netinet/in.h>
38 #include <netinet/if_ether.h>
39 #include <sys/queue.h>
41 #include "compat/compat.h"
43 #include "lldp-const.h"
47 TAILQ_ENTRY(lldpd_ppvid
) p_entries
;
48 u_int8_t p_cap_status
;
51 MARSHAL_BEGIN(lldpd_ppvid
)
52 MARSHAL_TQE(lldpd_ppvid
, p_entries
)
53 MARSHAL_END(lldpd_ppvid
);
56 TAILQ_ENTRY(lldpd_vlan
) v_entries
;
60 MARSHAL_BEGIN(lldpd_vlan
)
61 MARSHAL_TQE(lldpd_vlan
, v_entries
)
62 MARSHAL_STR(lldpd_vlan
, v_name
)
63 MARSHAL_END(lldpd_vlan
);
66 TAILQ_ENTRY(lldpd_pi
) p_entries
;
70 MARSHAL_BEGIN(lldpd_pi
)
71 MARSHAL_TQE(lldpd_pi
, p_entries
)
72 MARSHAL_FSTR(lldpd_pi
, p_pi
, p_pi_len
)
73 MARSHAL_END(lldpd_pi
);
77 struct lldpd_med_policy
{
78 u_int8_t index
; /* Not used. */
86 MARSHAL(lldpd_med_policy
);
88 struct lldpd_med_loc
{
89 u_int8_t index
; /* Not used. */
94 MARSHAL_BEGIN(lldpd_med_loc
)
95 MARSHAL_FSTR(lldpd_med_loc
, data
, data_len
)
96 MARSHAL_END(lldpd_med_loc
);
98 struct lldpd_med_power
{
99 u_int8_t devicetype
; /* PD or PSE */
104 MARSHAL(lldpd_med_power
);
108 struct lldpd_dot3_macphy
{
109 u_int8_t autoneg_support
;
110 u_int8_t autoneg_enabled
;
111 u_int16_t autoneg_advertised
;
115 struct lldpd_dot3_power
{
119 u_int8_t paircontrol
;
122 u_int8_t powertype
; /* If set to LLDP_DOT3_POWER_8023AT_OFF,
123 following fields have no meaning */
129 MARSHAL(lldpd_dot3_power
);
134 u_int16_t request_id
;
135 u_int16_t management_id
;
150 case LLDPD_AF_IPV4
: return AF_INET
;
151 case LLDPD_AF_IPV6
: return AF_INET6
;
152 case LLDPD_AF_LAST
: return AF_MAX
;
153 default: return AF_UNSPEC
;
157 #define LLDPD_MGMT_MAXADDRSIZE 16 /* sizeof(struct in6_addr) */
158 union lldpd_address
{
160 struct in6_addr inet6
;
161 u_int8_t octets
[LLDPD_MGMT_MAXADDRSIZE
]; /* network byte order! */
164 TAILQ_ENTRY(lldpd_mgmt
) m_entries
;
166 union lldpd_address m_addr
;
170 MARSHAL_BEGIN(lldpd_mgmt
)
171 MARSHAL_TQE(lldpd_mgmt
, m_entries
)
172 MARSHAL_END(lldpd_mgmt
);
174 struct lldpd_chassis
{
175 TAILQ_ENTRY(lldpd_chassis
) c_entries
;
176 u_int16_t c_refcount
; /* Reference count by ports */
177 u_int16_t c_index
; /* Monotonic index */
178 u_int8_t c_protocol
; /* Protocol used to get this chassis */
179 u_int8_t c_id_subtype
;
185 u_int16_t c_cap_available
;
186 u_int16_t c_cap_enabled
;
188 TAILQ_HEAD(, lldpd_mgmt
) c_mgmt
;
190 #ifdef ENABLE_LLDPMED
191 u_int16_t c_med_cap_available
;
203 /* WARNING: any change to this structure should also be reflected into
204 `lldpd_copy_chassis()` which is not using marshaling. */
205 MARSHAL_BEGIN(lldpd_chassis
)
206 MARSHAL_IGNORE(lldpd_chassis
, c_entries
.tqe_next
)
207 MARSHAL_IGNORE(lldpd_chassis
, c_entries
.tqe_prev
)
208 MARSHAL_FSTR(lldpd_chassis
, c_id
, c_id_len
)
209 MARSHAL_STR(lldpd_chassis
, c_name
)
210 MARSHAL_STR(lldpd_chassis
, c_descr
)
211 MARSHAL_SUBTQ(lldpd_chassis
, lldpd_mgmt
, c_mgmt
)
212 #ifdef ENABLE_LLDPMED
213 MARSHAL_STR(lldpd_chassis
, c_med_hw
)
214 MARSHAL_STR(lldpd_chassis
, c_med_fw
)
215 MARSHAL_STR(lldpd_chassis
, c_med_sw
)
216 MARSHAL_STR(lldpd_chassis
, c_med_sn
)
217 MARSHAL_STR(lldpd_chassis
, c_med_manuf
)
218 MARSHAL_STR(lldpd_chassis
, c_med_model
)
219 MARSHAL_STR(lldpd_chassis
, c_med_asset
)
221 MARSHAL_END(lldpd_chassis
);
225 #define CUSTOM_TLV_ADD 1
226 #define CUSTOM_TLV_REPLACE 2
227 #define CUSTOM_TLV_REMOVE 3
229 /* Custom TLV struct as defined on page 35 of IEEE 802.1AB-2005 */
230 struct lldpd_custom
{
231 TAILQ_ENTRY(lldpd_custom
) next
; /* Pointer to next custom TLV */
233 /* Organizationally Unique Identifier */
234 u_int8_t oui
[LLDP_TLV_ORG_OUI_LEN
];
235 /* Organizationally Defined Subtype */
237 /* Organizationally Defined Information String */
239 /* Organizationally Defined Information String length */
242 MARSHAL_BEGIN(lldpd_custom
)
243 MARSHAL_TQE(lldpd_custom
, next
)
244 MARSHAL_FSTR(lldpd_custom
, oui_info
, oui_info_len
)
245 MARSHAL_END(lldpd_custom
);
249 TAILQ_ENTRY(lldpd_port
) p_entries
;
250 struct lldpd_chassis
*p_chassis
; /* Attached chassis */
251 time_t p_lastchange
; /* Time of last change of values */
252 time_t p_lastupdate
; /* Time of last update received */
253 time_t p_lastremove
; /* Time of last removal of a remote port. Used for local ports only
254 * Used for deciding lldpStatsRemTablesLastChangeTime */
255 struct lldpd_frame
*p_lastframe
; /* Frame received during last update */
256 u_int8_t p_protocol
; /* Protocol used to get this port */
257 u_int8_t p_hidden_in
:1; /* Considered as hidden for reception */
258 u_int8_t p_hidden_out
:2; /* Considered as hidden for emission */
259 u_int8_t p_disable_rx
:3; /* Should RX be disabled for this port? */
260 u_int8_t p_disable_tx
:4; /* Should TX be disabled for this port? */
261 /* Important: all fields that should be ignored to check if a port has
262 * been changed should be before this mark. */
263 #define LLDPD_PORT_START_MARKER (offsetof(struct lldpd_port, _p_hardware_flags))
264 int _p_hardware_flags
; /* This is a copy of hardware flags. Do not use it! */
265 u_int8_t p_id_subtype
;
269 int p_descr_force
; /* Description has been forced by user */
271 u_int16_t p_ttl
; /* TTL for remote port */
275 u_int32_t p_aggregid
;
276 struct lldpd_dot3_macphy p_macphy
;
277 struct lldpd_dot3_power p_power
;
280 #ifdef ENABLE_LLDPMED
281 u_int16_t p_med_cap_enabled
;
282 struct lldpd_med_policy p_med_policy
[LLDP_MED_APPTYPE_LAST
];
283 struct lldpd_med_loc p_med_location
[LLDP_MED_LOCFORMAT_LAST
];
284 struct lldpd_med_power p_med_power
;
288 struct cdpv2_power p_cdp_power
;
293 TAILQ_HEAD(, lldpd_vlan
) p_vlans
;
294 TAILQ_HEAD(, lldpd_ppvid
) p_ppvids
;
295 TAILQ_HEAD(, lldpd_pi
) p_pids
;
298 TAILQ_HEAD(, lldpd_custom
) p_custom_list
;
301 MARSHAL_BEGIN(lldpd_port
)
302 MARSHAL_TQE(lldpd_port
, p_entries
)
303 MARSHAL_POINTER(lldpd_port
, lldpd_chassis
, p_chassis
)
304 MARSHAL_IGNORE(lldpd_port
, p_lastframe
)
305 MARSHAL_FSTR(lldpd_port
, p_id
, p_id_len
)
306 MARSHAL_STR(lldpd_port
, p_descr
)
307 #ifdef ENABLE_LLDPMED
308 MARSHAL_SUBSTRUCT(lldpd_port
, lldpd_med_loc
, p_med_location
[0])
309 MARSHAL_SUBSTRUCT(lldpd_port
, lldpd_med_loc
, p_med_location
[1])
310 MARSHAL_SUBSTRUCT(lldpd_port
, lldpd_med_loc
, p_med_location
[2])
313 MARSHAL_SUBTQ(lldpd_port
, lldpd_vlan
, p_vlans
)
314 MARSHAL_SUBTQ(lldpd_port
, lldpd_ppvid
, p_ppvids
)
315 MARSHAL_SUBTQ(lldpd_port
, lldpd_pi
, p_pids
)
318 MARSHAL_SUBTQ(lldpd_port
, lldpd_custom
, p_custom_list
)
320 MARSHAL_END(lldpd_port
);
322 /* Used to modify some port related settings */
323 #define LLDPD_RXTX_UNCHANGED 0
324 #define LLDPD_RXTX_TXONLY 1
325 #define LLDPD_RXTX_RXONLY 2
326 #define LLDPD_RXTX_DISABLED 3
327 #define LLDPD_RXTX_BOTH 4
328 #define LLDPD_RXTX_FROM_PORT(p) (((p)->p_disable_rx && (p)->p_disable_tx)?LLDPD_RXTX_DISABLED: \
329 ((p)->p_disable_rx && !(p)->p_disable_tx)?LLDPD_RXTX_TXONLY: \
330 (!(p)->p_disable_rx && (p)->p_disable_tx)?LLDPD_RXTX_RXONLY: \
332 #define LLDPD_RXTX_RXENABLED(v) ((v) == LLDPD_RXTX_RXONLY || (v) == LLDPD_RXTX_BOTH)
333 #define LLDPD_RXTX_TXENABLED(v) ((v) == LLDPD_RXTX_TXONLY || (v) == LLDPD_RXTX_BOTH)
334 struct lldpd_port_set
{
339 #ifdef ENABLE_LLDPMED
340 struct lldpd_med_policy
*med_policy
;
341 struct lldpd_med_loc
*med_location
;
342 struct lldpd_med_power
*med_power
;
345 struct lldpd_dot3_power
*dot3_power
;
348 struct lldpd_custom
*custom
;
349 int custom_list_clear
;
353 MARSHAL_BEGIN(lldpd_port_set
)
354 MARSHAL_STR(lldpd_port_set
, ifname
)
355 MARSHAL_STR(lldpd_port_set
, local_id
)
356 MARSHAL_STR(lldpd_port_set
, local_descr
)
357 #ifdef ENABLE_LLDPMED
358 MARSHAL_POINTER(lldpd_port_set
, lldpd_med_policy
, med_policy
)
359 MARSHAL_POINTER(lldpd_port_set
, lldpd_med_loc
, med_location
)
360 MARSHAL_POINTER(lldpd_port_set
, lldpd_med_power
, med_power
)
363 MARSHAL_POINTER(lldpd_port_set
, lldpd_dot3_power
, dot3_power
)
366 MARSHAL_POINTER(lldpd_port_set
, lldpd_custom
, custom
)
368 MARSHAL_END(lldpd_port_set
);
370 /* Smart mode / Hide mode */
371 #define SMART_INCOMING_FILTER (1<<0) /* Incoming filtering enabled */
372 #define SMART_INCOMING_ONE_PROTO (1<<1) /* On reception, keep only one proto */
373 #define SMART_INCOMING_ONE_NEIGH (1<<2) /* On reception, keep only one neighbor */
374 #define SMART_OUTGOING_FILTER (1<<3) /* Outgoing filtering enabled */
375 #define SMART_OUTGOING_ONE_PROTO (1<<4) /* On emission, keep only one proto */
376 #define SMART_OUTGOING_ONE_NEIGH (1<<5) /* On emission, consider only one neighbor */
377 #define SMART_INCOMING (SMART_INCOMING_FILTER | \
378 SMART_INCOMING_ONE_PROTO | \
379 SMART_INCOMING_ONE_NEIGH)
380 #define SMART_OUTGOING (SMART_OUTGOING_FILTER | \
381 SMART_OUTGOING_ONE_PROTO | \
382 SMART_OUTGOING_ONE_NEIGH)
384 struct lldpd_config
{
385 int c_paused
; /* lldpd is paused */
386 int c_tx_interval
; /* Transmit interval */
388 int c_smart
; /* Bitmask for smart configuration (see SMART_*) */
389 int c_receiveonly
; /* Receive only mode */
390 int c_max_neighbors
; /* Maximum number of neighbors (per protocol) */
392 char *c_mgmt_pattern
; /* Pattern to match a management address */
393 char *c_cid_pattern
; /* Pattern to match interfaces to use for chassis ID */
394 char *c_cid_string
; /* User defined string for chassis ID */
395 char *c_iface_pattern
; /* Pattern to match interfaces to use */
396 char *c_perm_ifaces
; /* Pattern to match interfaces to keep */
398 char *c_platform
; /* Override platform description (for CDP) */
399 char *c_description
; /* Override chassis description */
400 char *c_hostname
; /* Override system name */
401 int c_advertise_version
; /* Should the precise version be advertised? */
402 int c_set_ifdescr
; /* Set interface description */
403 int c_promisc
; /* Interfaces should be in promiscuous mode */
404 int c_cap_advertise
; /* Chassis capabilities advertisement */
405 int c_mgmt_advertise
; /* Management addresses advertisement */
407 #ifdef ENABLE_LLDPMED
408 int c_noinventory
; /* Don't send inventory with LLDP-MED */
409 int c_enable_fast_start
; /* enable fast start */
410 int c_tx_fast_init
; /* Num of lldpd lldppdu's for fast start */
411 int c_tx_fast_interval
; /* Time intr between sends during fast start */
413 int c_tx_hold
; /* Transmit hold */
414 int c_bond_slave_src_mac_type
; /* Src mac type in lldp frames over bond
416 int c_lldp_portid_type
; /* The PortID type */
417 int c_lldp_agent_type
; /* The agent type */
419 MARSHAL_BEGIN(lldpd_config
)
420 MARSHAL_STR(lldpd_config
, c_mgmt_pattern
)
421 MARSHAL_STR(lldpd_config
, c_cid_pattern
)
422 MARSHAL_STR(lldpd_config
, c_cid_string
)
423 MARSHAL_STR(lldpd_config
, c_iface_pattern
)
424 MARSHAL_STR(lldpd_config
, c_perm_ifaces
)
425 MARSHAL_STR(lldpd_config
, c_hostname
)
426 MARSHAL_STR(lldpd_config
, c_platform
)
427 MARSHAL_STR(lldpd_config
, c_description
)
428 MARSHAL_END(lldpd_config
);
432 unsigned char frame
[1];
435 struct lldpd_hardware
;
438 int(*send
)(struct lldpd
*,
439 struct lldpd_hardware
*,
440 char *, size_t); /* Function to send a frame */
441 int(*recv
)(struct lldpd
*,
442 struct lldpd_hardware
*,
443 int, char *, size_t); /* Function to receive a frame */
444 int(*cleanup
)(struct lldpd
*, struct lldpd_hardware
*); /* Cleanup function. */
447 /* An interface is uniquely identified by h_ifindex, h_ifname and h_ops. This
448 * means if an interface becomes enslaved, it will be considered as a new
449 * interface. The same applies for renaming and we include the index in case of
450 * renaming to an existing interface. */
451 struct lldpd_hardware
{
452 TAILQ_ENTRY(lldpd_hardware
) h_entries
;
454 struct lldpd
*h_cfg
; /* Pointer to main configuration */
455 void *h_recv
; /* FD for reception */
456 int h_sendfd
; /* FD for sending, only used by h_ops */
457 int h_mangle
; /* 1 if we have to mangle the MAC address */
458 struct lldpd_ops
*h_ops
; /* Hardware-dependent functions */
459 void *h_data
; /* Hardware-dependent data */
460 void *h_timer
; /* Timer for this port */
463 int h_flags
; /* Packets will be sent only
464 if IFF_RUNNING. Will be
465 removed if this is left
467 int h_ifindex
; /* Interface index, used by SNMP */
468 char h_ifname
[IFNAMSIZ
]; /* Should be unique */
469 u_int8_t h_lladdr
[ETHER_ADDR_LEN
];
473 u_int64_t h_rx_discarded_cnt
;
474 u_int64_t h_rx_unrecognized_cnt
;
475 u_int64_t h_ageout_cnt
;
476 u_int64_t h_insert_cnt
;
477 u_int64_t h_delete_cnt
;
478 u_int64_t h_drop_cnt
;
480 /* Previous values of different stuff. */
481 /* Backup of the previous local port. Used to check if there was a
482 * change to send an immediate update. All those are not marshalled to
484 void *h_lport_previous
;
485 ssize_t h_lport_previous_len
;
486 /* Backup of the previous chassis ID. Used to check if there was a
487 * change and send an LLDP shutdown. */
488 u_int8_t h_lchassis_previous_id_subtype
;
489 char *h_lchassis_previous_id
;
490 int h_lchassis_previous_id_len
;
491 /* Backup of the previous port ID. Used to check if there was a change
492 * and send an LLDP shutdown. */
493 u_int8_t h_lport_previous_id_subtype
;
494 char *h_lport_previous_id
;
495 int h_lport_previous_id_len
;
497 struct lldpd_port h_lport
; /* Port attached to this hardware port */
498 TAILQ_HEAD(, lldpd_port
) h_rports
; /* Remote ports */
500 #ifdef ENABLE_LLDPMED
501 int h_tx_fast
; /* current tx fast start count */
504 MARSHAL_BEGIN(lldpd_hardware
)
505 MARSHAL_IGNORE(lldpd_hardware
, h_entries
.tqe_next
)
506 MARSHAL_IGNORE(lldpd_hardware
, h_entries
.tqe_prev
)
507 MARSHAL_IGNORE(lldpd_hardware
, h_ops
)
508 MARSHAL_IGNORE(lldpd_hardware
, h_data
)
509 MARSHAL_IGNORE(lldpd_hardware
, h_cfg
)
510 MARSHAL_IGNORE(lldpd_hardware
, h_lport_previous
)
511 MARSHAL_IGNORE(lldpd_hardware
, h_lport_previous_len
)
512 MARSHAL_IGNORE(lldpd_hardware
, h_lchassis_previous_id_subtype
)
513 MARSHAL_IGNORE(lldpd_hardware
, h_lchassis_previous_id
)
514 MARSHAL_IGNORE(lldpd_hardware
, h_lchassis_previous_id_len
)
515 MARSHAL_IGNORE(lldpd_hardware
, h_lport_previous_id_subtype
)
516 MARSHAL_IGNORE(lldpd_hardware
, h_lport_previous_id
)
517 MARSHAL_IGNORE(lldpd_hardware
, h_lport_previous_id_len
)
518 MARSHAL_SUBSTRUCT(lldpd_hardware
, lldpd_port
, h_lport
)
519 MARSHAL_SUBTQ(lldpd_hardware
, lldpd_port
, h_rports
)
520 MARSHAL_END(lldpd_hardware
);
522 struct lldpd_interface
{
523 TAILQ_ENTRY(lldpd_interface
) next
;
526 MARSHAL_BEGIN(lldpd_interface
)
527 MARSHAL_TQE(lldpd_interface
, next
)
528 MARSHAL_STR(lldpd_interface
, name
)
529 MARSHAL_END(lldpd_interface
);
530 TAILQ_HEAD(lldpd_interface_list
, lldpd_interface
);
531 MARSHAL_TQ(lldpd_interface_list
, lldpd_interface
);
533 struct lldpd_neighbor_change
{
535 #define NEIGHBOR_CHANGE_DELETED -1
536 #define NEIGHBOR_CHANGE_ADDED 1
537 #define NEIGHBOR_CHANGE_UPDATED 0
539 struct lldpd_port
*neighbor
;
541 MARSHAL_BEGIN(lldpd_neighbor_change
)
542 MARSHAL_STR(lldpd_neighbor_change
, ifname
)
543 MARSHAL_POINTER(lldpd_neighbor_change
, lldpd_port
, neighbor
)
544 MARSHAL_END(lldpd_neighbor_change
);
546 /* Cleanup functions */
547 void lldpd_chassis_mgmt_cleanup(struct lldpd_chassis
*);
548 void lldpd_chassis_cleanup(struct lldpd_chassis
*, int);
549 void lldpd_remote_cleanup(struct lldpd_hardware
*,
550 void(*expire
)(struct lldpd_hardware
*, struct lldpd_port
*),
552 void lldpd_port_cleanup(struct lldpd_port
*, int);
553 void lldpd_config_cleanup(struct lldpd_config
*);
555 void lldpd_ppvid_cleanup(struct lldpd_port
*);
556 void lldpd_vlan_cleanup(struct lldpd_port
*);
557 void lldpd_pi_cleanup(struct lldpd_port
*);
560 void lldpd_custom_tlv_cleanup(struct lldpd_port
*, struct lldpd_custom
*);
561 void lldpd_custom_tlv_add(struct lldpd_port
*, struct lldpd_custom
*);
562 void lldpd_custom_list_cleanup(struct lldpd_port
*);