summaryrefslogtreecommitdiff
path: root/src/systemd/sd-lldp.h
blob: 64047ee81716ce1cb96a90e2967b96fa6bf462d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef foosdlldphfoo
#define foosdlldphfoo

/***
  systemd is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 2.1 of the License, or
  (at your option) any later version.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

#include <errno.h>
#include <inttypes.h>
#include <net/ethernet.h>
#include <sys/types.h>

#include "sd-event.h"

#include "_sd-common.h"

_SD_BEGIN_DECLARATIONS;

/* IEEE 802.1AB-2009 Clause 8: TLV Types */
enum {
        SD_LLDP_TYPE_END                 = 0,
        SD_LLDP_TYPE_CHASSIS_ID          = 1,
        SD_LLDP_TYPE_PORT_ID             = 2,
        SD_LLDP_TYPE_TTL                 = 3,
        SD_LLDP_TYPE_PORT_DESCRIPTION    = 4,
        SD_LLDP_TYPE_SYSTEM_NAME         = 5,
        SD_LLDP_TYPE_SYSTEM_DESCRIPTION  = 6,
        SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
        SD_LLDP_TYPE_MGMT_ADDRESS        = 8,
        SD_LLDP_TYPE_PRIVATE             = 127,
};

/* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */
enum {
        SD_LLDP_CHASSIS_SUBTYPE_RESERVED            = 0,
        SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT   = 1,
        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS     = 2,
        SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT      = 3,
        SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS         = 4,
        SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS     = 5,
        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME      = 6,
        SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED    = 7,
};

/* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */
enum {
        SD_LLDP_PORT_SUBTYPE_RESERVED         = 0,
        SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS  = 1,
        SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT   = 2,
        SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS      = 3,
        SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS  = 4,
        SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME   = 5,
        SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
};

/* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */
enum {
        SD_LLDP_SYSTEM_CAPABILITIES_OTHER    = 1 << 0,
        SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
        SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE   = 1 << 2,
        SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP  = 1 << 3,
        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER   = 1 << 4,
        SD_LLDP_SYSTEM_CAPABILITIES_PHONE    = 1 << 5,
        SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS   = 1 << 6,
        SD_LLDP_SYSTEM_CAPABILITIES_STATION  = 1 << 7,
        SD_LLDP_SYSTEM_CAPABILITIES_CVLAN    = 1 << 8,
        SD_LLDP_SYSTEM_CAPABILITIES_SVLAN    = 1 << 9,
        SD_LLDP_SYSTEM_CAPABILITIES_TPMR     = 1 << 10,
};

#define SD_LLDP_SYSTEM_CAPABILITIES_ALL UINT16_MAX

#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS                         \
        ((uint16_t)                                                     \
         (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER|                         \
          SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|                           \
          SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP|                          \
          SD_LLDP_SYSTEM_CAPABILITIES_ROUTER|                           \
          SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS|                           \
          SD_LLDP_SYSTEM_CAPABILITIES_CVLAN|                            \
          SD_LLDP_SYSTEM_CAPABILITIES_SVLAN|                            \
          SD_LLDP_SYSTEM_CAPABILITIES_TPMR))

#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }

#define SD_LLDP_OUI_MUD   (uint8_t[]) { 0x00, 0x00, 0x5E }
#define SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION  0x01

/* IEEE 802.1AB-2009 Annex E */
enum {
        SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID          = 1,
        SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
        SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME             = 3,
        SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY     = 4,
        SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST      = 5,
        SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID        = 6,
        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7,
};

/* IEEE 802.1AB-2009 Annex F */
enum {
        SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1,
        SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI         = 2,
        SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION      = 3,
        SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE    = 4,
};

typedef struct sd_lldp sd_lldp;
typedef struct sd_lldp_neighbor sd_lldp_neighbor;

typedef enum sd_lldp_event_t {
        SD_LLDP_EVENT_ADDED,
        SD_LLDP_EVENT_REMOVED,
        SD_LLDP_EVENT_UPDATED,
        SD_LLDP_EVENT_REFRESHED,
        _SD_LLDP_EVENT_MAX,
        _SD_LLDP_EVENT_INVALID = -EINVAL,
        _SD_ENUM_FORCE_S64(LLDP_EVENT),
} sd_lldp_event_t;

typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n, void *userdata);

int sd_lldp_new(sd_lldp **ret);
sd_lldp* sd_lldp_ref(sd_lldp *lldp);
sd_lldp* sd_lldp_unref(sd_lldp *lldp);

int sd_lldp_start(sd_lldp *lldp);
int sd_lldp_stop(sd_lldp *lldp);

int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
int sd_lldp_detach_event(sd_lldp *lldp);
sd_event *sd_lldp_get_event(sd_lldp *lldp);

int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname);
const char *sd_lldp_get_ifname(sd_lldp *lldp);

/* Controls how much and what to store in the neighbors database */
int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);
int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask);
int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *address);

int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***neighbors);

int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size);
sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n);
sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n);

/* Access to LLDP frame metadata */
int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address);
int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address);
int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret);
int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);

/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */
int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret);
int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret);
int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec);
int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret);
int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);

/* Low-level, iterative TLV access. This is for everything else, it iteratively goes through all available TLVs
 * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type);
int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type);
int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype);
int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype);
int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);

_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref);

_SD_END_DECLARATIONS;

#endif