]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/lib/atoms/chassis.c
lldp: don't use chassis TTL anymore
[thirdparty/lldpd.git] / src / lib / atoms / chassis.c
CommitLineData
99ef55d3
VB
1/* -*- mode: c; c-file-style: "openbsd" -*- */
2/*
3 * Copyright (c) 2015 Vincent Bernat <vincent@bernat.im>
4 *
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.
8 *
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.
16 */
17
18#include <stdio.h>
19#include <stdarg.h>
20#include <string.h>
21#include <arpa/inet.h>
22
23#include "lldpctl.h"
24#include "../log.h"
25#include "atom.h"
26#include "helpers.h"
27
28static lldpctl_map_t chassis_id_subtype_map[] = {
29 { LLDP_CHASSISID_SUBTYPE_IFNAME, "ifname"},
30 { LLDP_CHASSISID_SUBTYPE_IFALIAS, "ifalias" },
31 { LLDP_CHASSISID_SUBTYPE_LOCAL, "local" },
32 { LLDP_CHASSISID_SUBTYPE_LLADDR, "mac" },
33 { LLDP_CHASSISID_SUBTYPE_ADDR, "ip" },
34 { LLDP_CHASSISID_SUBTYPE_PORT, "unhandled" },
35 { LLDP_CHASSISID_SUBTYPE_CHASSIS, "unhandled" },
36 { 0, NULL},
37};
38
39#ifdef ENABLE_LLDPMED
40
41static lldpctl_map_t chassis_med_type_map[] = {
42 { LLDP_MED_CLASS_I, "Generic Endpoint (Class I)" },
43 { LLDP_MED_CLASS_II, "Media Endpoint (Class II)" },
44 { LLDP_MED_CLASS_III, "Communication Device Endpoint (Class III)" },
45 { LLDP_MED_NETWORK_DEVICE, "Network Connectivity Device" },
46 { 0, NULL },
47};
48
49#endif
50
51static int
52_lldpctl_atom_new_chassis(lldpctl_atom_t *atom, va_list ap)
53{
54 struct _lldpctl_atom_chassis_t *p =
55 (struct _lldpctl_atom_chassis_t *)atom;
56 p->chassis = va_arg(ap, struct lldpd_chassis*);
57 p->parent = va_arg(ap, struct _lldpctl_atom_port_t*);
e55e7492
VB
58 p->embedded = va_arg(ap, int);
59 if (p->parent && !p->embedded)
99ef55d3
VB
60 lldpctl_atom_inc_ref((lldpctl_atom_t*)p->parent);
61 return 1;
62}
63
64static void
65_lldpctl_atom_free_chassis(lldpctl_atom_t *atom)
66{
67 struct _lldpctl_atom_chassis_t *p =
68 (struct _lldpctl_atom_chassis_t *)atom;
69 /* When we have a parent, the chassis structure is in fact part of the
70 * parent, just decrement the reference count of the parent. Otherwise,
e55e7492
VB
71 * we need to free the whole chassis. When embedded, we don't alter the
72 * reference count of the parent. Therefore, it's important to also not
73 * increase the reference count of this atom. See
74 * `_lldpctl_atom_get_atom_chassis' for how to handle that. */
75 if (p->parent) {
76 if (!p->embedded)
77 lldpctl_atom_dec_ref((lldpctl_atom_t*)p->parent);
78 } else
79 lldpd_chassis_cleanup(p->chassis, 1);
99ef55d3
VB
80}
81
82static lldpctl_atom_t*
83_lldpctl_atom_get_atom_chassis(lldpctl_atom_t *atom, lldpctl_key_t key)
84{
85 struct _lldpctl_atom_chassis_t *p =
86 (struct _lldpctl_atom_chassis_t *)atom;
87 struct lldpd_chassis *chassis = p->chassis;
88
89 switch (key) {
90 case lldpctl_k_chassis_mgmt:
91 return _lldpctl_new_atom(atom->conn, atom_mgmts_list,
e55e7492
VB
92 (p->parent && p->embedded)?
93 (lldpctl_atom_t *)p->parent:
94 (lldpctl_atom_t *)p,
95 chassis);
99ef55d3
VB
96 default:
97 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
98 return NULL;
99 }
100}
101
102static const char*
103_lldpctl_atom_get_str_chassis(lldpctl_atom_t *atom, lldpctl_key_t key)
104{
105 struct _lldpctl_atom_chassis_t *p =
106 (struct _lldpctl_atom_chassis_t *)atom;
107 struct lldpd_chassis *chassis = p->chassis;
108 char *ipaddress = NULL; size_t len;
109
110 /* Local and remote port */
111 switch (key) {
112
113 case lldpctl_k_chassis_id_subtype:
114 return map_lookup(chassis_id_subtype_map, chassis->c_id_subtype);
115 case lldpctl_k_chassis_id:
116 switch (chassis->c_id_subtype) {
117 case LLDP_CHASSISID_SUBTYPE_IFNAME:
118 case LLDP_CHASSISID_SUBTYPE_IFALIAS:
119 case LLDP_CHASSISID_SUBTYPE_LOCAL:
120 return chassis->c_id;
121 case LLDP_CHASSISID_SUBTYPE_LLADDR:
122 return _lldpctl_dump_in_atom(atom,
123 (uint8_t*)chassis->c_id, chassis->c_id_len,
124 ':', 0);
125 case LLDP_CHASSISID_SUBTYPE_ADDR:
126 switch (chassis->c_id[0]) {
127 case LLDP_MGMT_ADDR_IP4: len = INET_ADDRSTRLEN + 1; break;
128 case LLDP_MGMT_ADDR_IP6: len = INET6_ADDRSTRLEN + 1; break;
129 default: len = 0;
130 }
131 if (len > 0) {
132 ipaddress = _lldpctl_alloc_in_atom(atom, len);
133 if (!ipaddress) return NULL;
134 if (inet_ntop((chassis->c_id[0] == LLDP_MGMT_ADDR_IP4)?
135 AF_INET:AF_INET6,
136 &chassis->c_id[1], ipaddress, len) == NULL)
137 break;
138 return ipaddress;
139 }
140 break;
141 }
142 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
143 return NULL;
144 case lldpctl_k_chassis_name: return chassis->c_name;
145 case lldpctl_k_chassis_descr: return chassis->c_descr;
146
147#ifdef ENABLE_LLDPMED
148 case lldpctl_k_chassis_med_type:
149 return map_lookup(chassis_med_type_map, chassis->c_med_type);
150 case lldpctl_k_chassis_med_inventory_hw:
151 return chassis->c_med_hw;
152 case lldpctl_k_chassis_med_inventory_sw:
153 return chassis->c_med_sw;
154 case lldpctl_k_chassis_med_inventory_fw:
155 return chassis->c_med_fw;
156 case lldpctl_k_chassis_med_inventory_sn:
157 return chassis->c_med_sn;
158 case lldpctl_k_chassis_med_inventory_manuf:
159 return chassis->c_med_manuf;
160 case lldpctl_k_chassis_med_inventory_model:
161 return chassis->c_med_model;
162 case lldpctl_k_chassis_med_inventory_asset:
163 return chassis->c_med_asset;
164#endif
165
166 default:
167 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
168 return NULL;
169 }
170}
171
172static long int
173_lldpctl_atom_get_int_chassis(lldpctl_atom_t *atom, lldpctl_key_t key)
174{
175 struct _lldpctl_atom_chassis_t *p =
176 (struct _lldpctl_atom_chassis_t *)atom;
177 struct lldpd_chassis *chassis = p->chassis;
178
179 /* Local and remote port */
180 switch (key) {
181 case lldpctl_k_chassis_index:
182 return chassis->c_index;
183 case lldpctl_k_chassis_id_subtype:
184 return chassis->c_id_subtype;
185 case lldpctl_k_chassis_cap_available:
186 return chassis->c_cap_available;
187 case lldpctl_k_chassis_cap_enabled:
188 return chassis->c_cap_enabled;
189#ifdef ENABLE_LLDPMED
190 case lldpctl_k_chassis_med_type:
191 return chassis->c_med_type;
192 case lldpctl_k_chassis_med_cap:
193 return chassis->c_med_cap_available;
194#endif
195 default:
196 return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
197 }
198 return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
199}
200
201static const uint8_t*
202_lldpctl_atom_get_buf_chassis(lldpctl_atom_t *atom, lldpctl_key_t key, size_t *n)
203{
204 struct _lldpctl_atom_chassis_t *p =
205 (struct _lldpctl_atom_chassis_t *)atom;
206 struct lldpd_chassis *chassis = p->chassis;
207
208 switch (key) {
209 case lldpctl_k_chassis_id:
210 *n = chassis->c_id_len;
211 return (uint8_t*)chassis->c_id;
212 default:
213 SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
214 return NULL;
215 }
216}
217
218static struct atom_builder chassis =
219 { atom_chassis, sizeof(struct _lldpctl_atom_chassis_t),
220 .init = _lldpctl_atom_new_chassis,
221 .free = _lldpctl_atom_free_chassis,
222 .get = _lldpctl_atom_get_atom_chassis,
223 .get_str = _lldpctl_atom_get_str_chassis,
224 .get_int = _lldpctl_atom_get_int_chassis,
225 .get_buffer = _lldpctl_atom_get_buf_chassis };
226
227ATOM_BUILDER_REGISTER(chassis, 3);