1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2015 Vincent Bernat <vincent@bernat.im>
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.
21 #include <arpa/inet.h>
28 static struct atom_map lldpd_protocol_map
= {
29 .key
= lldpctl_k_port_protocol
,
31 { LLDPD_MODE_LLDP
, "LLDP" },
32 { LLDPD_MODE_CDPV1
, "CDPv1"},
33 { LLDPD_MODE_CDPV2
, "CDPv2"},
34 { LLDPD_MODE_EDP
, "EDP" },
35 { LLDPD_MODE_FDP
, "FDP"},
36 { LLDPD_MODE_SONMP
, "SONMP"},
41 ATOM_MAP_REGISTER(lldpd_protocol_map
, 3);
43 static lldpctl_map_t port_id_subtype_map
[] = {
44 { LLDP_PORTID_SUBTYPE_IFNAME
, "ifname"},
45 { LLDP_PORTID_SUBTYPE_IFALIAS
, "ifalias" },
46 { LLDP_PORTID_SUBTYPE_LOCAL
, "local" },
47 { LLDP_PORTID_SUBTYPE_LLADDR
, "mac" },
48 { LLDP_PORTID_SUBTYPE_ADDR
, "ip" },
49 { LLDP_PORTID_SUBTYPE_PORT
, "unhandled" },
50 { LLDP_PORTID_SUBTYPE_AGENTCID
, "unhandled" },
54 static struct atom_map port_status_map
= {
55 .key
= lldpctl_k_port_status
,
57 { LLDPD_RXTX_TXONLY
, "TX only" },
58 { LLDPD_RXTX_RXONLY
, "RX only" },
59 { LLDPD_RXTX_DISABLED
, "disabled" },
60 { LLDPD_RXTX_BOTH
, "RX and TX" },
65 ATOM_MAP_REGISTER(port_status_map
, 3);
68 static lldpctl_map_t operational_mau_type_values
[] = {
69 { LLDP_DOT3_MAU_AUI
, "AUI - No internal MAU, view from AUI" },
70 { LLDP_DOT3_MAU_10BASE5
, "10Base5 - Thick coax MAU" },
71 { LLDP_DOT3_MAU_FOIRL
, "Foirl - FOIRL MAU" },
72 { LLDP_DOT3_MAU_10BASE2
, "10Base2 - Thin coax MAU" },
73 { LLDP_DOT3_MAU_10BASET
, "10BaseT - UTP MAU" },
74 { LLDP_DOT3_MAU_10BASEFP
, "10BaseFP - Passive fiber MAU" },
75 { LLDP_DOT3_MAU_10BASEFB
, "10BaseFB - Sync fiber MAU" },
76 { LLDP_DOT3_MAU_10BASEFL
, "10BaseFL - Async fiber MAU" },
77 { LLDP_DOT3_MAU_10BROAD36
, "10Broad36 - Broadband DTE MAU" },
78 { LLDP_DOT3_MAU_10BASETHD
, "10BaseTHD - UTP MAU, half duplex mode" },
79 { LLDP_DOT3_MAU_10BASETFD
, "10BaseTFD - UTP MAU, full duplex mode" },
80 { LLDP_DOT3_MAU_10BASEFLHD
, "10BaseFLHD - Async fiber MAU, half duplex mode" },
81 { LLDP_DOT3_MAU_10BASEFLFD
, "10BaseFLDF - Async fiber MAU, full duplex mode" },
82 { LLDP_DOT3_MAU_100BASET4
, "100BaseT4 - 4 pair category 3 UTP" },
83 { LLDP_DOT3_MAU_100BASETXHD
, "100BaseTXHD - 2 pair category 5 UTP, half duplex mode" },
84 { LLDP_DOT3_MAU_100BASETXFD
, "100BaseTXFD - 2 pair category 5 UTP, full duplex mode" },
85 { LLDP_DOT3_MAU_100BASEFXHD
, "100BaseFXHD - X fiber over PMT, half duplex mode" },
86 { LLDP_DOT3_MAU_100BASEFXFD
, "100BaseFXFD - X fiber over PMT, full duplex mode" },
87 { LLDP_DOT3_MAU_100BASET2HD
, "100BaseT2HD - 2 pair category 3 UTP, half duplex mode" },
88 { LLDP_DOT3_MAU_100BASET2FD
, "100BaseT2FD - 2 pair category 3 UTP, full duplex mode" },
89 { LLDP_DOT3_MAU_1000BASEXHD
, "1000BaseXHD - PCS/PMA, unknown PMD, half duplex mode" },
90 { LLDP_DOT3_MAU_1000BASEXFD
, "1000BaseXFD - PCS/PMA, unknown PMD, full duplex mode" },
91 { LLDP_DOT3_MAU_1000BASELXHD
, "1000BaseLXHD - Fiber over long-wavelength laser, half duplex mode" },
92 { LLDP_DOT3_MAU_1000BASELXFD
, "1000BaseLXFD - Fiber over long-wavelength laser, full duplex mode" },
93 { LLDP_DOT3_MAU_1000BASESXHD
, "1000BaseSXHD - Fiber over short-wavelength laser, half duplex mode" },
94 { LLDP_DOT3_MAU_1000BASESXFD
, "1000BaseSXFD - Fiber over short-wavelength laser, full duplex mode" },
95 { LLDP_DOT3_MAU_1000BASECXHD
, "1000BaseCXHD - Copper over 150-Ohm balanced cable, half duplex mode" },
96 { LLDP_DOT3_MAU_1000BASECXFD
, "1000BaseCXFD - Copper over 150-Ohm balanced cable, full duplex mode" },
97 { LLDP_DOT3_MAU_1000BASETHD
, "1000BaseTHD - Four-pair Category 5 UTP, half duplex mode" },
98 { LLDP_DOT3_MAU_1000BASETFD
, "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode" },
99 { LLDP_DOT3_MAU_10GIGBASEX
, "10GigBaseX - X PCS/PMA, unknown PMD." },
100 { LLDP_DOT3_MAU_10GIGBASELX4
, "10GigBaseLX4 - X fiber over WWDM optics" },
101 { LLDP_DOT3_MAU_10GIGBASER
, "10GigBaseR - R PCS/PMA, unknown PMD." },
102 { LLDP_DOT3_MAU_10GIGBASEER
, "10GigBaseER - R fiber over 1550 nm optics" },
103 { LLDP_DOT3_MAU_10GIGBASELR
, "10GigBaseLR - R fiber over 1310 nm optics" },
104 { LLDP_DOT3_MAU_10GIGBASESR
, "10GigBaseSR - R fiber over 850 nm optics" },
105 { LLDP_DOT3_MAU_10GIGBASEW
, "10GigBaseW - W PCS/PMA, unknown PMD." },
106 { LLDP_DOT3_MAU_10GIGBASEEW
, "10GigBaseEW - W fiber over 1550 nm optics" },
107 { LLDP_DOT3_MAU_10GIGBASELW
, "10GigBaseLW - W fiber over 1310 nm optics" },
108 { LLDP_DOT3_MAU_10GIGBASESW
, "10GigBaseSW - W fiber over 850 nm optics" },
109 { LLDP_DOT3_MAU_10GIGBASECX4
, "10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable" },
110 { LLDP_DOT3_MAU_2BASETL
, "2BaseTL - Voice grade UTP copper, up to 2700m, optional PAF" },
111 { LLDP_DOT3_MAU_10PASSTS
, "10PassTS - Voice grade UTP copper, up to 750m, optional PAF" },
112 { LLDP_DOT3_MAU_100BASEBX10D
, "100BaseBX10D - One single-mode fiber OLT, long wavelength, 10km" },
113 { LLDP_DOT3_MAU_100BASEBX10U
, "100BaseBX10U - One single-mode fiber ONU, long wavelength, 10km" },
114 { LLDP_DOT3_MAU_100BASELX10
, "100BaseLX10 - Two single-mode fibers, long wavelength, 10km" },
115 { LLDP_DOT3_MAU_1000BASEBX10D
, "1000BaseBX10D - One single-mode fiber OLT, long wavelength, 10km" },
116 { LLDP_DOT3_MAU_1000BASEBX10U
, "1000BaseBX10U - One single-mode fiber ONU, long wavelength, 10km" },
117 { LLDP_DOT3_MAU_1000BASELX10
, "1000BaseLX10 - Two sigle-mode fiber, long wavelength, 10km" },
118 { LLDP_DOT3_MAU_1000BASEPX10D
, "1000BasePX10D - One single-mode fiber EPON OLT, 10km" },
119 { LLDP_DOT3_MAU_1000BASEPX10U
, "1000BasePX10U - One single-mode fiber EPON ONU, 10km" },
120 { LLDP_DOT3_MAU_1000BASEPX20D
, "1000BasePX20D - One single-mode fiber EPON OLT, 20km" },
121 { LLDP_DOT3_MAU_1000BASEPX20U
, "1000BasePX20U - One single-mode fiber EPON ONU, 20km" },
122 { LLDP_DOT3_MAU_10GBASET
, "10GbaseT - Four-pair Category 6A or better, full duplex mode only" },
123 { LLDP_DOT3_MAU_10GBASELRM
, "10GbaseLRM - R multimode fiber over 1310 nm optics" },
124 { LLDP_DOT3_MAU_1000BASEKX
, "1000baseKX - X backplane, full duplex mode only" },
125 { LLDP_DOT3_MAU_10GBASEKX4
, "10GbaseKX4 - 4 lane X backplane, full duplex mode only" },
126 { LLDP_DOT3_MAU_10GBASEKR
, "10GbaseKR - R backplane, full duplex mode only" },
127 { LLDP_DOT3_MAU_10G1GBASEPRXD1
, "10G1GbasePRXD1 - One single-mode fiber asymmetric-rate EPON OLT, low power budget (PRX10)" },
128 { LLDP_DOT3_MAU_10G1GBASEPRXD2
, "10G1GbasePRXD2 - One single-mode fiber asymmetric-rate EPON OLT, medium power budget (PRX20)" },
129 { LLDP_DOT3_MAU_10G1GBASEPRXD3
, "10G1GbasePRXD3 - One single-mode fiber asymmetric-rate EPON OLT, high power budget (PRX30)" },
130 { LLDP_DOT3_MAU_10G1GBASEPRXU1
, "10G1GbasePRXU1 - One single-mode fiber asymmetric-rate EPON ONU, low power budget (PRX10)" },
131 { LLDP_DOT3_MAU_10G1GBASEPRXU2
, "10G1GbasePRXU2 - One single-mode fiber asymmetric-rate EPON ONU, medium power budget (PRX20)" },
132 { LLDP_DOT3_MAU_10G1GBASEPRXU3
, "10G1GbasePRXU3 - One single-mode fiber asymmetric-rate EPON ONU, high power budget (PRX30)" },
133 { LLDP_DOT3_MAU_10GBASEPRD1
, "10GbasePRD1 - One single-mode fiber symmetric-rate EPON OLT, low power budget (PR10)" },
134 { LLDP_DOT3_MAU_10GBASEPRD2
, "10GbasePRD2 - One single-mode fiber symmetric-rate EPON OLT, medium power budget (PR20)" },
135 { LLDP_DOT3_MAU_10GBASEPRD3
, "10GbasePRD3 - One single-mode fiber symmetric-rate EPON OLT, high power budget (PR30)" },
136 { LLDP_DOT3_MAU_10GBASEPRU1
, "10GbasePRU1 - One single-mode fiber symmetric-rate EPON ONU, low and medium power budget" },
137 { LLDP_DOT3_MAU_10GBASEPRU3
, "10GbasePRU3 - One single-mode fiber symmetric-rate EPON ONU, high power budget (PR30)" },
138 { LLDP_DOT3_MAU_40GBASEKR4
, "40GbaseKR4 - 40GBASE-R PCS/PMA over an electrical backplane" },
139 { LLDP_DOT3_MAU_40GBASECR4
, "40GbaseCR4 - 40GBASE-R PCS/PMA over 4 lane shielded copper balanced cable" },
140 { LLDP_DOT3_MAU_40GBASESR4
, "40GbaseSR4 - 40GBASE-R PCS/PMA over 4 lane multimode fiber" },
141 { LLDP_DOT3_MAU_40GBASEFR
, "40GbaseFR - 40GBASE-R PCS/PMA over single mode fiber" },
142 { LLDP_DOT3_MAU_40GBASELR4
, "40GbaseLR4 - 40GBASE-R PCS/PMA over 4 WDM lane single mode fiber" },
143 { LLDP_DOT3_MAU_100GBASECR10
, "100GbaseCR10 - 100GBASE-R PCS/PMA over 10 lane shielded copper balanced cable" },
144 { LLDP_DOT3_MAU_100GBASESR10
, "100GbaseSR10 - 100GBASE-R PCS/PMA over 10 lane multimode fiber" },
145 { LLDP_DOT3_MAU_100GBASELR4
, "100GbaseLR4 - 100GBASE-R PCS/PMA over 4 WDM lane single mode fiber, long reach" },
146 { LLDP_DOT3_MAU_100GBASEER4
, "100GbaseER4 - 100GBASE-R PCS/PMA over 4 WDM lane single mode fiber PMD, extended reach" },
151 static lldpctl_atom_iter_t
*
152 _lldpctl_atom_iter_ports_list(lldpctl_atom_t
*atom
)
154 struct _lldpctl_atom_any_list_t
*plist
=
155 (struct _lldpctl_atom_any_list_t
*)atom
;
156 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(&plist
->parent
->hardware
->h_rports
);
159 static lldpctl_atom_iter_t
*
160 _lldpctl_atom_next_ports_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
162 struct lldpd_port
*port
= (struct lldpd_port
*)iter
;
163 return (lldpctl_atom_iter_t
*)TAILQ_NEXT(port
, p_entries
);
166 static lldpctl_atom_t
*
167 _lldpctl_atom_value_ports_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
169 struct lldpd_port
*port
= (struct lldpd_port
*)iter
;
170 return _lldpctl_new_atom(atom
->conn
, atom_port
, 0, NULL
, port
,
171 ((struct _lldpctl_atom_any_list_t
*)atom
)->parent
);
175 _lldpctl_atom_new_port(lldpctl_atom_t
*atom
, va_list ap
)
177 struct _lldpctl_atom_port_t
*port
=
178 (struct _lldpctl_atom_port_t
*)atom
;
179 port
->local
= va_arg(ap
, int);
180 port
->hardware
= va_arg(ap
, struct lldpd_hardware
*);
181 port
->port
= va_arg(ap
, struct lldpd_port
*);
182 port
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
184 lldpctl_atom_inc_ref((lldpctl_atom_t
*)port
->parent
);
187 /* Internal atom. We are the parent, but our reference count is
188 * not incremented. */
189 port
->chassis
= _lldpctl_new_atom(atom
->conn
, atom_chassis
,
190 port
->port
->p_chassis
, port
, 1);
195 TAILQ_HEAD(chassis_list
, lldpd_chassis
);
198 add_chassis(struct chassis_list
*chassis_list
,
199 struct lldpd_chassis
*chassis
)
201 struct lldpd_chassis
*one_chassis
;
202 TAILQ_FOREACH(one_chassis
, chassis_list
, c_entries
) {
203 if (one_chassis
== chassis
) return;
205 TAILQ_INSERT_TAIL(chassis_list
,
210 _lldpctl_atom_free_port(lldpctl_atom_t
*atom
)
212 struct _lldpctl_atom_port_t
*port
=
213 (struct _lldpctl_atom_port_t
*)atom
;
214 struct lldpd_hardware
*hardware
= port
->hardware
;
215 struct lldpd_chassis
*one_chassis
, *one_chassis_next
;
216 struct lldpd_port
*one_port
;
218 /* Free internal chassis atom. Should be freed immediately since we
219 * should have the only reference. */
220 lldpctl_atom_dec_ref((lldpctl_atom_t
*)port
->chassis
);
222 /* We need to free the whole struct lldpd_hardware: local port, local
223 * chassis and remote ports... The same chassis may be present several
224 * times. We build a list of chassis (we don't use reference count). */
225 struct chassis_list chassis_list
;
226 TAILQ_INIT(&chassis_list
);
228 if (port
->parent
) lldpctl_atom_dec_ref((lldpctl_atom_t
*)port
->parent
);
229 else if (!hardware
&& port
->port
) {
230 /* No parent, no hardware, we assume a single neighbor: one
231 * port, one chassis. */
232 if (port
->port
->p_chassis
) {
233 lldpd_chassis_cleanup(port
->port
->p_chassis
, 1);
234 port
->port
->p_chassis
= NULL
;
236 lldpd_port_cleanup(port
->port
, 1);
239 if (!hardware
) return;
241 add_chassis(&chassis_list
, port
->port
->p_chassis
);
242 TAILQ_FOREACH(one_port
, &hardware
->h_rports
, p_entries
)
243 add_chassis(&chassis_list
, one_port
->p_chassis
);
245 /* Free hardware port */
246 lldpd_remote_cleanup(hardware
, NULL
, 1);
247 lldpd_port_cleanup(port
->port
, 1);
248 free(port
->hardware
);
250 /* Free list of chassis */
251 for (one_chassis
= TAILQ_FIRST(&chassis_list
);
253 one_chassis
= one_chassis_next
) {
254 one_chassis_next
= TAILQ_NEXT(one_chassis
, c_entries
);
255 lldpd_chassis_cleanup(one_chassis
, 1);
259 static lldpctl_atom_t
*
260 _lldpctl_atom_get_atom_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
262 struct _lldpctl_atom_port_t
*p
=
263 (struct _lldpctl_atom_port_t
*)atom
;
264 struct lldpd_port
*port
= p
->port
;
265 struct lldpd_hardware
*hardware
= p
->hardware
;
267 /* Local port only */
268 if (hardware
!= NULL
) {
270 case lldpctl_k_port_neighbors
:
271 return _lldpctl_new_atom(atom
->conn
, atom_ports_list
, p
);
276 /* Local and remote port */
278 case lldpctl_k_port_chassis
:
279 if (port
->p_chassis
) {
280 return _lldpctl_new_atom(atom
->conn
, atom_chassis
,
281 port
->p_chassis
, p
, 0);
283 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
286 case lldpctl_k_port_dot3_power
:
287 return _lldpctl_new_atom(atom
->conn
, atom_dot3_power
,
291 case lldpctl_k_port_vlans
:
292 return _lldpctl_new_atom(atom
->conn
, atom_vlans_list
,
294 case lldpctl_k_port_ppvids
:
295 return _lldpctl_new_atom(atom
->conn
, atom_ppvids_list
,
297 case lldpctl_k_port_pis
:
298 return _lldpctl_new_atom(atom
->conn
, atom_pis_list
,
301 #ifdef ENABLE_LLDPMED
302 case lldpctl_k_port_med_policies
:
303 return _lldpctl_new_atom(atom
->conn
, atom_med_policies_list
,
305 case lldpctl_k_port_med_locations
:
306 return _lldpctl_new_atom(atom
->conn
, atom_med_locations_list
,
308 case lldpctl_k_port_med_power
:
309 return _lldpctl_new_atom(atom
->conn
, atom_med_power
, p
);
312 case lldpctl_k_custom_tlvs
:
313 return _lldpctl_new_atom(atom
->conn
, atom_custom_list
, p
);
316 /* Compatibility: query the associated chassis too */
318 return lldpctl_atom_get(p
->chassis
, key
);
319 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
324 static lldpctl_atom_t
*
325 _lldpctl_atom_set_atom_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
, lldpctl_atom_t
*value
)
327 struct _lldpctl_atom_port_t
*p
=
328 (struct _lldpctl_atom_port_t
*)atom
;
329 struct lldpd_hardware
*hardware
= p
->hardware
;
330 struct lldpd_port_set set
= {};
335 struct _lldpctl_atom_dot3_power_t
*dpow
;
337 #ifdef ENABLE_LLDPMED
338 struct _lldpctl_atom_med_power_t
*mpow
;
339 struct _lldpctl_atom_med_policy_t
*mpol
;
340 struct _lldpctl_atom_med_location_t
*mloc
;
343 struct _lldpctl_atom_custom_t
*custom
;
346 /* Local and default port only */
348 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
353 case lldpctl_k_port_id
:
354 set
.local_id
= p
->port
->p_id
;
356 case lldpctl_k_port_descr
:
357 set
.local_descr
= p
->port
->p_descr
;
359 case lldpctl_k_port_status
:
360 set
.rxtx
= LLDPD_RXTX_FROM_PORT(p
->port
);
363 case lldpctl_k_port_dot3_power
:
364 if (value
->type
!= atom_dot3_power
) {
365 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
369 dpow
= (struct _lldpctl_atom_dot3_power_t
*)value
;
370 set
.dot3_power
= &dpow
->parent
->port
->p_power
;
373 #ifdef ENABLE_LLDPMED
374 case lldpctl_k_port_med_power
:
375 if (value
->type
!= atom_med_power
) {
376 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
380 mpow
= (struct _lldpctl_atom_med_power_t
*)value
;
381 set
.med_power
= &mpow
->parent
->port
->p_med_power
;
383 case lldpctl_k_port_med_policies
:
384 if (value
->type
!= atom_med_policy
) {
385 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
388 mpol
= (struct _lldpctl_atom_med_policy_t
*)value
;
389 set
.med_policy
= mpol
->policy
;
391 case lldpctl_k_port_med_locations
:
392 if (value
->type
!= atom_med_location
) {
393 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
396 mloc
= (struct _lldpctl_atom_med_location_t
*)value
;
397 set
.med_location
= mloc
->location
;
401 case lldpctl_k_custom_tlvs_clear
:
402 set
.custom_list_clear
= 1;
404 case lldpctl_k_custom_tlv
:
405 if (value
->type
!= atom_custom
) {
406 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
409 custom
= (struct _lldpctl_atom_custom_t
*)value
;
410 set
.custom
= custom
->tlv
;
411 set
.custom_tlv_op
= custom
->op
;
415 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
419 set
.ifname
= hardware
? hardware
->h_ifname
: "";
421 if (asprintf(&canary
, "%d%p%s", key
, value
, set
.ifname
) == -1) {
422 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
425 rc
= _lldpctl_do_something(atom
->conn
,
426 CONN_STATE_SET_PORT_SEND
, CONN_STATE_SET_PORT_RECV
,
428 SET_PORT
, &set
, &MARSHAL_INFO(lldpd_port_set
),
431 if (rc
== 0) return atom
;
436 _lldpctl_atom_get_str_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
438 struct _lldpctl_atom_port_t
*p
=
439 (struct _lldpctl_atom_port_t
*)atom
;
440 struct lldpd_port
*port
= p
->port
;
441 struct lldpd_hardware
*hardware
= p
->hardware
;
442 char *ipaddress
= NULL
; size_t len
;
444 /* Local port only */
446 case lldpctl_k_port_name
:
447 if (hardware
!= NULL
) return hardware
->h_ifname
;
449 case lldpctl_k_port_status
:
450 if (p
->local
) return map_lookup(port_status_map
.map
,
451 LLDPD_RXTX_FROM_PORT(port
));
459 /* Local and remote port */
461 case lldpctl_k_port_protocol
:
462 return map_lookup(lldpd_protocol_map
.map
, port
->p_protocol
);
463 case lldpctl_k_port_id_subtype
:
464 return map_lookup(port_id_subtype_map
, port
->p_id_subtype
);
465 case lldpctl_k_port_id
:
466 switch (port
->p_id_subtype
) {
467 case LLDP_PORTID_SUBTYPE_IFNAME
:
468 case LLDP_PORTID_SUBTYPE_IFALIAS
:
469 case LLDP_PORTID_SUBTYPE_LOCAL
:
471 case LLDP_PORTID_SUBTYPE_LLADDR
:
472 return _lldpctl_dump_in_atom(atom
,
473 (uint8_t*)port
->p_id
, port
->p_id_len
,
475 case LLDP_PORTID_SUBTYPE_ADDR
:
476 switch (port
->p_id
[0]) {
477 case LLDP_MGMT_ADDR_IP4
: len
= INET_ADDRSTRLEN
+ 1; break;
478 case LLDP_MGMT_ADDR_IP6
: len
= INET6_ADDRSTRLEN
+ 1; break;
482 ipaddress
= _lldpctl_alloc_in_atom(atom
, len
);
483 if (!ipaddress
) return NULL
;
484 if (inet_ntop((port
->p_id
[0] == LLDP_MGMT_ADDR_IP4
)?
486 &port
->p_id
[1], ipaddress
, len
) == NULL
)
492 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
494 case lldpctl_k_port_descr
:
495 return port
->p_descr
;
498 case lldpctl_k_port_dot3_mautype
:
499 return map_lookup(operational_mau_type_values
,
500 port
->p_macphy
.mau_type
);
504 /* Compatibility: query the associated chassis too */
505 return lldpctl_atom_get_str(p
->chassis
, key
);
509 static lldpctl_atom_t
*
510 _lldpctl_atom_set_int_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
513 struct _lldpctl_atom_port_t
*p
=
514 (struct _lldpctl_atom_port_t
*)atom
;
515 struct lldpd_port
*port
= p
->port
;
519 case lldpctl_k_port_status
:
520 port
->p_disable_rx
= !LLDPD_RXTX_RXENABLED(value
);
521 port
->p_disable_tx
= !LLDPD_RXTX_TXENABLED(value
);
524 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
528 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
532 return _lldpctl_atom_set_atom_port(atom
, key
, NULL
);
535 static lldpctl_atom_t
*
536 _lldpctl_atom_set_str_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
539 struct _lldpctl_atom_port_t
*p
=
540 (struct _lldpctl_atom_port_t
*)atom
;
541 struct lldpd_port
*port
= p
->port
;
543 if (!value
|| !strlen(value
))
548 case lldpctl_k_port_status
:
549 return _lldpctl_atom_set_int_port(atom
, key
,
550 map_reverse_lookup(port_status_map
.map
, value
));
556 case lldpctl_k_port_id
:
558 port
->p_id
= strdup(value
);
559 port
->p_id_len
= strlen(value
);
561 case lldpctl_k_port_descr
:
563 port
->p_descr
= strdup(value
);
566 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
570 return _lldpctl_atom_set_atom_port(atom
, key
, NULL
);
574 _lldpctl_atom_get_int_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
576 struct _lldpctl_atom_port_t
*p
=
577 (struct _lldpctl_atom_port_t
*)atom
;
578 struct lldpd_port
*port
= p
->port
;
579 struct lldpd_hardware
*hardware
= p
->hardware
;
581 /* Local port only */
582 if (hardware
!= NULL
) {
584 case lldpctl_k_port_index
:
585 return hardware
->h_ifindex
;
586 case lldpctl_k_tx_cnt
:
587 return hardware
->h_tx_cnt
;
588 case lldpctl_k_rx_cnt
:
589 return hardware
->h_rx_cnt
;
590 case lldpctl_k_rx_discarded_cnt
:
591 return hardware
->h_rx_discarded_cnt
;
592 case lldpctl_k_rx_unrecognized_cnt
:
593 return hardware
->h_rx_unrecognized_cnt
;
594 case lldpctl_k_ageout_cnt
:
595 return hardware
->h_ageout_cnt
;
596 case lldpctl_k_insert_cnt
:
597 return hardware
->h_insert_cnt
;
598 case lldpctl_k_delete_cnt
:
599 return hardware
->h_delete_cnt
;
605 case lldpctl_k_port_status
:
606 return LLDPD_RXTX_FROM_PORT(port
);
611 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
613 /* Local and remote port */
615 case lldpctl_k_port_protocol
:
616 return port
->p_protocol
;
617 case lldpctl_k_port_age
:
618 return port
->p_lastchange
;
619 case lldpctl_k_port_ttl
:
621 case lldpctl_k_port_id_subtype
:
622 return port
->p_id_subtype
;
623 case lldpctl_k_port_hidden
:
624 return port
->p_hidden_in
;
626 case lldpctl_k_port_dot3_mfs
:
630 case lldpctl_k_port_dot3_aggregid
:
631 if (port
->p_aggregid
> 0)
632 return port
->p_aggregid
;
634 case lldpctl_k_port_dot3_autoneg_support
:
635 return port
->p_macphy
.autoneg_support
;
636 case lldpctl_k_port_dot3_autoneg_enabled
:
637 return port
->p_macphy
.autoneg_enabled
;
638 case lldpctl_k_port_dot3_autoneg_advertised
:
639 return port
->p_macphy
.autoneg_advertised
;
640 case lldpctl_k_port_dot3_mautype
:
641 return port
->p_macphy
.mau_type
;
644 case lldpctl_k_port_vlan_pvid
:
648 /* Compatibility: query the associated chassis too */
649 return lldpctl_atom_get_int(p
->chassis
, key
);
651 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
654 static const uint8_t*
655 _lldpctl_atom_get_buf_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
, size_t *n
)
657 struct _lldpctl_atom_port_t
*p
=
658 (struct _lldpctl_atom_port_t
*)atom
;
659 struct lldpd_port
*port
= p
->port
;
662 case lldpctl_k_port_id
:
664 return (uint8_t*)port
->p_id
;
666 /* Compatibility: query the associated chassis too */
667 return lldpctl_atom_get_buffer(p
->chassis
, key
, n
);
671 static struct atom_builder ports_list
=
672 { atom_ports_list
, sizeof(struct _lldpctl_atom_any_list_t
),
673 .init
= _lldpctl_atom_new_any_list
,
674 .free
= _lldpctl_atom_free_any_list
,
675 .iter
= _lldpctl_atom_iter_ports_list
,
676 .next
= _lldpctl_atom_next_ports_list
,
677 .value
= _lldpctl_atom_value_ports_list
};
679 static struct atom_builder port
=
680 { atom_port
, sizeof(struct _lldpctl_atom_port_t
),
681 .init
= _lldpctl_atom_new_port
,
682 .free
= _lldpctl_atom_free_port
,
683 .get
= _lldpctl_atom_get_atom_port
,
684 .set
= _lldpctl_atom_set_atom_port
,
685 .get_str
= _lldpctl_atom_get_str_port
,
686 .set_str
= _lldpctl_atom_set_str_port
,
687 .get_int
= _lldpctl_atom_get_int_port
,
688 .set_int
= _lldpctl_atom_set_int_port
,
689 .get_buffer
= _lldpctl_atom_get_buf_port
};
691 ATOM_BUILDER_REGISTER(ports_list
, 4);
692 ATOM_BUILDER_REGISTER(port
, 5);