1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2012 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.
21 #include <arpa/inet.h>
24 #include "../lldpd-structs.h"
27 #include "fixedpoint.h"
29 /* Translation from constants to string */
30 static lldpctl_map_t lldpd_protocol_map
[] = {
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"},
40 static lldpctl_map_t chassis_id_subtype_map
[] = {
41 { LLDP_CHASSISID_SUBTYPE_IFNAME
, "ifname"},
42 { LLDP_CHASSISID_SUBTYPE_IFALIAS
, "ifalias" },
43 { LLDP_CHASSISID_SUBTYPE_LOCAL
, "local" },
44 { LLDP_CHASSISID_SUBTYPE_LLADDR
, "mac" },
45 { LLDP_CHASSISID_SUBTYPE_ADDR
, "ip" },
46 { LLDP_CHASSISID_SUBTYPE_PORT
, "unhandled" },
47 { LLDP_CHASSISID_SUBTYPE_CHASSIS
, "unhandled" },
51 static lldpctl_map_t port_id_subtype_map
[] = {
52 { LLDP_PORTID_SUBTYPE_IFNAME
, "ifname"},
53 { LLDP_PORTID_SUBTYPE_IFALIAS
, "ifalias" },
54 { LLDP_PORTID_SUBTYPE_LOCAL
, "local" },
55 { LLDP_PORTID_SUBTYPE_LLADDR
, "mac" },
56 { LLDP_PORTID_SUBTYPE_ADDR
, "ip" },
57 { LLDP_PORTID_SUBTYPE_PORT
, "unhandled" },
58 { LLDP_PORTID_SUBTYPE_AGENTCID
, "unhandled" },
63 static lldpctl_map_t operational_mau_type_values
[] = {
64 { 1, "AUI - no internal MAU, view from AUI" },
65 { 2, "10Base5 - thick coax MAU" },
66 { 3, "Foirl - FOIRL MAU" },
67 { 4, "10Base2 - thin coax MAU" },
68 { 5, "10BaseT - UTP MAU" },
69 { 6, "10BaseFP - passive fiber MAU" },
70 { 7, "10BaseFB - sync fiber MAU" },
71 { 8, "10BaseFL - async fiber MAU" },
72 { 9, "10Broad36 - broadband DTE MAU" },
73 { 10, "10BaseTHD - UTP MAU, half duplex mode" },
74 { 11, "10BaseTFD - UTP MAU, full duplex mode" },
75 { 12, "10BaseFLHD - async fiber MAU, half duplex mode" },
76 { 13, "10BaseFLDF - async fiber MAU, full duplex mode" },
77 { 14, "10BaseT4 - 4 pair category 3 UTP" },
78 { 15, "100BaseTXHD - 2 pair category 5 UTP, half duplex mode" },
79 { 16, "100BaseTXFD - 2 pair category 5 UTP, full duplex mode" },
80 { 17, "100BaseFXHD - X fiber over PMT, half duplex mode" },
81 { 18, "100BaseFXFD - X fiber over PMT, full duplex mode" },
82 { 19, "100BaseT2HD - 2 pair category 3 UTP, half duplex mode" },
83 { 20, "100BaseT2FD - 2 pair category 3 UTP, full duplex mode" },
84 { 21, "1000BaseXHD - PCS/PMA, unknown PMD, half duplex mode" },
85 { 22, "1000BaseXFD - PCS/PMA, unknown PMD, full duplex mode" },
86 { 23, "1000BaseLXHD - Fiber over long-wavelength laser, half duplex mode" },
87 { 24, "1000BaseLXFD - Fiber over long-wavelength laser, full duplex mode" },
88 { 25, "1000BaseSXHD - Fiber over short-wavelength laser, half duplex mode" },
89 { 26, "1000BaseSXFD - Fiber over short-wavelength laser, full duplex mode" },
90 { 27, "1000BaseCXHD - Copper over 150-Ohm balanced cable, half duplex mode" },
91 { 28, "1000BaseCXFD - Copper over 150-Ohm balanced cable, full duplex mode" },
92 { 29, "1000BaseTHD - Four-pair Category 5 UTP, half duplex mode" },
93 { 30, "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode" },
94 { 31, "10GigBaseX - X PCS/PMA, unknown PMD." },
95 { 32, "10GigBaseLX4 - X fiber over WWDM optics" },
96 { 33, "10GigBaseR - R PCS/PMA, unknown PMD." },
97 { 34, "10GigBaseER - R fiber over 1550 nm optics" },
98 { 35, "10GigBaseLR - R fiber over 1310 nm optics" },
99 { 36, "10GigBaseSR - R fiber over 850 nm optics" },
100 { 37, "10GigBaseW - W PCS/PMA, unknown PMD." },
101 { 38, "10GigBaseEW - W fiber over 1550 nm optics" },
102 { 39, "10GigBaseLW - W fiber over 1310 nm optics" },
103 { 40, "10GigBaseSW - W fiber over 850 nm optics" },
104 { 41, "10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable" },
105 { 42, "2BaseTL - Voice grade UTP copper, up to 2700m, optional PAF" },
106 { 43, "10PassTS - Voice grade UTP copper, up to 750m, optional PAF" },
107 { 44, "100BaseBX10D - One single-mode fiber OLT, long wavelength, 10km" },
108 { 45, "100BaseBX10U - One single-mode fiber ONU, long wavelength, 10km" },
109 { 46, "100BaseLX10 - Two single-mode fibers, long wavelength, 10km" },
110 { 47, "1000BaseBX10D - One single-mode fiber OLT, long wavelength, 10km" },
111 { 48, "1000BaseBX10U - One single-mode fiber ONU, long wavelength, 10km" },
112 { 49, "1000BaseLX10 - Two sigle-mode fiber, long wavelength, 10km" },
113 { 50, "1000BasePX10D - One single-mode fiber EPON OLT, 10km" },
114 { 51, "1000BasePX10U - One single-mode fiber EPON ONU, 10km" },
115 { 52, "1000BasePX20D - One single-mode fiber EPON OLT, 20km" },
116 { 53, "1000BasePX20U - One single-mode fiber EPON ONU, 20km" },
120 static lldpctl_map_t port_dot3_power_devicetype_map
[] = {
121 { LLDP_DOT3_POWER_PSE
, "PSE" },
122 { LLDP_DOT3_POWER_PD
, "PD" },
126 static lldpctl_map_t port_dot3_power_pairs_map
[] = {
127 { LLDP_DOT3_POWERPAIRS_SIGNAL
, "signal" },
128 { LLDP_DOT3_POWERPAIRS_SPARE
, "spare" },
132 static lldpctl_map_t port_dot3_power_class_map
[] = {
141 static lldpctl_map_t port_dot3_power_pse_source_map
[] = {
142 { LLDP_DOT3_POWER_SOURCE_BOTH
, "PSE + Local" },
143 { LLDP_DOT3_POWER_SOURCE_PSE
, "PSE" },
147 static lldpctl_map_t port_dot3_power_pd_source_map
[] = {
148 { LLDP_DOT3_POWER_SOURCE_BACKUP
, "Backup source" },
149 { LLDP_DOT3_POWER_SOURCE_PRIMARY
, "Primary power source" },
153 static lldpctl_map_t port_dot3_power_priority_map
[] = {
155 { LLDP_MED_POW_PRIO_CRITICAL
, "critical" },
156 { LLDP_MED_POW_PRIO_HIGH
, "high" },
157 { LLDP_MED_POW_PRIO_LOW
, "low" },
162 #ifdef ENABLE_LLDPMED
163 static lldpctl_map_t chassis_med_type_map
[] = {
164 { LLDP_MED_CLASS_I
, "Generic Endpoint (Class I)" },
165 { LLDP_MED_CLASS_II
, "Media Endpoint (Class II)" },
166 { LLDP_MED_CLASS_III
, "Communication Device Endpoint (Class III)" },
167 { LLDP_MED_NETWORK_DEVICE
, "Network Connectivity Device" },
171 static lldpctl_map_t port_med_policy_map
[] = {
172 { LLDP_MED_APPTYPE_VOICE
, "Voice"},
173 { LLDP_MED_APPTYPE_VOICESIGNAL
, "Voice Signaling"},
174 { LLDP_MED_APPTYPE_GUESTVOICE
, "Guest Voice"},
175 { LLDP_MED_APPTYPE_GUESTVOICESIGNAL
, "Guest Voice Signaling"},
176 { LLDP_MED_APPTYPE_SOFTPHONEVOICE
, "Softphone Voice"},
177 { LLDP_MED_APPTYPE_VIDEOCONFERENCE
, "Video Conferencing"},
178 { LLDP_MED_APPTYPE_VIDEOSTREAM
, "Streaming Video"},
179 { LLDP_MED_APPTYPE_VIDEOSIGNAL
, "Video Signaling"},
183 static lldpctl_map_t port_med_policy_prio_map
[] = {
186 { 2, "Best effort" },
187 { 3, "Excellent effort" },
188 { 4, "Controlled load" },
191 { 7, "Network control" },
195 static lldpctl_map_t port_med_location_map
[] = {
196 { LLDP_MED_LOCFORMAT_COORD
, "Coordinates" },
197 { LLDP_MED_LOCFORMAT_CIVIC
, "Civic address" },
198 { LLDP_MED_LOCFORMAT_ELIN
, "ELIN" },
202 static lldpctl_map_t civic_address_type_map
[] = {
204 { 1, "Country subdivision" },
207 { 4, "City division" },
211 { 17, "Trailing street suffix" },
212 { 18, "Street suffix" },
214 { 20, "Number suffix" },
216 { 22, "Additional" },
223 { 29, "Place type" },
228 static lldpctl_map_t port_med_geoid_map
[] = {
229 { LLDP_MED_LOCATION_GEOID_WGS84
, "WGS84" },
230 { LLDP_MED_LOCATION_GEOID_NAD83
, "NAD83" },
231 { LLDP_MED_LOCATION_GEOID_NAD83_MLLW
, "NAD83/MLLW" },
235 static lldpctl_map_t port_med_pow_devicetype_map
[] = {
236 { LLDP_MED_POW_TYPE_PSE
, "PSE" },
237 { LLDP_MED_POW_TYPE_PD
, "PD" },
241 static lldpctl_map_t port_med_pow_source_map
[] = {
242 { LLDP_MED_POW_SOURCE_PRIMARY
, "Primary Power Source" },
243 { LLDP_MED_POW_SOURCE_BACKUP
, "Backup Power Source / Power Conservation Mode" },
244 { LLDP_MED_POW_SOURCE_PSE
, "PSE" },
245 { LLDP_MED_POW_SOURCE_LOCAL
, "Local"},
246 { LLDP_MED_POW_SOURCE_BOTH
, "PSE + Local"},
250 static lldpctl_map_t port_med_pow_source_map2
[] = {
252 { LLDP_MED_POW_SOURCE_PRIMARY
, "primary" },
253 { LLDP_MED_POW_SOURCE_BACKUP
, "backup" },
254 { LLDP_MED_POW_SOURCE_PSE
, "pse" },
255 { LLDP_MED_POW_SOURCE_LOCAL
, "local" },
256 { LLDP_MED_POW_SOURCE_BOTH
, "both" },
260 static lldpctl_map_t
*port_med_pow_priority_map
= port_dot3_power_priority_map
;
263 static lldpctl_map_t bond_slave_src_mac_map
[] = {
264 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_REAL
, "real"},
265 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_ZERO
, "zero"},
266 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_FIXED
, "fixed"},
267 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED
, "local" },
268 { LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN
, NULL
},
272 map_lookup(lldpctl_map_t
*list
, int n
)
277 for (i
= 0; list
[i
].string
!= NULL
; i
++) {
278 if (list
[i
].value
== n
) {
279 return list
[i
].string
;
286 #if defined ENABLE_LLDPMED || defined ENABLE_DOT3
288 map_reverse_lookup(lldpctl_map_t
*list
, const char *string
)
292 for (i
= 0; list
[i
].string
!= NULL
; i
++) {
293 if (!strcasecmp(list
[i
].string
, string
))
294 return list
[i
].value
;
301 static lldpctl_map_t empty_map
[] = {{ 0, NULL
}};
304 lldpctl_key_get_map(lldpctl_key_t key
)
307 #ifdef ENABLE_LLDPMED
308 case lldpctl_k_med_location_geoid
:
309 return port_med_geoid_map
;
310 case lldpctl_k_med_civicaddress_type
:
311 return civic_address_type_map
;
312 case lldpctl_k_med_policy_type
:
313 return port_med_policy_map
;
314 case lldpctl_k_med_policy_priority
:
315 return port_med_policy_prio_map
;
316 case lldpctl_k_med_power_priority
:
317 return port_med_pow_priority_map
;
320 case lldpctl_k_dot3_power_pairs
:
321 return port_dot3_power_pairs_map
;
322 case lldpctl_k_dot3_power_class
:
323 return port_dot3_power_class_map
;
324 case lldpctl_k_dot3_power_priority
:
325 return port_dot3_power_priority_map
;
327 case lldpctl_k_config_bond_slave_src_mac_type
:
328 return bond_slave_src_mac_map
;
329 default: return empty_map
;
336 _lldpctl_atom_new_config(lldpctl_atom_t
*atom
, va_list ap
)
338 struct _lldpctl_atom_config_t
*c
=
339 (struct _lldpctl_atom_config_t
*)atom
;
340 c
->config
= va_arg(ap
, struct lldpd_config
*);
345 _lldpctl_atom_free_config(lldpctl_atom_t
*atom
)
347 struct _lldpctl_atom_config_t
*c
=
348 (struct _lldpctl_atom_config_t
*)atom
;
349 lldpd_config_cleanup(c
->config
);
354 _lldpctl_atom_get_str_config(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
357 struct _lldpctl_atom_config_t
*c
=
358 (struct _lldpctl_atom_config_t
*)atom
;
360 case lldpctl_k_config_mgmt_pattern
:
361 res
= c
->config
->c_mgmt_pattern
; break;
362 case lldpctl_k_config_iface_pattern
:
363 res
= c
->config
->c_iface_pattern
; break;
364 case lldpctl_k_config_cid_pattern
:
365 res
= c
->config
->c_cid_pattern
; break;
366 case lldpctl_k_config_description
:
367 res
= c
->config
->c_description
; break;
368 case lldpctl_k_config_platform
:
369 res
= c
->config
->c_platform
; break;
370 case lldpctl_k_config_bond_slave_src_mac_type
:
371 return map_lookup(bond_slave_src_mac_map
,
372 c
->config
->c_bond_slave_src_mac_type
);
374 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
380 static lldpctl_atom_t
*
381 _lldpctl_atom_set_str_config(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
384 struct _lldpctl_atom_config_t
*c
=
385 (struct _lldpctl_atom_config_t
*)atom
;
386 struct lldpd_config config
= {};
387 char *iface_pattern
= NULL
;
388 char *description
= NULL
;
391 len
= strlen(value
) + 1;
394 case lldpctl_k_config_iface_pattern
:
395 iface_pattern
= _lldpctl_alloc_in_atom(atom
, strlen(value
) + 1);
398 memcpy(iface_pattern
, value
, len
);
399 config
.c_iface_pattern
= iface_pattern
;
400 free(c
->config
->c_iface_pattern
);
401 c
->config
->c_iface_pattern
= strdup(iface_pattern
);
403 case lldpctl_k_config_description
:
404 description
= _lldpctl_alloc_in_atom(atom
, strlen(value
) + 1);
407 memcpy(description
, value
, len
);
408 config
.c_description
= description
;
409 free(c
->config
->c_description
);
410 c
->config
->c_description
= strdup(description
);
412 case lldpctl_k_config_platform
:
413 description
= _lldpctl_alloc_in_atom(atom
, strlen(value
) + 1);
416 memcpy(description
, value
, len
);
417 config
.c_platform
= description
;
418 free(c
->config
->c_platform
);
419 c
->config
->c_description
= strdup(description
);
422 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
426 rc
= _lldpctl_do_something(atom
->conn
,
427 CONN_STATE_SET_CONFIG_SEND
, CONN_STATE_SET_CONFIG_RECV
,
429 SET_CONFIG
, &config
, &MARSHAL_INFO(lldpd_config
),
431 if (rc
== 0) return atom
;
437 _lldpctl_atom_get_int_config(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
439 struct _lldpctl_atom_config_t
*c
=
440 (struct _lldpctl_atom_config_t
*)atom
;
442 case lldpctl_k_config_paused
:
443 return c
->config
->c_paused
;
444 case lldpctl_k_config_tx_interval
:
445 return c
->config
->c_tx_interval
;
446 case lldpctl_k_config_receiveonly
:
447 return c
->config
->c_receiveonly
;
448 case lldpctl_k_config_advertise_version
:
449 return c
->config
->c_advertise_version
;
450 case lldpctl_k_config_ifdescr_update
:
451 return c
->config
->c_set_ifdescr
;
452 #ifdef ENABLE_LLDPMED
453 case lldpctl_k_config_lldpmed_noinventory
:
454 return c
->config
->c_noinventory
;
455 case lldpctl_k_config_fast_start_enabled
:
456 return c
->config
->c_enable_fast_start
;
457 case lldpctl_k_config_fast_start_interval
:
458 return c
->config
->c_tx_fast_interval
;
460 case lldpctl_k_config_tx_hold
:
461 return c
->config
->c_tx_hold
;
463 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
467 static lldpctl_atom_t
*
468 _lldpctl_atom_set_int_config(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
472 struct _lldpctl_atom_config_t
*c
=
473 (struct _lldpctl_atom_config_t
*)atom
;
474 struct lldpd_config config
= {};
477 case lldpctl_k_config_paused
:
478 config
.c_paused
= c
->config
->c_paused
= value
;
480 case lldpctl_k_config_tx_interval
:
481 config
.c_tx_interval
= value
;
482 if (value
> 0) c
->config
->c_tx_interval
= value
;
484 case lldpctl_k_config_ifdescr_update
:
485 config
.c_set_ifdescr
= c
->config
->c_set_ifdescr
= value
;
487 #ifdef ENABLE_LLDPMED
488 case lldpctl_k_config_fast_start_enabled
:
489 config
.c_enable_fast_start
= value
?1:2;
490 c
->config
->c_enable_fast_start
= value
;
492 case lldpctl_k_config_fast_start_interval
:
493 config
.c_tx_fast_interval
= c
->config
->c_tx_fast_interval
= value
;
496 case lldpctl_k_config_tx_hold
:
497 config
.c_tx_hold
= value
;
498 if (value
> 0) c
->config
->c_tx_hold
= value
;
500 case lldpctl_k_config_bond_slave_src_mac_type
:
501 config
.c_bond_slave_src_mac_type
= value
;
502 c
->config
->c_bond_slave_src_mac_type
= value
;
505 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
509 rc
= _lldpctl_do_something(atom
->conn
,
510 CONN_STATE_SET_CONFIG_SEND
, CONN_STATE_SET_CONFIG_RECV
,
512 SET_CONFIG
, &config
, &MARSHAL_INFO(lldpd_config
),
514 if (rc
== 0) return atom
;
520 _lldpctl_atom_new_interfaces_list(lldpctl_atom_t
*atom
, va_list ap
)
522 struct _lldpctl_atom_interfaces_list_t
*iflist
=
523 (struct _lldpctl_atom_interfaces_list_t
*)atom
;
524 iflist
->ifs
= va_arg(ap
, struct lldpd_interface_list
*);
529 _lldpctl_atom_free_interfaces_list(lldpctl_atom_t
*atom
)
531 struct _lldpctl_atom_interfaces_list_t
*iflist
=
532 (struct _lldpctl_atom_interfaces_list_t
*)atom
;
533 struct lldpd_interface
*iface
, *iface_next
;
534 for (iface
= TAILQ_FIRST(iflist
->ifs
);
536 iface
= iface_next
) {
537 /* Don't TAILQ_REMOVE, this is not a real list! */
538 iface_next
= TAILQ_NEXT(iface
, next
);
545 static lldpctl_atom_iter_t
*
546 _lldpctl_atom_iter_interfaces_list(lldpctl_atom_t
*atom
)
548 struct _lldpctl_atom_interfaces_list_t
*iflist
=
549 (struct _lldpctl_atom_interfaces_list_t
*)atom
;
550 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(iflist
->ifs
);
553 static lldpctl_atom_iter_t
*
554 _lldpctl_atom_next_interfaces_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
556 return (lldpctl_atom_iter_t
*)TAILQ_NEXT((struct lldpd_interface
*)iter
, next
);
559 static lldpctl_atom_t
*
560 _lldpctl_atom_value_interfaces_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
562 struct lldpd_interface
*iface
= (struct lldpd_interface
*)iter
;
563 return _lldpctl_new_atom(atom
->conn
, atom_interface
, iface
->name
);
567 _lldpctl_atom_new_interface(lldpctl_atom_t
*atom
, va_list ap
)
569 struct _lldpctl_atom_interface_t
*port
=
570 (struct _lldpctl_atom_interface_t
*)atom
;
571 port
->name
= strdup(va_arg(ap
, char *));
572 return (port
->name
!= NULL
);
576 _lldpctl_atom_free_interface(lldpctl_atom_t
*atom
)
578 struct _lldpctl_atom_interface_t
*port
=
579 (struct _lldpctl_atom_interface_t
*)atom
;
584 _lldpctl_atom_get_str_interface(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
586 struct _lldpctl_atom_interface_t
*port
=
587 (struct _lldpctl_atom_interface_t
*)atom
;
589 case lldpctl_k_interface_name
:
592 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
598 _lldpctl_atom_new_any_list(lldpctl_atom_t
*atom
, va_list ap
)
600 struct _lldpctl_atom_any_list_t
*plist
=
601 (struct _lldpctl_atom_any_list_t
*)atom
;
602 plist
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
603 lldpctl_atom_inc_ref((lldpctl_atom_t
*)plist
->parent
);
608 _lldpctl_atom_free_any_list(lldpctl_atom_t
*atom
)
610 struct _lldpctl_atom_any_list_t
*plist
=
611 (struct _lldpctl_atom_any_list_t
*)atom
;
612 lldpctl_atom_dec_ref((lldpctl_atom_t
*)plist
->parent
);
615 static lldpctl_atom_iter_t
*
616 _lldpctl_atom_iter_ports_list(lldpctl_atom_t
*atom
)
618 struct _lldpctl_atom_any_list_t
*plist
=
619 (struct _lldpctl_atom_any_list_t
*)atom
;
620 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(&plist
->parent
->hardware
->h_rports
);
623 static lldpctl_atom_iter_t
*
624 _lldpctl_atom_next_ports_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
626 struct lldpd_port
*port
= (struct lldpd_port
*)iter
;
627 return (lldpctl_atom_iter_t
*)TAILQ_NEXT(port
, p_entries
);
630 static lldpctl_atom_t
*
631 _lldpctl_atom_value_ports_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
633 struct lldpd_port
*port
= (struct lldpd_port
*)iter
;
634 return _lldpctl_new_atom(atom
->conn
, atom_port
, NULL
, port
,
635 ((struct _lldpctl_atom_any_list_t
*)atom
)->parent
);
639 _lldpctl_atom_new_port(lldpctl_atom_t
*atom
, va_list ap
)
641 struct _lldpctl_atom_port_t
*port
=
642 (struct _lldpctl_atom_port_t
*)atom
;
643 port
->hardware
= va_arg(ap
, struct lldpd_hardware
*);
644 port
->port
= va_arg(ap
, struct lldpd_port
*);
645 port
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
647 lldpctl_atom_inc_ref((lldpctl_atom_t
*)port
->parent
);
651 TAILQ_HEAD(chassis_list
, lldpd_chassis
);
654 add_chassis(struct chassis_list
*chassis_list
,
655 struct lldpd_chassis
*chassis
)
657 struct lldpd_chassis
*one_chassis
;
658 TAILQ_FOREACH(one_chassis
, chassis_list
, c_entries
) {
659 if (one_chassis
== chassis
) return;
661 TAILQ_INSERT_TAIL(chassis_list
,
666 _lldpctl_atom_free_port(lldpctl_atom_t
*atom
)
668 struct _lldpctl_atom_port_t
*port
=
669 (struct _lldpctl_atom_port_t
*)atom
;
670 struct lldpd_hardware
*hardware
= port
->hardware
;
671 struct lldpd_chassis
*one_chassis
, *one_chassis_next
;
672 struct lldpd_port
*one_port
;
674 /* We need to free the whole struct lldpd_hardware: local port, local
675 * chassis and remote ports... The same chassis may be present several
676 * times. We build a list of chassis (we don't use reference count). */
677 struct chassis_list chassis_list
;
678 TAILQ_INIT(&chassis_list
);
680 if (port
->parent
) lldpctl_atom_dec_ref((lldpctl_atom_t
*)port
->parent
);
681 else if (!hardware
) {
682 /* No parent, no hardware, we assume a single neighbor: one
683 * port, one chassis. */
684 lldpd_chassis_cleanup(port
->port
->p_chassis
, 1);
685 port
->port
->p_chassis
= NULL
;
686 lldpd_port_cleanup(port
->port
, 1);
689 if (!hardware
) return;
691 add_chassis(&chassis_list
, port
->port
->p_chassis
);
692 TAILQ_FOREACH(one_port
, &hardware
->h_rports
, p_entries
)
693 add_chassis(&chassis_list
, one_port
->p_chassis
);
695 /* Free hardware port */
696 lldpd_remote_cleanup(hardware
, NULL
, 1);
697 lldpd_port_cleanup(port
->port
, 1);
698 free(port
->hardware
);
700 /* Free list of chassis */
701 for (one_chassis
= TAILQ_FIRST(&chassis_list
);
703 one_chassis
= one_chassis_next
) {
704 one_chassis_next
= TAILQ_NEXT(one_chassis
, c_entries
);
705 lldpd_chassis_cleanup(one_chassis
, 1);
709 static lldpctl_atom_t
*
710 _lldpctl_atom_get_atom_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
712 struct _lldpctl_atom_port_t
*p
=
713 (struct _lldpctl_atom_port_t
*)atom
;
714 struct lldpd_port
*port
= p
->port
;
715 struct lldpd_hardware
*hardware
= p
->hardware
;
717 /* Local port only */
718 if (hardware
!= NULL
) {
720 case lldpctl_k_port_neighbors
:
721 return _lldpctl_new_atom(atom
->conn
, atom_ports_list
, p
);
726 /* Local and remote port */
728 case lldpctl_k_chassis_mgmt
:
729 return _lldpctl_new_atom(atom
->conn
, atom_mgmts_list
,
732 case lldpctl_k_port_dot3_power
:
733 return _lldpctl_new_atom(atom
->conn
, atom_dot3_power
,
737 case lldpctl_k_port_vlans
:
738 return _lldpctl_new_atom(atom
->conn
, atom_vlans_list
,
740 case lldpctl_k_port_ppvids
:
741 return _lldpctl_new_atom(atom
->conn
, atom_ppvids_list
,
743 case lldpctl_k_port_pis
:
744 return _lldpctl_new_atom(atom
->conn
, atom_pis_list
,
747 #ifdef ENABLE_LLDPMED
748 case lldpctl_k_port_med_policies
:
749 return _lldpctl_new_atom(atom
->conn
, atom_med_policies_list
,
751 case lldpctl_k_port_med_locations
:
752 return _lldpctl_new_atom(atom
->conn
, atom_med_locations_list
,
754 case lldpctl_k_port_med_power
:
755 return _lldpctl_new_atom(atom
->conn
, atom_med_power
, p
);
758 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
763 static lldpctl_atom_t
*
764 _lldpctl_atom_set_atom_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
, lldpctl_atom_t
*value
)
766 struct _lldpctl_atom_port_t
*p
=
767 (struct _lldpctl_atom_port_t
*)atom
;
768 struct lldpd_hardware
*hardware
= p
->hardware
;
769 struct lldpd_port_set set
= {};
773 struct _lldpctl_atom_dot3_power_t
*dpow
;
775 #ifdef ENABLE_LLDPMED
776 struct _lldpctl_atom_med_power_t
*mpow
;
777 struct _lldpctl_atom_med_policy_t
*mpol
;
778 struct _lldpctl_atom_med_location_t
*mloc
;
781 /* Local port only */
782 if (hardware
== NULL
) {
783 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
789 case lldpctl_k_port_dot3_power
:
790 if (value
->type
!= atom_dot3_power
) {
791 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
795 dpow
= (struct _lldpctl_atom_dot3_power_t
*)value
;
796 set
.dot3_power
= &dpow
->parent
->port
->p_power
;
799 #ifdef ENABLE_LLDPMED
800 case lldpctl_k_port_med_power
:
801 if (value
->type
!= atom_med_power
) {
802 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
806 mpow
= (struct _lldpctl_atom_med_power_t
*)value
;
807 set
.med_power
= &mpow
->parent
->port
->p_med_power
;
809 case lldpctl_k_port_med_policies
:
810 if (value
->type
!= atom_med_policy
) {
811 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
814 mpol
= (struct _lldpctl_atom_med_policy_t
*)value
;
815 set
.med_policy
= mpol
->policy
;
817 case lldpctl_k_port_med_locations
:
818 if (value
->type
!= atom_med_location
) {
819 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
822 mloc
= (struct _lldpctl_atom_med_location_t
*)value
;
823 set
.med_location
= mloc
->location
;
827 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
831 set
.ifname
= hardware
->h_ifname
;
832 rc
= _lldpctl_do_something(atom
->conn
,
833 CONN_STATE_SET_PORT_SEND
, CONN_STATE_SET_PORT_RECV
,
835 SET_PORT
, &set
, &MARSHAL_INFO(lldpd_port_set
),
837 if (rc
== 0) return atom
;
842 _lldpctl_atom_get_str_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
844 struct _lldpctl_atom_port_t
*p
=
845 (struct _lldpctl_atom_port_t
*)atom
;
846 struct lldpd_port
*port
= p
->port
;
847 struct lldpd_hardware
*hardware
= p
->hardware
;
848 struct lldpd_chassis
*chassis
= port
->p_chassis
;
849 char *ipaddress
= NULL
; size_t len
;
851 /* Local port only */
852 if (hardware
!= NULL
) {
854 case lldpctl_k_port_name
:
855 return hardware
->h_ifname
;
860 /* Local and remote port */
862 case lldpctl_k_port_protocol
:
863 return map_lookup(lldpd_protocol_map
, port
->p_protocol
);
864 case lldpctl_k_port_id_subtype
:
865 return map_lookup(port_id_subtype_map
, port
->p_id_subtype
);
866 case lldpctl_k_port_id
:
867 switch (port
->p_id_subtype
) {
868 case LLDP_PORTID_SUBTYPE_IFNAME
:
869 case LLDP_PORTID_SUBTYPE_IFALIAS
:
870 case LLDP_PORTID_SUBTYPE_LOCAL
:
872 case LLDP_PORTID_SUBTYPE_LLADDR
:
873 return _lldpctl_dump_in_atom(atom
,
874 (uint8_t*)port
->p_id
, port
->p_id_len
,
876 case LLDP_PORTID_SUBTYPE_ADDR
:
877 switch (port
->p_id
[0]) {
878 case LLDP_MGMT_ADDR_IP4
: len
= INET_ADDRSTRLEN
+ 1; break;
879 case LLDP_MGMT_ADDR_IP6
: len
= INET6_ADDRSTRLEN
+ 1; break;
883 ipaddress
= _lldpctl_alloc_in_atom(atom
, len
);
884 if (!ipaddress
) return NULL
;
885 if (inet_ntop((port
->p_id
[0] == LLDP_MGMT_ADDR_IP4
)?
887 &port
->p_id
[1], ipaddress
, len
) == NULL
)
893 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
895 case lldpctl_k_port_descr
:
896 return port
->p_descr
;
899 case lldpctl_k_port_dot3_mautype
:
900 return map_lookup(operational_mau_type_values
,
901 port
->p_macphy
.mau_type
);
904 case lldpctl_k_chassis_id_subtype
:
905 return map_lookup(chassis_id_subtype_map
, chassis
->c_id_subtype
);
906 case lldpctl_k_chassis_id
:
907 switch (chassis
->c_id_subtype
) {
908 case LLDP_CHASSISID_SUBTYPE_IFNAME
:
909 case LLDP_CHASSISID_SUBTYPE_IFALIAS
:
910 case LLDP_CHASSISID_SUBTYPE_LOCAL
:
911 return chassis
->c_id
;
912 case LLDP_CHASSISID_SUBTYPE_LLADDR
:
913 return _lldpctl_dump_in_atom(atom
,
914 (uint8_t*)chassis
->c_id
, chassis
->c_id_len
,
916 case LLDP_CHASSISID_SUBTYPE_ADDR
:
917 switch (chassis
->c_id
[0]) {
918 case LLDP_MGMT_ADDR_IP4
: len
= INET_ADDRSTRLEN
+ 1; break;
919 case LLDP_MGMT_ADDR_IP6
: len
= INET6_ADDRSTRLEN
+ 1; break;
923 ipaddress
= _lldpctl_alloc_in_atom(atom
, len
);
924 if (!ipaddress
) return NULL
;
925 if (inet_ntop((chassis
->c_id
[0] == LLDP_MGMT_ADDR_IP4
)?
927 &chassis
->c_id
[1], ipaddress
, len
) == NULL
)
933 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
935 case lldpctl_k_chassis_name
: return chassis
->c_name
;
936 case lldpctl_k_chassis_descr
: return chassis
->c_descr
;
938 #ifdef ENABLE_LLDPMED
939 case lldpctl_k_chassis_med_type
:
940 return map_lookup(chassis_med_type_map
, chassis
->c_med_type
);
941 case lldpctl_k_chassis_med_inventory_hw
:
942 return chassis
->c_med_hw
;
943 case lldpctl_k_chassis_med_inventory_sw
:
944 return chassis
->c_med_sw
;
945 case lldpctl_k_chassis_med_inventory_fw
:
946 return chassis
->c_med_fw
;
947 case lldpctl_k_chassis_med_inventory_sn
:
948 return chassis
->c_med_sn
;
949 case lldpctl_k_chassis_med_inventory_manuf
:
950 return chassis
->c_med_manuf
;
951 case lldpctl_k_chassis_med_inventory_model
:
952 return chassis
->c_med_model
;
953 case lldpctl_k_chassis_med_inventory_asset
:
954 return chassis
->c_med_asset
;
958 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
964 _lldpctl_atom_get_int_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
966 struct _lldpctl_atom_port_t
*p
=
967 (struct _lldpctl_atom_port_t
*)atom
;
968 struct lldpd_port
*port
= p
->port
;
969 struct lldpd_hardware
*hardware
= p
->hardware
;
970 struct lldpd_chassis
*chassis
= port
->p_chassis
;
972 /* Local port only */
973 if (hardware
!= NULL
) {
975 case lldpctl_k_port_index
:
976 return hardware
->h_ifindex
;
977 case lldpctl_k_tx_cnt
:
978 return hardware
->h_tx_cnt
;
979 case lldpctl_k_rx_cnt
:
980 return hardware
->h_rx_cnt
;
981 case lldpctl_k_rx_discarded_cnt
:
982 return hardware
->h_rx_discarded_cnt
;
983 case lldpctl_k_rx_unrecognized_cnt
:
984 return hardware
->h_rx_unrecognized_cnt
;
985 case lldpctl_k_ageout_cnt
:
986 return hardware
->h_ageout_cnt
;
987 case lldpctl_k_insert_cnt
:
988 return hardware
->h_insert_cnt
;
989 case lldpctl_k_delete_cnt
:
990 return hardware
->h_delete_cnt
;
995 /* Local and remote port */
997 case lldpctl_k_port_protocol
:
998 return port
->p_protocol
;
999 case lldpctl_k_port_age
:
1000 return port
->p_lastchange
;
1001 case lldpctl_k_port_id_subtype
:
1002 return port
->p_id_subtype
;
1003 case lldpctl_k_port_hidden
:
1004 return port
->p_hidden_in
;
1006 case lldpctl_k_port_dot3_mfs
:
1007 if (port
->p_mfs
> 0)
1010 case lldpctl_k_port_dot3_aggregid
:
1011 if (port
->p_aggregid
> 0)
1012 return port
->p_aggregid
;
1014 case lldpctl_k_port_dot3_autoneg_support
:
1015 return port
->p_macphy
.autoneg_support
;
1016 case lldpctl_k_port_dot3_autoneg_enabled
:
1017 return port
->p_macphy
.autoneg_enabled
;
1018 case lldpctl_k_port_dot3_autoneg_advertised
:
1019 return port
->p_macphy
.autoneg_advertised
;
1020 case lldpctl_k_port_dot3_mautype
:
1021 return port
->p_macphy
.mau_type
;
1024 case lldpctl_k_port_vlan_pvid
:
1025 return port
->p_pvid
;
1027 case lldpctl_k_chassis_index
:
1028 return chassis
->c_index
;
1029 case lldpctl_k_chassis_id_subtype
:
1030 return chassis
->c_id_subtype
;
1031 case lldpctl_k_chassis_cap_available
:
1032 return chassis
->c_cap_available
;
1033 case lldpctl_k_chassis_cap_enabled
:
1034 return chassis
->c_cap_enabled
;
1035 #ifdef ENABLE_LLDPMED
1036 case lldpctl_k_chassis_med_type
:
1037 return chassis
->c_med_type
;
1038 case lldpctl_k_chassis_med_cap
:
1039 return chassis
->c_med_cap_available
;
1042 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1044 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1047 static const uint8_t*
1048 _lldpctl_atom_get_buf_port(lldpctl_atom_t
*atom
, lldpctl_key_t key
, size_t *n
)
1050 struct _lldpctl_atom_port_t
*p
=
1051 (struct _lldpctl_atom_port_t
*)atom
;
1052 struct lldpd_port
*port
= p
->port
;
1053 struct lldpd_chassis
*chassis
= port
->p_chassis
;
1056 case lldpctl_k_port_id
:
1057 *n
= port
->p_id_len
;
1058 return (uint8_t*)port
->p_id
;
1059 case lldpctl_k_chassis_id
:
1060 *n
= chassis
->c_id_len
;
1061 return (uint8_t*)chassis
->c_id
;
1063 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1069 _lldpctl_atom_new_mgmts_list(lldpctl_atom_t
*atom
, va_list ap
)
1071 struct _lldpctl_atom_mgmts_list_t
*plist
=
1072 (struct _lldpctl_atom_mgmts_list_t
*)atom
;
1073 plist
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1074 plist
->chassis
= va_arg(ap
, struct lldpd_chassis
*);
1075 lldpctl_atom_inc_ref((lldpctl_atom_t
*)plist
->parent
);
1080 _lldpctl_atom_free_mgmts_list(lldpctl_atom_t
*atom
)
1082 struct _lldpctl_atom_mgmts_list_t
*plist
=
1083 (struct _lldpctl_atom_mgmts_list_t
*)atom
;
1084 lldpctl_atom_dec_ref((lldpctl_atom_t
*)plist
->parent
);
1087 static lldpctl_atom_iter_t
*
1088 _lldpctl_atom_iter_mgmts_list(lldpctl_atom_t
*atom
)
1090 struct _lldpctl_atom_mgmts_list_t
*plist
=
1091 (struct _lldpctl_atom_mgmts_list_t
*)atom
;
1092 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(&plist
->chassis
->c_mgmt
);
1095 static lldpctl_atom_iter_t
*
1096 _lldpctl_atom_next_mgmts_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1098 struct lldpd_mgmt
*mgmt
= (struct lldpd_mgmt
*)iter
;
1099 return (lldpctl_atom_iter_t
*)TAILQ_NEXT(mgmt
, m_entries
);
1102 static lldpctl_atom_t
*
1103 _lldpctl_atom_value_mgmts_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1105 struct _lldpctl_atom_mgmts_list_t
*plist
=
1106 (struct _lldpctl_atom_mgmts_list_t
*)atom
;
1107 struct lldpd_mgmt
*mgmt
= (struct lldpd_mgmt
*)iter
;
1108 return _lldpctl_new_atom(atom
->conn
, atom_mgmt
, plist
->parent
, mgmt
);
1112 _lldpctl_atom_new_mgmt(lldpctl_atom_t
*atom
, va_list ap
)
1114 struct _lldpctl_atom_mgmt_t
*mgmt
=
1115 (struct _lldpctl_atom_mgmt_t
*)atom
;
1116 mgmt
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1117 mgmt
->mgmt
= va_arg(ap
, struct lldpd_mgmt
*);
1118 lldpctl_atom_inc_ref((lldpctl_atom_t
*)mgmt
->parent
);
1123 _lldpctl_atom_free_mgmt(lldpctl_atom_t
*atom
)
1125 struct _lldpctl_atom_mgmt_t
*mgmt
=
1126 (struct _lldpctl_atom_mgmt_t
*)atom
;
1127 lldpctl_atom_dec_ref((lldpctl_atom_t
*)mgmt
->parent
);
1131 _lldpctl_atom_get_str_mgmt(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1133 char *ipaddress
= NULL
;
1135 struct _lldpctl_atom_mgmt_t
*m
=
1136 (struct _lldpctl_atom_mgmt_t
*)atom
;
1138 /* Local and remote port */
1140 case lldpctl_k_mgmt_ip
:
1141 switch (m
->mgmt
->m_family
) {
1143 len
= INET_ADDRSTRLEN
+ 1;
1147 len
= INET6_ADDRSTRLEN
+ 1;
1153 if (len
== 0) break;
1154 ipaddress
= _lldpctl_alloc_in_atom(atom
, len
);
1155 if (!ipaddress
) return NULL
;
1156 if (inet_ntop(af
, &m
->mgmt
->m_addr
, ipaddress
, len
) == NULL
)
1160 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1163 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1169 _lldpctl_atom_new_dot3_power(lldpctl_atom_t
*atom
, va_list ap
)
1171 struct _lldpctl_atom_dot3_power_t
*dpow
=
1172 (struct _lldpctl_atom_dot3_power_t
*)atom
;
1173 dpow
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1174 lldpctl_atom_inc_ref((lldpctl_atom_t
*)dpow
->parent
);
1179 _lldpctl_atom_free_dot3_power(lldpctl_atom_t
*atom
)
1181 struct _lldpctl_atom_dot3_power_t
*dpow
=
1182 (struct _lldpctl_atom_dot3_power_t
*)atom
;
1183 lldpctl_atom_dec_ref((lldpctl_atom_t
*)dpow
->parent
);
1187 _lldpctl_atom_get_str_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1189 struct _lldpctl_atom_dot3_power_t
*dpow
=
1190 (struct _lldpctl_atom_dot3_power_t
*)atom
;
1191 struct lldpd_port
*port
= dpow
->parent
->port
;
1193 /* Local and remote port */
1195 case lldpctl_k_dot3_power_devicetype
:
1196 return map_lookup(port_dot3_power_devicetype_map
,
1197 port
->p_power
.devicetype
);
1198 case lldpctl_k_dot3_power_pairs
:
1199 return map_lookup(port_dot3_power_pairs_map
,
1200 port
->p_power
.pairs
);
1201 case lldpctl_k_dot3_power_class
:
1202 return map_lookup(port_dot3_power_class_map
,
1203 port
->p_power
.class);
1204 case lldpctl_k_dot3_power_source
:
1205 return map_lookup((port
->p_power
.devicetype
== LLDP_DOT3_POWER_PSE
)?
1206 port_dot3_power_pse_source_map
:
1207 port_dot3_power_pd_source_map
,
1208 port
->p_power
.source
);
1209 case lldpctl_k_dot3_power_priority
:
1210 return map_lookup(port_dot3_power_priority_map
,
1211 port
->p_power
.priority
);
1213 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1219 _lldpctl_atom_get_int_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1221 struct _lldpctl_atom_dot3_power_t
*dpow
=
1222 (struct _lldpctl_atom_dot3_power_t
*)atom
;
1223 struct lldpd_port
*port
= dpow
->parent
->port
;
1225 /* Local and remote port */
1227 case lldpctl_k_dot3_power_devicetype
:
1228 return port
->p_power
.devicetype
;
1229 case lldpctl_k_dot3_power_supported
:
1230 return port
->p_power
.supported
;
1231 case lldpctl_k_dot3_power_enabled
:
1232 return port
->p_power
.enabled
;
1233 case lldpctl_k_dot3_power_paircontrol
:
1234 return port
->p_power
.paircontrol
;
1235 case lldpctl_k_dot3_power_pairs
:
1236 return port
->p_power
.pairs
;
1237 case lldpctl_k_dot3_power_class
:
1238 return port
->p_power
.class;
1239 case lldpctl_k_dot3_power_type
:
1240 return port
->p_power
.powertype
;
1241 case lldpctl_k_dot3_power_source
:
1242 return port
->p_power
.source
;
1243 case lldpctl_k_dot3_power_priority
:
1244 return port
->p_power
.priority
;
1245 case lldpctl_k_dot3_power_requested
:
1246 return port
->p_power
.requested
* 100;
1247 case lldpctl_k_dot3_power_allocated
:
1248 return port
->p_power
.allocated
* 100;
1250 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1254 static lldpctl_atom_t
*
1255 _lldpctl_atom_set_int_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
1258 struct _lldpctl_atom_dot3_power_t
*dpow
=
1259 (struct _lldpctl_atom_dot3_power_t
*)atom
;
1260 struct lldpd_port
*port
= dpow
->parent
->port
;
1262 /* Only local port can be modified */
1263 if (dpow
->parent
->hardware
== NULL
) {
1264 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1269 case lldpctl_k_dot3_power_devicetype
:
1271 case 0: /* Disabling */
1272 case LLDP_DOT3_POWER_PSE
:
1273 case LLDP_DOT3_POWER_PD
:
1274 port
->p_power
.devicetype
= value
;
1278 case lldpctl_k_dot3_power_supported
:
1282 port
->p_power
.supported
= value
;
1286 case lldpctl_k_dot3_power_enabled
:
1290 port
->p_power
.enabled
= value
;
1294 case lldpctl_k_dot3_power_paircontrol
:
1298 port
->p_power
.paircontrol
= value
;
1302 case lldpctl_k_dot3_power_pairs
:
1306 port
->p_power
.pairs
= value
;
1310 case lldpctl_k_dot3_power_class
:
1311 if (value
< 0 || value
> 5)
1313 port
->p_power
.class = value
;
1315 case lldpctl_k_dot3_power_type
:
1317 case LLDP_DOT3_POWER_8023AT_TYPE1
:
1318 case LLDP_DOT3_POWER_8023AT_TYPE2
:
1319 case LLDP_DOT3_POWER_8023AT_OFF
:
1320 port
->p_power
.powertype
= value
;
1324 case lldpctl_k_dot3_power_source
:
1325 if (value
< 0 || value
> 3)
1327 port
->p_power
.source
= value
;
1329 case lldpctl_k_dot3_power_priority
:
1331 case LLDP_DOT3_POWER_PRIO_UNKNOWN
:
1332 case LLDP_DOT3_POWER_PRIO_CRITICAL
:
1333 case LLDP_DOT3_POWER_PRIO_HIGH
:
1334 case LLDP_DOT3_POWER_PRIO_LOW
:
1335 port
->p_power
.priority
= value
;
1339 case lldpctl_k_dot3_power_allocated
:
1340 if (value
< 0) goto bad
;
1341 port
->p_power
.allocated
= value
/ 100;
1343 case lldpctl_k_dot3_power_requested
:
1344 if (value
< 0) goto bad
;
1345 port
->p_power
.requested
= value
/ 100;
1348 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1354 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
1358 static lldpctl_atom_t
*
1359 _lldpctl_atom_set_str_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
1363 case lldpctl_k_dot3_power_devicetype
:
1364 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
1365 map_reverse_lookup(port_dot3_power_devicetype_map
, value
));
1366 case lldpctl_k_dot3_power_pairs
:
1367 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
1368 map_reverse_lookup(port_dot3_power_pairs_map
, value
));
1369 case lldpctl_k_dot3_power_class
:
1370 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
1371 map_reverse_lookup(port_dot3_power_class_map
, value
));
1372 case lldpctl_k_dot3_power_priority
:
1373 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
1374 map_reverse_lookup(port_dot3_power_priority_map
, value
));
1376 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1383 static lldpctl_atom_iter_t
*
1384 _lldpctl_atom_iter_vlans_list(lldpctl_atom_t
*atom
)
1386 struct _lldpctl_atom_any_list_t
*vlist
=
1387 (struct _lldpctl_atom_any_list_t
*)atom
;
1388 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(&vlist
->parent
->port
->p_vlans
);
1391 static lldpctl_atom_iter_t
*
1392 _lldpctl_atom_next_vlans_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1394 struct lldpd_vlan
*vlan
= (struct lldpd_vlan
*)iter
;
1395 return (lldpctl_atom_iter_t
*)TAILQ_NEXT(vlan
, v_entries
);
1398 static lldpctl_atom_t
*
1399 _lldpctl_atom_value_vlans_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1401 struct _lldpctl_atom_any_list_t
*vlist
=
1402 (struct _lldpctl_atom_any_list_t
*)atom
;
1403 struct lldpd_vlan
*vlan
= (struct lldpd_vlan
*)iter
;
1404 return _lldpctl_new_atom(atom
->conn
, atom_vlan
, vlist
->parent
, vlan
);
1408 _lldpctl_atom_new_vlan(lldpctl_atom_t
*atom
, va_list ap
)
1410 struct _lldpctl_atom_vlan_t
*vlan
=
1411 (struct _lldpctl_atom_vlan_t
*)atom
;
1412 vlan
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1413 vlan
->vlan
= va_arg(ap
, struct lldpd_vlan
*);
1414 lldpctl_atom_inc_ref((lldpctl_atom_t
*)vlan
->parent
);
1419 _lldpctl_atom_free_vlan(lldpctl_atom_t
*atom
)
1421 struct _lldpctl_atom_vlan_t
*vlan
=
1422 (struct _lldpctl_atom_vlan_t
*)atom
;
1423 lldpctl_atom_dec_ref((lldpctl_atom_t
*)vlan
->parent
);
1427 _lldpctl_atom_get_str_vlan(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1429 struct _lldpctl_atom_vlan_t
*m
=
1430 (struct _lldpctl_atom_vlan_t
*)atom
;
1432 /* Local and remote port */
1434 case lldpctl_k_vlan_name
:
1435 return m
->vlan
->v_name
;
1437 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1443 _lldpctl_atom_get_int_vlan(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1445 struct _lldpctl_atom_vlan_t
*m
=
1446 (struct _lldpctl_atom_vlan_t
*)atom
;
1448 /* Local and remote port */
1450 case lldpctl_k_vlan_id
:
1451 return m
->vlan
->v_vid
;
1453 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1457 static lldpctl_atom_iter_t
*
1458 _lldpctl_atom_iter_ppvids_list(lldpctl_atom_t
*atom
)
1460 struct _lldpctl_atom_any_list_t
*vlist
=
1461 (struct _lldpctl_atom_any_list_t
*)atom
;
1462 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(&vlist
->parent
->port
->p_ppvids
);
1465 static lldpctl_atom_iter_t
*
1466 _lldpctl_atom_next_ppvids_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1468 struct lldpd_ppvid
*ppvid
= (struct lldpd_ppvid
*)iter
;
1469 return (lldpctl_atom_iter_t
*)TAILQ_NEXT(ppvid
, p_entries
);
1472 static lldpctl_atom_t
*
1473 _lldpctl_atom_value_ppvids_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1475 struct _lldpctl_atom_any_list_t
*vlist
=
1476 (struct _lldpctl_atom_any_list_t
*)atom
;
1477 struct lldpd_ppvid
*ppvid
= (struct lldpd_ppvid
*)iter
;
1478 return _lldpctl_new_atom(atom
->conn
, atom_ppvid
, vlist
->parent
, ppvid
);
1482 _lldpctl_atom_new_ppvid(lldpctl_atom_t
*atom
, va_list ap
)
1484 struct _lldpctl_atom_ppvid_t
*ppvid
=
1485 (struct _lldpctl_atom_ppvid_t
*)atom
;
1486 ppvid
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1487 ppvid
->ppvid
= va_arg(ap
, struct lldpd_ppvid
*);
1488 lldpctl_atom_inc_ref((lldpctl_atom_t
*)ppvid
->parent
);
1493 _lldpctl_atom_free_ppvid(lldpctl_atom_t
*atom
)
1495 struct _lldpctl_atom_ppvid_t
*ppvid
=
1496 (struct _lldpctl_atom_ppvid_t
*)atom
;
1497 lldpctl_atom_dec_ref((lldpctl_atom_t
*)ppvid
->parent
);
1501 _lldpctl_atom_get_int_ppvid(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1503 struct _lldpctl_atom_ppvid_t
*m
=
1504 (struct _lldpctl_atom_ppvid_t
*)atom
;
1506 /* Local and remote port */
1508 case lldpctl_k_ppvid_id
:
1509 return m
->ppvid
->p_ppvid
;
1510 case lldpctl_k_ppvid_status
:
1511 return m
->ppvid
->p_cap_status
;
1513 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1517 static lldpctl_atom_iter_t
*
1518 _lldpctl_atom_iter_pis_list(lldpctl_atom_t
*atom
)
1520 struct _lldpctl_atom_any_list_t
*vlist
=
1521 (struct _lldpctl_atom_any_list_t
*)atom
;
1522 return (lldpctl_atom_iter_t
*)TAILQ_FIRST(&vlist
->parent
->port
->p_pids
);
1525 static lldpctl_atom_iter_t
*
1526 _lldpctl_atom_next_pis_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1528 struct lldpd_pi
*pi
= (struct lldpd_pi
*)iter
;
1529 return (lldpctl_atom_iter_t
*)TAILQ_NEXT(pi
, p_entries
);
1532 static lldpctl_atom_t
*
1533 _lldpctl_atom_value_pis_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1535 struct _lldpctl_atom_any_list_t
*vlist
=
1536 (struct _lldpctl_atom_any_list_t
*)atom
;
1537 struct lldpd_pi
*pi
= (struct lldpd_pi
*)iter
;
1538 return _lldpctl_new_atom(atom
->conn
, atom_pi
, vlist
->parent
, pi
);
1542 _lldpctl_atom_new_pi(lldpctl_atom_t
*atom
, va_list ap
)
1544 struct _lldpctl_atom_pi_t
*pi
=
1545 (struct _lldpctl_atom_pi_t
*)atom
;
1546 pi
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1547 pi
->pi
= va_arg(ap
, struct lldpd_pi
*);
1548 lldpctl_atom_inc_ref((lldpctl_atom_t
*)pi
->parent
);
1553 _lldpctl_atom_free_pi(lldpctl_atom_t
*atom
)
1555 struct _lldpctl_atom_pi_t
*pi
=
1556 (struct _lldpctl_atom_pi_t
*)atom
;
1557 lldpctl_atom_dec_ref((lldpctl_atom_t
*)pi
->parent
);
1560 static const uint8_t*
1561 _lldpctl_atom_get_buf_pi(lldpctl_atom_t
*atom
, lldpctl_key_t key
, size_t *n
)
1563 struct _lldpctl_atom_pi_t
*m
=
1564 (struct _lldpctl_atom_pi_t
*)atom
;
1566 /* Local and remote port */
1568 case lldpctl_k_pi_id
:
1569 *n
= m
->pi
->p_pi_len
;
1570 return (const uint8_t*)m
->pi
->p_pi
;
1572 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1578 #ifdef ENABLE_LLDPMED
1579 static lldpctl_atom_iter_t
*
1580 _lldpctl_atom_iter_med_policies_list(lldpctl_atom_t
*atom
)
1583 struct _lldpctl_atom_any_list_t
*vlist
=
1584 (struct _lldpctl_atom_any_list_t
*)atom
;
1585 for (i
= 0; i
< LLDP_MED_APPTYPE_LAST
; i
++)
1586 vlist
->parent
->port
->p_med_policy
[i
].index
= i
;
1587 return (lldpctl_atom_iter_t
*)&vlist
->parent
->port
->p_med_policy
[0];
1590 static lldpctl_atom_iter_t
*
1591 _lldpctl_atom_next_med_policies_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1593 struct lldpd_med_policy
*policy
= (struct lldpd_med_policy
*)iter
;
1594 if (policy
->index
== LLDP_MED_APPTYPE_LAST
- 1) return NULL
;
1595 return (lldpctl_atom_iter_t
*)(++policy
);
1598 static lldpctl_atom_t
*
1599 _lldpctl_atom_value_med_policies_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1601 struct _lldpctl_atom_any_list_t
*vlist
=
1602 (struct _lldpctl_atom_any_list_t
*)atom
;
1603 struct lldpd_med_policy
*policy
= (struct lldpd_med_policy
*)iter
;
1604 return _lldpctl_new_atom(atom
->conn
, atom_med_policy
, vlist
->parent
, policy
);
1608 _lldpctl_atom_new_med_policy(lldpctl_atom_t
*atom
, va_list ap
)
1610 struct _lldpctl_atom_med_policy_t
*policy
=
1611 (struct _lldpctl_atom_med_policy_t
*)atom
;
1612 policy
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1613 policy
->policy
= va_arg(ap
, struct lldpd_med_policy
*);
1614 lldpctl_atom_inc_ref((lldpctl_atom_t
*)policy
->parent
);
1619 _lldpctl_atom_free_med_policy(lldpctl_atom_t
*atom
)
1621 struct _lldpctl_atom_med_policy_t
*policy
=
1622 (struct _lldpctl_atom_med_policy_t
*)atom
;
1623 lldpctl_atom_dec_ref((lldpctl_atom_t
*)policy
->parent
);
1627 _lldpctl_atom_get_int_med_policy(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1629 struct _lldpctl_atom_med_policy_t
*m
=
1630 (struct _lldpctl_atom_med_policy_t
*)atom
;
1632 /* Local and remote port */
1634 case lldpctl_k_med_policy_type
:
1635 return m
->policy
->type
;
1636 case lldpctl_k_med_policy_unknown
:
1637 return m
->policy
->unknown
;
1638 case lldpctl_k_med_policy_tagged
:
1639 return m
->policy
->tagged
;
1640 case lldpctl_k_med_policy_vid
:
1641 return m
->policy
->vid
;
1642 case lldpctl_k_med_policy_dscp
:
1643 return m
->policy
->dscp
;
1644 case lldpctl_k_med_policy_priority
:
1645 return m
->policy
->priority
;
1647 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1651 static lldpctl_atom_t
*
1652 _lldpctl_atom_set_int_med_policy(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
1655 struct _lldpctl_atom_med_policy_t
*m
=
1656 (struct _lldpctl_atom_med_policy_t
*)atom
;
1658 /* Only local port can be modified */
1659 if (m
->parent
->hardware
== NULL
) {
1660 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1665 case lldpctl_k_med_policy_type
:
1666 /* We let set any policy type, including one whose are not
1667 * compatible with the index. If a policy type is set, the index
1668 * will be ignored. If a policy type is 0, the index will be
1669 * used to know which policy to "erase". */
1670 if (value
< 0 || value
> LLDP_MED_APPTYPE_LAST
) goto bad
;
1671 m
->policy
->type
= value
;
1673 case lldpctl_k_med_policy_unknown
:
1674 if (value
!= 0 && value
!= 1) goto bad
;
1675 m
->policy
->unknown
= value
;
1677 case lldpctl_k_med_policy_tagged
:
1678 if (value
!= 0 && value
!= 1) goto bad
;
1679 m
->policy
->tagged
= value
;
1681 case lldpctl_k_med_policy_vid
:
1682 if (value
< 0 || value
> 4094) goto bad
;
1683 m
->policy
->vid
= value
;
1685 case lldpctl_k_med_policy_dscp
:
1686 if (value
< 0 || value
> 63) goto bad
;
1687 m
->policy
->dscp
= value
;
1689 case lldpctl_k_med_policy_priority
:
1690 if (value
< 0 || value
> 7) goto bad
;
1691 m
->policy
->priority
= value
;
1694 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1700 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
1705 _lldpctl_atom_get_str_med_policy(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1707 struct _lldpctl_atom_med_policy_t
*m
=
1708 (struct _lldpctl_atom_med_policy_t
*)atom
;
1710 /* Local and remote port */
1712 case lldpctl_k_med_policy_type
:
1713 return map_lookup(port_med_policy_map
, m
->policy
->type
);
1714 case lldpctl_k_med_policy_priority
:
1715 return map_lookup(port_med_policy_prio_map
, m
->policy
->priority
);
1717 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1722 static lldpctl_atom_t
*
1723 _lldpctl_atom_set_str_med_policy(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
1726 /* Local and remote port */
1728 case lldpctl_k_med_policy_type
:
1729 return _lldpctl_atom_set_int_med_policy(atom
, key
,
1730 map_reverse_lookup(port_med_policy_map
, value
));
1731 case lldpctl_k_med_policy_priority
:
1732 return _lldpctl_atom_set_int_med_policy(atom
, key
,
1733 map_reverse_lookup(port_med_policy_prio_map
, value
));
1735 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1740 static lldpctl_atom_iter_t
*
1741 _lldpctl_atom_iter_med_locations_list(lldpctl_atom_t
*atom
)
1744 struct _lldpctl_atom_any_list_t
*vlist
=
1745 (struct _lldpctl_atom_any_list_t
*)atom
;
1746 for (i
= 0; i
< LLDP_MED_LOCFORMAT_LAST
; i
++)
1747 vlist
->parent
->port
->p_med_location
[i
].index
= i
;
1748 return (lldpctl_atom_iter_t
*)&vlist
->parent
->port
->p_med_location
[0];
1751 static lldpctl_atom_iter_t
*
1752 _lldpctl_atom_next_med_locations_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1754 struct lldpd_med_loc
*location
= (struct lldpd_med_loc
*)iter
;
1755 if (location
->index
== LLDP_MED_LOCFORMAT_LAST
- 1) return NULL
;
1756 return (lldpctl_atom_iter_t
*)(++location
);
1759 static lldpctl_atom_t
*
1760 _lldpctl_atom_value_med_locations_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
1762 struct _lldpctl_atom_any_list_t
*vlist
=
1763 (struct _lldpctl_atom_any_list_t
*)atom
;
1764 struct lldpd_med_loc
*location
= (struct lldpd_med_loc
*)iter
;
1765 return _lldpctl_new_atom(atom
->conn
, atom_med_location
, vlist
->parent
, location
);
1769 _lldpctl_atom_new_med_location(lldpctl_atom_t
*atom
, va_list ap
)
1771 struct _lldpctl_atom_med_location_t
*location
=
1772 (struct _lldpctl_atom_med_location_t
*)atom
;
1773 location
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
1774 location
->location
= va_arg(ap
, struct lldpd_med_loc
*);
1775 lldpctl_atom_inc_ref((lldpctl_atom_t
*)location
->parent
);
1780 _lldpctl_atom_free_med_location(lldpctl_atom_t
*atom
)
1782 struct _lldpctl_atom_med_location_t
*location
=
1783 (struct _lldpctl_atom_med_location_t
*)atom
;
1784 lldpctl_atom_dec_ref((lldpctl_atom_t
*)location
->parent
);
1788 _lldpctl_atom_get_int_med_location(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1790 struct _lldpctl_atom_med_location_t
*m
=
1791 (struct _lldpctl_atom_med_location_t
*)atom
;
1793 /* Local and remote port */
1795 case lldpctl_k_med_location_format
:
1796 switch (m
->location
->format
) {
1797 case LLDP_MED_LOCFORMAT_COORD
:
1798 if (m
->location
->data_len
!= 16) break;
1799 return LLDP_MED_LOCFORMAT_COORD
;
1800 case LLDP_MED_LOCFORMAT_CIVIC
:
1801 if ((m
->location
->data_len
< 3) ||
1802 (m
->location
->data_len
- 1 !=
1803 m
->location
->data
[0])) break;
1804 return LLDP_MED_LOCFORMAT_CIVIC
;
1805 case LLDP_MED_LOCFORMAT_ELIN
:
1806 return LLDP_MED_LOCFORMAT_ELIN
;
1810 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1811 case lldpctl_k_med_location_geoid
:
1812 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
)
1813 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1814 return m
->location
->data
[15];
1815 case lldpctl_k_med_location_altitude_unit
:
1816 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
)
1817 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1818 return (m
->location
->data
[10] & 0xf0) >> 4;
1820 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1824 static lldpctl_atom_t
*
1825 _lldpctl_atom_set_int_med_location(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
1828 struct _lldpctl_atom_med_location_t
*mloc
=
1829 (struct _lldpctl_atom_med_location_t
*)atom
;
1831 /* Only local port can be modified */
1832 if (mloc
->parent
->hardware
== NULL
) {
1833 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1838 case lldpctl_k_med_location_format
:
1840 case 0: /* Disabling */
1841 case LLDP_MED_LOCFORMAT_COORD
:
1842 mloc
->location
->format
= value
;
1843 if (mloc
->location
->data
) free(mloc
->location
->data
);
1844 mloc
->location
->data
= calloc(1, 16);
1845 if (mloc
->location
->data
== NULL
) {
1846 mloc
->location
->data_len
= 0;
1847 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
1850 mloc
->location
->data_len
= 16;
1852 case LLDP_MED_LOCFORMAT_CIVIC
:
1853 mloc
->location
->format
= value
;
1854 if (mloc
->location
->data
) free(mloc
->location
->data
);
1855 mloc
->location
->data
= calloc(1, 4);
1856 if (mloc
->location
->data
== NULL
) {
1857 mloc
->location
->data_len
= 0;
1858 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
1861 mloc
->location
->data_len
= 4;
1862 mloc
->location
->data
[0] = 3;
1863 mloc
->location
->data
[1] = 2; /* Client */
1864 mloc
->location
->data
[2] = 'U';
1865 mloc
->location
->data
[3] = 'S';
1867 case LLDP_MED_LOCFORMAT_ELIN
:
1868 mloc
->location
->format
= value
;
1869 if (mloc
->location
->data
) free(mloc
->location
->data
);
1870 mloc
->location
->data
= NULL
;
1871 mloc
->location
->data_len
= 0;
1875 case lldpctl_k_med_location_geoid
:
1876 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) goto bad
;
1877 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
!= 16) goto bad
;
1880 case LLDP_MED_LOCATION_GEOID_WGS84
:
1881 case LLDP_MED_LOCATION_GEOID_NAD83
:
1882 case LLDP_MED_LOCATION_GEOID_NAD83_MLLW
:
1883 mloc
->location
->data
[15] = value
;
1887 case lldpctl_k_med_location_altitude_unit
:
1888 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) goto bad
;
1889 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
!= 16) goto bad
;
1892 case LLDP_MED_LOCATION_ALTITUDE_UNIT_METER
:
1893 case LLDP_MED_LOCATION_ALTITUDE_UNIT_FLOOR
:
1894 mloc
->location
->data
[10] &= 0x0f;
1895 mloc
->location
->data
[10] |= value
<< 4;
1900 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1906 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
1912 read_fixed_precision(lldpctl_atom_t
*atom
,
1913 char *buffer
, unsigned shift
,
1914 unsigned intbits
, unsigned fltbits
, const char *suffix
)
1916 struct fp_number fp
= fp_buftofp((unsigned char*)buffer
, intbits
, fltbits
, shift
);
1917 char *result
= fp_fptostr(fp
, suffix
);
1918 if (result
== NULL
) {
1919 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
1923 char *stored
= _lldpctl_alloc_in_atom(atom
, strlen(result
) + 1);
1924 if (stored
== NULL
) {
1928 strlcpy(stored
, result
, strlen(result
) + 1);
1933 _lldpctl_atom_get_str_med_location(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
1935 struct _lldpctl_atom_med_location_t
*m
=
1936 (struct _lldpctl_atom_med_location_t
*)atom
;
1939 /* Local and remote port */
1941 case lldpctl_k_med_location_format
:
1942 return map_lookup(port_med_location_map
, m
->location
->format
);
1943 case lldpctl_k_med_location_geoid
:
1944 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) break;
1945 return map_lookup(port_med_geoid_map
,
1946 m
->location
->data
[15]);
1947 case lldpctl_k_med_location_latitude
:
1948 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) break;
1949 return read_fixed_precision(atom
, m
->location
->data
,
1951 case lldpctl_k_med_location_longitude
:
1952 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) break;
1953 return read_fixed_precision(atom
, m
->location
->data
,
1955 case lldpctl_k_med_location_altitude
:
1956 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) break;
1957 return read_fixed_precision(atom
, m
->location
->data
,
1959 case lldpctl_k_med_location_altitude_unit
:
1960 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) break;
1961 switch (m
->location
->data
[10] & 0xf0) {
1962 case (LLDP_MED_LOCATION_ALTITUDE_UNIT_METER
<< 4):
1964 case (LLDP_MED_LOCATION_ALTITUDE_UNIT_FLOOR
<< 4):
1967 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1969 case lldpctl_k_med_location_country
:
1970 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_CIVIC
) break;
1971 value
= _lldpctl_alloc_in_atom(atom
, 3);
1972 if (!value
) return NULL
;
1973 memcpy(value
, m
->location
->data
+ 2, 2);
1975 case lldpctl_k_med_location_elin
:
1976 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_ELIN
) break;
1977 value
= _lldpctl_alloc_in_atom(atom
, m
->location
->data_len
+ 1);
1978 if (!value
) return NULL
;
1979 memcpy(value
, m
->location
->data
, m
->location
->data_len
);
1982 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1985 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
1989 static lldpctl_atom_t
*
1990 _lldpctl_atom_set_str_med_location(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
1993 struct _lldpctl_atom_med_location_t
*mloc
=
1994 (struct _lldpctl_atom_med_location_t
*)atom
;
1995 struct fp_number fp
;
1998 /* Only local port can be modified */
1999 if (mloc
->parent
->hardware
== NULL
) {
2000 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2005 case lldpctl_k_med_location_latitude
:
2006 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) goto bad
;
2007 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
!= 16) goto bad
;
2008 fp
= fp_strtofp(value
, &end
, 9, 25);
2010 if (end
&& *end
!= '\0') {
2011 if (*(end
+1) != '\0') goto bad
;
2012 if (*end
== 'S') fp
= fp_negate(fp
);
2013 else if (*end
!= 'N') goto bad
;
2015 fp_fptobuf(fp
, (unsigned char*)mloc
->location
->data
, 0);
2017 case lldpctl_k_med_location_longitude
:
2018 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) goto bad
;
2019 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
!= 16) goto bad
;
2020 fp
= fp_strtofp(value
, &end
, 9, 25);
2022 if (end
&& *end
!= '\0') {
2023 if (*(end
+1) != '\0') goto bad
;
2024 if (*end
== 'W') fp
= fp_negate(fp
);
2025 else if (*end
!= 'E') goto bad
;
2027 fp_fptobuf(fp
, (unsigned char*)mloc
->location
->data
, 40);
2029 case lldpctl_k_med_location_altitude
:
2030 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) goto bad
;
2031 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
!= 16) goto bad
;
2032 fp
= fp_strtofp(value
, &end
, 22, 8);
2033 if (!end
|| *end
!= '\0') goto bad
;
2034 fp_fptobuf(fp
, (unsigned char*)mloc
->location
->data
, 84);
2036 case lldpctl_k_med_location_altitude_unit
:
2037 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_COORD
) goto bad
;
2038 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
!= 16) goto bad
;
2039 if (!strcmp(value
, "m"))
2040 return _lldpctl_atom_set_int_med_location(atom
, key
,
2041 LLDP_MED_LOCATION_ALTITUDE_UNIT_METER
);
2042 if (!strcmp(value
, "f") ||
2043 (!strcmp(value
, "floor")))
2044 return _lldpctl_atom_set_int_med_location(atom
, key
,
2045 LLDP_MED_LOCATION_ALTITUDE_UNIT_FLOOR
);
2047 case lldpctl_k_med_location_geoid
:
2048 return _lldpctl_atom_set_int_med_location(atom
, key
,
2049 map_reverse_lookup(port_med_geoid_map
, value
));
2050 case lldpctl_k_med_location_country
:
2051 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_CIVIC
) goto bad
;
2052 if (mloc
->location
->data
== NULL
|| mloc
->location
->data_len
< 3) goto bad
;
2053 if (strlen(value
) != 2) goto bad
;
2054 memcpy(mloc
->location
->data
+ 2, value
, 2);
2056 case lldpctl_k_med_location_elin
:
2057 if (mloc
->location
->format
!= LLDP_MED_LOCFORMAT_ELIN
) goto bad
;
2058 if (mloc
->location
->data
) free(mloc
->location
->data
);
2059 mloc
->location
->data
= calloc(1, strlen(value
));
2060 if (mloc
->location
->data
== NULL
) {
2061 mloc
->location
->data_len
= 0;
2062 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
2065 mloc
->location
->data_len
= strlen(value
);
2066 memcpy(mloc
->location
->data
, value
,
2067 mloc
->location
->data_len
);
2070 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2076 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
2081 static lldpctl_atom_t
*
2082 _lldpctl_atom_get_atom_med_location(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
2084 struct _lldpctl_atom_med_location_t
*m
=
2085 (struct _lldpctl_atom_med_location_t
*)atom
;
2087 /* Local and remote port */
2089 case lldpctl_k_med_location_ca_elements
:
2090 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_CIVIC
) {
2091 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2094 return _lldpctl_new_atom(atom
->conn
, atom_med_caelements_list
, m
);
2096 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2101 static lldpctl_atom_t
*
2102 _lldpctl_atom_set_atom_med_location(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
2103 lldpctl_atom_t
*value
)
2105 struct _lldpctl_atom_med_location_t
*m
=
2106 (struct _lldpctl_atom_med_location_t
*)atom
;
2107 struct _lldpctl_atom_med_caelement_t
*el
;
2110 /* Only local port can be modified */
2111 if (m
->parent
->hardware
== NULL
) {
2112 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2117 case lldpctl_k_med_location_ca_elements
:
2118 if (value
->type
!= atom_med_caelement
) {
2119 SET_ERROR(atom
->conn
, LLDPCTL_ERR_INCORRECT_ATOM_TYPE
);
2122 if (m
->location
->format
!= LLDP_MED_LOCFORMAT_CIVIC
) goto bad
;
2123 if (m
->location
->data
== NULL
|| m
->location
->data_len
< 3) goto bad
;
2125 /* We append this element. */
2126 el
= (struct _lldpctl_atom_med_caelement_t
*)value
;
2127 new = malloc(m
->location
->data_len
+ 2 + el
->len
);
2129 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
2132 memcpy(new, m
->location
->data
, m
->location
->data_len
);
2133 new[m
->location
->data_len
] = el
->type
;
2134 new[m
->location
->data_len
+ 1] = el
->len
;
2135 memcpy(new + m
->location
->data_len
+ 2, el
->value
, el
->len
);
2136 new[0] += 2 + el
->len
;
2137 free(m
->location
->data
);
2138 m
->location
->data
= (char*)new;
2139 m
->location
->data_len
+= 2 + el
->len
;
2142 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2146 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
2155 static lldpctl_atom_iter_t
*
2156 _lldpctl_atom_iter_med_caelements_list(lldpctl_atom_t
*atom
)
2158 struct _lldpctl_atom_med_caelements_list_t
*plist
=
2159 (struct _lldpctl_atom_med_caelements_list_t
*)atom
;
2160 struct ca_iter
*iter
= _lldpctl_alloc_in_atom(atom
, sizeof(struct ca_iter
));
2161 if (!iter
) return NULL
;
2162 iter
->data
= (uint8_t*)plist
->parent
->location
->data
+ 4;
2163 iter
->data_len
= plist
->parent
->location
->data_len
- 4;
2164 return (lldpctl_atom_iter_t
*)iter
;
2167 static lldpctl_atom_iter_t
*
2168 _lldpctl_atom_next_med_caelements_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
2170 struct ca_iter
*cai
= (struct ca_iter
*)iter
;
2172 if (cai
->data_len
< 2) return NULL
;
2173 len
= *((uint8_t *)cai
->data
+ 1);
2174 if (cai
->data_len
< 2 + len
) return NULL
;
2175 cai
->data
+= 2 + len
;
2176 cai
->data_len
-= 2 + len
;
2177 return (lldpctl_atom_iter_t
*)cai
;
2180 static lldpctl_atom_t
*
2181 _lldpctl_atom_value_med_caelements_list(lldpctl_atom_t
*atom
, lldpctl_atom_iter_t
*iter
)
2183 struct _lldpctl_atom_med_caelements_list_t
*plist
=
2184 (struct _lldpctl_atom_med_caelements_list_t
*)atom
;
2185 struct ca_iter
*cai
= (struct ca_iter
*)iter
;
2187 if (cai
->data_len
< 2) return NULL
;
2188 len
= *((uint8_t *)cai
->data
+ 1);
2189 if (cai
->data_len
< 2 + len
) return NULL
;
2190 return _lldpctl_new_atom(atom
->conn
, atom_med_caelement
, plist
->parent
,
2191 (int)*cai
->data
, cai
->data
+ 2, len
);
2194 static lldpctl_atom_t
*
2195 _lldpctl_atom_create_med_caelements_list(lldpctl_atom_t
*atom
)
2197 struct _lldpctl_atom_med_caelements_list_t
*plist
=
2198 (struct _lldpctl_atom_med_caelements_list_t
*)atom
;
2199 return _lldpctl_new_atom(atom
->conn
, atom_med_caelement
, plist
->parent
,
2204 _lldpctl_atom_new_med_caelement(lldpctl_atom_t
*atom
, va_list ap
)
2206 struct _lldpctl_atom_med_caelement_t
*el
=
2207 (struct _lldpctl_atom_med_caelement_t
*)atom
;
2208 el
->parent
= va_arg(ap
, struct _lldpctl_atom_med_location_t
*);
2209 el
->type
= va_arg(ap
, int);
2210 el
->value
= va_arg(ap
, uint8_t*);
2211 el
->len
= va_arg(ap
, size_t);
2212 lldpctl_atom_inc_ref((lldpctl_atom_t
*)el
->parent
);
2217 _lldpctl_atom_free_med_caelement(lldpctl_atom_t
*atom
)
2219 struct _lldpctl_atom_med_caelement_t
*el
=
2220 (struct _lldpctl_atom_med_caelement_t
*)atom
;
2221 lldpctl_atom_dec_ref((lldpctl_atom_t
*)el
->parent
);
2225 _lldpctl_atom_get_int_med_caelement(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
2227 struct _lldpctl_atom_med_caelement_t
*m
=
2228 (struct _lldpctl_atom_med_caelement_t
*)atom
;
2231 case lldpctl_k_med_civicaddress_type
:
2234 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2238 static lldpctl_atom_t
*
2239 _lldpctl_atom_set_int_med_caelement(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
2242 struct _lldpctl_atom_med_caelement_t
*el
=
2243 (struct _lldpctl_atom_med_caelement_t
*)atom
;
2245 /* Only local port can be modified */
2246 if (el
->parent
->parent
->hardware
== NULL
) {
2247 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2252 case lldpctl_k_med_civicaddress_type
:
2253 if (value
<= 0 || value
> 128) goto bad
;
2257 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2263 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
2268 _lldpctl_atom_get_str_med_caelement(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
2271 struct _lldpctl_atom_med_caelement_t
*m
=
2272 (struct _lldpctl_atom_med_caelement_t
*)atom
;
2274 /* Local and remote port */
2276 case lldpctl_k_med_civicaddress_type
:
2277 return map_lookup(civic_address_type_map
, m
->type
);
2278 case lldpctl_k_med_civicaddress_value
:
2279 value
= _lldpctl_alloc_in_atom(atom
, m
->len
+ 1);
2280 if (!value
) return NULL
;
2281 memcpy(value
, m
->value
, m
->len
);
2284 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2289 static lldpctl_atom_t
*
2290 _lldpctl_atom_set_str_med_caelement(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
2293 struct _lldpctl_atom_med_caelement_t
*el
=
2294 (struct _lldpctl_atom_med_caelement_t
*)atom
;
2296 /* Only local port can be modified */
2297 if (el
->parent
->parent
->hardware
== NULL
) {
2298 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2303 case lldpctl_k_med_civicaddress_value
:
2304 if (strlen(value
) > 250) goto bad
;
2305 el
->value
= _lldpctl_alloc_in_atom(atom
, strlen(value
) + 1);
2306 if (el
->value
== NULL
) return NULL
;
2307 strlcpy((char*)el
->value
, value
, strlen(value
) + 1);
2308 el
->len
= strlen(value
);
2310 case lldpctl_k_med_civicaddress_type
:
2311 return _lldpctl_atom_set_int_med_caelement(atom
, key
,
2312 map_reverse_lookup(civic_address_type_map
, value
));
2314 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2320 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
2325 _lldpctl_atom_new_med_power(lldpctl_atom_t
*atom
, va_list ap
)
2327 struct _lldpctl_atom_med_power_t
*mpow
=
2328 (struct _lldpctl_atom_med_power_t
*)atom
;
2329 mpow
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
2330 lldpctl_atom_inc_ref((lldpctl_atom_t
*)mpow
->parent
);
2335 _lldpctl_atom_free_med_power(lldpctl_atom_t
*atom
)
2337 struct _lldpctl_atom_med_power_t
*mpow
=
2338 (struct _lldpctl_atom_med_power_t
*)atom
;
2339 lldpctl_atom_dec_ref((lldpctl_atom_t
*)mpow
->parent
);
2343 _lldpctl_atom_get_str_med_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
2345 struct _lldpctl_atom_med_power_t
*mpow
=
2346 (struct _lldpctl_atom_med_power_t
*)atom
;
2347 struct lldpd_port
*port
= mpow
->parent
->port
;
2349 /* Local and remote port */
2351 case lldpctl_k_med_power_type
:
2352 return map_lookup(port_med_pow_devicetype_map
,
2353 port
->p_med_power
.devicetype
);
2354 case lldpctl_k_med_power_source
:
2355 return map_lookup(port_med_pow_source_map
,
2356 port
->p_med_power
.source
);
2357 case lldpctl_k_med_power_priority
:
2358 return map_lookup(port_med_pow_priority_map
,
2359 port
->p_med_power
.priority
);
2361 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2367 _lldpctl_atom_get_int_med_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
2369 struct _lldpctl_atom_med_power_t
*dpow
=
2370 (struct _lldpctl_atom_med_power_t
*)atom
;
2371 struct lldpd_port
*port
= dpow
->parent
->port
;
2373 /* Local and remote port */
2375 case lldpctl_k_med_power_type
:
2376 return port
->p_med_power
.devicetype
;
2377 case lldpctl_k_med_power_source
:
2378 return port
->p_med_power
.source
;
2379 case lldpctl_k_med_power_priority
:
2380 return port
->p_med_power
.priority
;
2381 case lldpctl_k_med_power_val
:
2382 return port
->p_med_power
.val
* 100;
2384 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2388 static lldpctl_atom_t
*
2389 _lldpctl_atom_set_int_med_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
2392 struct _lldpctl_atom_med_power_t
*dpow
=
2393 (struct _lldpctl_atom_med_power_t
*)atom
;
2394 struct lldpd_port
*port
= dpow
->parent
->port
;
2396 /* Only local port can be modified */
2397 if (dpow
->parent
->hardware
== NULL
) {
2398 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2403 case lldpctl_k_med_power_type
:
2406 case LLDP_MED_POW_TYPE_PSE
:
2407 case LLDP_MED_POW_TYPE_PD
:
2408 port
->p_med_power
.devicetype
= value
;
2412 case lldpctl_k_med_power_source
:
2414 case LLDP_MED_POW_SOURCE_PRIMARY
:
2415 case LLDP_MED_POW_SOURCE_BACKUP
:
2416 if (port
->p_med_power
.devicetype
!= LLDP_MED_POW_TYPE_PSE
)
2418 port
->p_med_power
.source
= value
;
2420 case LLDP_MED_POW_SOURCE_PSE
:
2421 case LLDP_MED_POW_SOURCE_LOCAL
:
2422 case LLDP_MED_POW_SOURCE_BOTH
:
2423 if (port
->p_med_power
.devicetype
!= LLDP_MED_POW_TYPE_PD
)
2425 port
->p_med_power
.source
= value
;
2427 case LLDP_MED_POW_SOURCE_UNKNOWN
:
2428 port
->p_med_power
.source
= value
;
2432 case lldpctl_k_med_power_priority
:
2433 if (value
< 0 || value
> 3) goto bad
;
2434 port
->p_med_power
.priority
= value
;
2436 case lldpctl_k_med_power_val
:
2437 if (value
< 0) goto bad
;
2438 port
->p_med_power
.val
= value
/ 100;
2441 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2447 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
2451 static lldpctl_atom_t
*
2452 _lldpctl_atom_set_str_med_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
2456 case lldpctl_k_med_power_type
:
2457 return _lldpctl_atom_set_int_med_power(atom
, key
,
2458 map_reverse_lookup(port_med_pow_devicetype_map
, value
));
2459 case lldpctl_k_med_power_source
:
2460 return _lldpctl_atom_set_int_med_power(atom
, key
,
2461 map_reverse_lookup(port_med_pow_source_map2
, value
));
2462 case lldpctl_k_med_power_priority
:
2463 return _lldpctl_atom_set_int_med_power(atom
, key
,
2464 map_reverse_lookup(port_med_pow_priority_map
, value
));
2466 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
2472 struct atom_builder
{
2473 atom_t type
; /* Atom type */
2474 size_t size
; /* Size of structure to allocate */
2475 int (*init
)(lldpctl_atom_t
*, va_list); /* Optional additional init steps */
2476 void (*free
)(lldpctl_atom_t
*); /* Optional deallocation steps */
2478 lldpctl_atom_iter_t
* (*iter
)(lldpctl_atom_t
*); /* Optional, return an iterator for this object */
2479 lldpctl_atom_iter_t
* (*next
)(lldpctl_atom_t
*, lldpctl_atom_iter_t
*); /* Return the next object for the provided iterator */
2480 lldpctl_atom_t
* (*value
)(lldpctl_atom_t
*, lldpctl_atom_iter_t
*); /* Return the current object for the provided iterator */
2482 lldpctl_atom_t
* (*get
)(lldpctl_atom_t
*, lldpctl_key_t
);
2483 const char* (*get_str
)(lldpctl_atom_t
*, lldpctl_key_t
);
2484 const u_int8_t
* (*get_buffer
)(lldpctl_atom_t
*, lldpctl_key_t
, size_t *);
2485 long int (*get_int
)(lldpctl_atom_t
*, lldpctl_key_t
);
2487 lldpctl_atom_t
* (*set
)(lldpctl_atom_t
*, lldpctl_key_t
, lldpctl_atom_t
*);
2488 lldpctl_atom_t
* (*set_str
)(lldpctl_atom_t
*, lldpctl_key_t
, const char *);
2489 lldpctl_atom_t
* (*set_buffer
)(lldpctl_atom_t
*, lldpctl_key_t
, const u_int8_t
*, size_t);
2490 lldpctl_atom_t
* (*set_int
)(lldpctl_atom_t
*, lldpctl_key_t
, long int);
2491 lldpctl_atom_t
* (*create
)(lldpctl_atom_t
*);
2494 struct atom_builder builders
[] = {
2495 { atom_config
, sizeof(struct _lldpctl_atom_config_t
),
2496 .init
= _lldpctl_atom_new_config
,
2497 .free
= _lldpctl_atom_free_config
,
2498 .get_str
= _lldpctl_atom_get_str_config
,
2499 .set_str
= _lldpctl_atom_set_str_config
,
2500 .get_int
= _lldpctl_atom_get_int_config
,
2501 .set_int
= _lldpctl_atom_set_int_config
},
2502 { atom_interfaces_list
, sizeof(struct _lldpctl_atom_interfaces_list_t
),
2503 .init
= _lldpctl_atom_new_interfaces_list
,
2504 .free
= _lldpctl_atom_free_interfaces_list
,
2505 .iter
= _lldpctl_atom_iter_interfaces_list
,
2506 .next
= _lldpctl_atom_next_interfaces_list
,
2507 .value
= _lldpctl_atom_value_interfaces_list
},
2508 { atom_interface
, sizeof(struct _lldpctl_atom_interface_t
),
2509 .init
= _lldpctl_atom_new_interface
,
2510 .free
= _lldpctl_atom_free_interface
,
2511 .get_str
= _lldpctl_atom_get_str_interface
},
2512 { atom_ports_list
, sizeof(struct _lldpctl_atom_any_list_t
),
2513 .init
= _lldpctl_atom_new_any_list
,
2514 .free
= _lldpctl_atom_free_any_list
,
2515 .iter
= _lldpctl_atom_iter_ports_list
,
2516 .next
= _lldpctl_atom_next_ports_list
,
2517 .value
= _lldpctl_atom_value_ports_list
},
2518 { atom_port
, sizeof(struct _lldpctl_atom_port_t
),
2519 .init
= _lldpctl_atom_new_port
,
2520 .free
= _lldpctl_atom_free_port
,
2521 .get
= _lldpctl_atom_get_atom_port
,
2522 .set
= _lldpctl_atom_set_atom_port
,
2523 .get_str
= _lldpctl_atom_get_str_port
,
2524 .get_int
= _lldpctl_atom_get_int_port
,
2525 .get_buffer
= _lldpctl_atom_get_buf_port
},
2526 { atom_mgmts_list
, sizeof(struct _lldpctl_atom_mgmts_list_t
),
2527 .init
= _lldpctl_atom_new_mgmts_list
,
2528 .free
= _lldpctl_atom_free_mgmts_list
,
2529 .iter
= _lldpctl_atom_iter_mgmts_list
,
2530 .next
= _lldpctl_atom_next_mgmts_list
,
2531 .value
= _lldpctl_atom_value_mgmts_list
},
2532 { atom_mgmt
, sizeof(struct _lldpctl_atom_mgmt_t
),
2533 .init
= _lldpctl_atom_new_mgmt
,
2534 .free
= _lldpctl_atom_free_mgmt
,
2535 .get_str
= _lldpctl_atom_get_str_mgmt
},
2537 { atom_dot3_power
, sizeof(struct _lldpctl_atom_dot3_power_t
),
2538 .init
= _lldpctl_atom_new_dot3_power
,
2539 .free
= _lldpctl_atom_free_dot3_power
,
2540 .get_int
= _lldpctl_atom_get_int_dot3_power
,
2541 .set_int
= _lldpctl_atom_set_int_dot3_power
,
2542 .get_str
= _lldpctl_atom_get_str_dot3_power
,
2543 .set_str
= _lldpctl_atom_set_str_dot3_power
},
2546 { atom_vlans_list
, sizeof(struct _lldpctl_atom_any_list_t
),
2547 .init
= _lldpctl_atom_new_any_list
,
2548 .free
= _lldpctl_atom_free_any_list
,
2549 .iter
= _lldpctl_atom_iter_vlans_list
,
2550 .next
= _lldpctl_atom_next_vlans_list
,
2551 .value
= _lldpctl_atom_value_vlans_list
},
2552 { atom_vlan
, sizeof(struct _lldpctl_atom_vlan_t
),
2553 .init
= _lldpctl_atom_new_vlan
,
2554 .free
= _lldpctl_atom_free_vlan
,
2555 .get_str
= _lldpctl_atom_get_str_vlan
,
2556 .get_int
= _lldpctl_atom_get_int_vlan
},
2557 { atom_ppvids_list
, sizeof(struct _lldpctl_atom_any_list_t
),
2558 .init
= _lldpctl_atom_new_any_list
,
2559 .free
= _lldpctl_atom_free_any_list
,
2560 .iter
= _lldpctl_atom_iter_ppvids_list
,
2561 .next
= _lldpctl_atom_next_ppvids_list
,
2562 .value
= _lldpctl_atom_value_ppvids_list
},
2563 { atom_ppvid
, sizeof(struct _lldpctl_atom_ppvid_t
),
2564 .init
= _lldpctl_atom_new_ppvid
,
2565 .free
= _lldpctl_atom_free_ppvid
,
2566 .get_int
= _lldpctl_atom_get_int_ppvid
},
2567 { atom_pis_list
, sizeof(struct _lldpctl_atom_any_list_t
),
2568 .init
= _lldpctl_atom_new_any_list
,
2569 .free
= _lldpctl_atom_free_any_list
,
2570 .iter
= _lldpctl_atom_iter_pis_list
,
2571 .next
= _lldpctl_atom_next_pis_list
,
2572 .value
= _lldpctl_atom_value_pis_list
},
2573 { atom_pi
, sizeof(struct _lldpctl_atom_pi_t
),
2574 .init
= _lldpctl_atom_new_pi
,
2575 .free
= _lldpctl_atom_free_pi
,
2576 .get_buffer
= _lldpctl_atom_get_buf_pi
},
2578 #ifdef ENABLE_LLDPMED
2579 { atom_med_policies_list
, sizeof(struct _lldpctl_atom_any_list_t
),
2580 .init
= _lldpctl_atom_new_any_list
,
2581 .free
= _lldpctl_atom_free_any_list
,
2582 .iter
= _lldpctl_atom_iter_med_policies_list
,
2583 .next
= _lldpctl_atom_next_med_policies_list
,
2584 .value
= _lldpctl_atom_value_med_policies_list
},
2585 { atom_med_policy
, sizeof(struct _lldpctl_atom_med_policy_t
),
2586 .init
= _lldpctl_atom_new_med_policy
,
2587 .free
= _lldpctl_atom_free_med_policy
,
2588 .get_int
= _lldpctl_atom_get_int_med_policy
,
2589 .set_int
= _lldpctl_atom_set_int_med_policy
,
2590 .get_str
= _lldpctl_atom_get_str_med_policy
,
2591 .set_str
= _lldpctl_atom_set_str_med_policy
},
2592 { atom_med_locations_list
, sizeof(struct _lldpctl_atom_any_list_t
),
2593 .init
= _lldpctl_atom_new_any_list
,
2594 .free
= _lldpctl_atom_free_any_list
,
2595 .iter
= _lldpctl_atom_iter_med_locations_list
,
2596 .next
= _lldpctl_atom_next_med_locations_list
,
2597 .value
= _lldpctl_atom_value_med_locations_list
},
2598 { atom_med_location
, sizeof(struct _lldpctl_atom_med_location_t
),
2599 .init
= _lldpctl_atom_new_med_location
,
2600 .free
= _lldpctl_atom_free_med_location
,
2601 .get
= _lldpctl_atom_get_atom_med_location
,
2602 .set
= _lldpctl_atom_set_atom_med_location
,
2603 .get_int
= _lldpctl_atom_get_int_med_location
,
2604 .set_int
= _lldpctl_atom_set_int_med_location
,
2605 .get_str
= _lldpctl_atom_get_str_med_location
,
2606 .set_str
= _lldpctl_atom_set_str_med_location
},
2607 { atom_med_caelements_list
, sizeof(struct _lldpctl_atom_med_caelements_list_t
),
2608 .init
= _lldpctl_atom_new_any_list
,
2609 .free
= _lldpctl_atom_free_any_list
,
2610 .iter
= _lldpctl_atom_iter_med_caelements_list
,
2611 .next
= _lldpctl_atom_next_med_caelements_list
,
2612 .value
= _lldpctl_atom_value_med_caelements_list
,
2613 .create
= _lldpctl_atom_create_med_caelements_list
},
2614 { atom_med_caelement
, sizeof(struct _lldpctl_atom_med_caelement_t
),
2615 .init
= _lldpctl_atom_new_med_caelement
,
2616 .free
= _lldpctl_atom_free_med_caelement
,
2617 .get_int
= _lldpctl_atom_get_int_med_caelement
,
2618 .set_int
= _lldpctl_atom_set_int_med_caelement
,
2619 .get_str
= _lldpctl_atom_get_str_med_caelement
,
2620 .set_str
= _lldpctl_atom_set_str_med_caelement
},
2621 { atom_med_power
, sizeof(struct _lldpctl_atom_med_power_t
),
2622 .init
= _lldpctl_atom_new_med_power
,
2623 .free
= _lldpctl_atom_free_med_power
,
2624 .get_int
= _lldpctl_atom_get_int_med_power
,
2625 .set_int
= _lldpctl_atom_set_int_med_power
,
2626 .get_str
= _lldpctl_atom_get_str_med_power
,
2627 .set_str
= _lldpctl_atom_set_str_med_power
},
2629 { 0, 0, .init
= NULL
, .free
= NULL
}
2633 _lldpctl_new_atom(lldpctl_conn_t
*conn
, atom_t type
, ...)
2635 struct atom_builder
*builder
;
2636 struct lldpctl_atom_t
*atom
;
2638 for (builder
= builders
; builder
->size
> 0; builder
++) {
2639 if (builder
->type
!= type
) continue;
2640 atom
= calloc(1, builder
->size
);
2642 SET_ERROR(conn
, LLDPCTL_ERR_NOMEM
);
2648 TAILQ_INIT(&atom
->buffers
);
2649 atom
->free
= builder
->free
;
2651 atom
->iter
= builder
->iter
;
2652 atom
->next
= builder
->next
;
2653 atom
->value
= builder
->value
;
2655 atom
->get
= builder
->get
;
2656 atom
->get_str
= builder
->get_str
;
2657 atom
->get_buffer
= builder
->get_buffer
;
2658 atom
->get_int
= builder
->get_int
;
2660 atom
->set
= builder
->set
;
2661 atom
->set_str
= builder
->set_str
;
2662 atom
->set_buffer
= builder
->set_buffer
;
2663 atom
->set_int
= builder
->set_int
;
2664 atom
->create
= builder
->create
;
2667 if (builder
->init
&& builder
->init(atom
, ap
) == 0) {
2670 /* Error to be set in init() */
2676 log_warnx("rpc", "unknown atom type: %d", type
);
2677 SET_ERROR(conn
, LLDPCTL_ERR_FATAL
);
2682 * Allocate a buffer inside an atom.
2684 * It will be freed automatically when the atom is released. This buffer cannot
2685 * be reallocated and should not be freed!
2687 * @param atom Atom which will be used as a container.
2688 * @param size Size of the allocated area.
2689 * @return Pointer to the buffer or @c NULL if allocation fails.
2692 _lldpctl_alloc_in_atom(lldpctl_atom_t
*atom
, size_t size
)
2694 struct atom_buffer
*buffer
;
2696 if ((buffer
= calloc(1, size
+ sizeof(struct atom_buffer
))) == NULL
) {
2697 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOMEM
);
2700 TAILQ_INSERT_TAIL(&atom
->buffers
, buffer
, next
);
2701 return &buffer
->data
[0];
2705 * Allocate a buffer inside an atom and dump another buffer in it.
2707 * The dump is done in hexadecimal with the provided separator.
2709 * @param atom Atom which will be used as a container.
2710 * @param input Buffer we want to dump.
2711 * @param size Size of the buffer
2712 * @param sep Separator to use.
2713 * @param max Maximum number of bytes to dump. Can be 0 if no maximum.
2714 * @return A string representing the dump of the buffer or @c NULL if error.
2717 _lldpctl_dump_in_atom(lldpctl_atom_t
*atom
,
2718 const uint8_t *input
, size_t size
,
2719 char sep
, size_t max
)
2721 static const char truncation
[] = "[...]";
2723 char *buffer
= NULL
;
2725 if (max
> 0 && size
> max
)
2726 len
= max
* 3 + sizeof(truncation
) + 1;
2730 if ((buffer
= _lldpctl_alloc_in_atom(atom
, len
)) == NULL
)
2733 for (i
= 0; (i
< size
) && (max
== 0 || i
< max
); i
++)
2734 snprintf(buffer
+ i
* 3, 4, "%02x%c", *(u_int8_t
*)(input
+ i
), sep
);
2735 if (max
> 0 && size
> max
)
2736 snprintf(buffer
+ i
* 3, sizeof(truncation
) + 1, "%s", truncation
);
2738 *(buffer
+ i
*3 - 1) = 0;