]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/daemon/agent.c
build: bump cross-platform-actions/action from 0.27.0 to 0.28.0
[thirdparty/lldpd.git] / src / daemon / agent.c
CommitLineData
4b292b55 1/* -*- mode: c; c-file-style: "openbsd" -*- */
43c02e7b
VB
2/*
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 *
51434125 5 * Permission to use, copy, modify, and/or distribute this software for any
43c02e7b
VB
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
5d6aba3e
VB
18#include "lldpd.h"
19
2eec5540
VB
20#include <assert.h>
21
4e22da4c 22#include "agent.h"
43c02e7b 23
ab2d1c1f 24#if HAVE_NET_SNMP_AGENT_UTIL_FUNCS_H
8b549648 25# include <net-snmp/agent/util_funcs.h>
ab2d1c1f 26#else
26836a43 27/* The above header may be buggy. We just need this function. */
8b549648 28int header_generic(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **);
ab2d1c1f 29#endif
43c02e7b 30
43c02e7b
VB
31/* For net-snmp */
32extern int register_sysORTable(oid *, size_t, const char *);
33extern int unregister_sysORTable(oid *, size_t);
43c02e7b
VB
34
35/* Global variable because no way to pass it as argument. Should not be used
36 * elsewhere. */
4e22da4c
VB
37#define scfg agent_scfg
38struct lldpd *agent_scfg;
43c02e7b 39
e86777ab 40static uint8_t
43c02e7b
VB
41swap_bits(uint8_t n)
42{
8b549648
VB
43 n = ((n & 0xF0) >> 4) | ((n & 0x0F) << 4);
44 n = ((n & 0xCC) >> 2) | ((n & 0x33) << 2);
45 n = ((n & 0xAA) >> 1) | ((n & 0x55) << 1);
43c02e7b 46
8b549648 47 return n;
43c02e7b
VB
48};
49
26836a43
VB
50extern struct timeval starttime;
51static long int
52lastchange(struct lldpd_port *port)
53{
54 if (port->p_lastchange > starttime.tv_sec)
8b549648 55 return (port->p_lastchange - starttime.tv_sec) * 100;
26836a43
VB
56 return 0;
57}
58
59/* -------------
60 Helper functions to build header_*indexed_table() functions.
61 Those functions keep an internal state. They are not reentrant!
62*/
63struct header_index {
64 struct variable *vp;
8b549648
VB
65 oid *name; /* Requested/returned OID */
66 size_t *length; /* Length of above OID */
67 int exact;
68 oid best[MAX_OID_LEN]; /* Best OID */
69 size_t best_len; /* Best OID length */
70 void *entity; /* Best entity */
26836a43
VB
71};
72static struct header_index header_idx;
73
4e22da4c 74static int
8b549648
VB
75header_index_init(struct variable *vp, oid *name, size_t *length, int exact,
76 size_t *var_len, WriteMethod **write_method)
43c02e7b 77{
4e22da4c
VB
78 /* If the requested OID name is less than OID prefix we
79 handle, adjust it to our prefix. */
8b549648
VB
80 if ((snmp_oid_compare(name, *length, vp->name, vp->namelen)) < 0) {
81 memcpy(name, vp->name, sizeof(oid) * vp->namelen);
82 *length = vp->namelen;
83 }
4e22da4c
VB
84 /* Now, we can only handle OID matching our prefix. Those two
85 tests are not really necessary since NetSNMP won't give us
86 OID "above" our prefix. But this makes unit tests
87 easier. */
88 if (*length < vp->namelen) return 0;
89 if (memcmp(name, vp->name, vp->namelen * sizeof(oid))) return 0;
90
8b549648 91 if (write_method != NULL) *write_method = 0;
26836a43
VB
92 *var_len = sizeof(long);
93
94 /* Initialize our header index structure */
95 header_idx.vp = vp;
96 header_idx.name = name;
97 header_idx.length = length;
98 header_idx.exact = exact;
99 header_idx.best_len = 0;
100 header_idx.entity = NULL;
4e22da4c 101 return 1;
26836a43
VB
102}
103
104static int
105header_index_add(oid *index, size_t len, void *entity)
106{
8b549648
VB
107 int result;
108 oid *target;
109 size_t target_len;
26836a43 110
8b549648
VB
111 target = header_idx.name + header_idx.vp->namelen;
112 target_len = *header_idx.length - header_idx.vp->namelen;
26836a43 113 if ((result = snmp_oid_compare(index, len, target, target_len)) < 0)
8b549648
VB
114 return 0; /* Too small. */
115 if (result == 0) return header_idx.exact;
26836a43 116 if (header_idx.best_len == 0 ||
8b549648 117 (snmp_oid_compare(index, len, header_idx.best, header_idx.best_len) < 0)) {
26836a43
VB
118 memcpy(header_idx.best, index, sizeof(oid) * len);
119 header_idx.best_len = len;
120 header_idx.entity = entity;
121 }
8b549648 122 return 0; /* No best match yet. */
26836a43 123}
43c02e7b 124
f540397c 125static void *
26836a43
VB
126header_index_best()
127{
8b549648
VB
128 if (header_idx.entity == NULL) return NULL;
129 if (header_idx.exact) return NULL;
130 memcpy(header_idx.name + header_idx.vp->namelen, header_idx.best,
131 sizeof(oid) * header_idx.best_len);
26836a43
VB
132 *header_idx.length = header_idx.vp->namelen + header_idx.best_len;
133 return header_idx.entity;
134}
135/* ----------------------------- */
136
8b549648
VB
137static struct lldpd_hardware *
138header_portindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
139 size_t *var_len, WriteMethod **write_method)
26836a43
VB
140{
141 struct lldpd_hardware *hardware;
43c02e7b 142
8b549648
VB
143 if (!header_index_init(vp, name, length, exact, var_len, write_method))
144 return NULL;
145 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
26836a43 146 oid index[1] = { hardware->h_ifindex };
8b549648 147 if (header_index_add(index, 1, hardware)) return hardware;
43c02e7b 148 }
26836a43 149 return header_index_best();
43c02e7b
VB
150}
151
fd6aa9a3 152#ifdef ENABLE_LLDPMED
8b549648 153static struct lldpd_med_policy *
26836a43
VB
154header_pmedindexed_policy_table(struct variable *vp, oid *name, size_t *length,
155 int exact, size_t *var_len, WriteMethod **write_method)
fd6aa9a3
VB
156{
157 struct lldpd_hardware *hardware;
26836a43 158 int i;
5fd6695c 159 oid index[2];
fd6aa9a3 160
8b549648
VB
161 if (!header_index_init(vp, name, length, exact, var_len, write_method))
162 return NULL;
163 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
4b292b55 164 for (i = 0; i < LLDP_MED_APPTYPE_LAST; i++) {
8b549648 165 if (hardware->h_lport.p_med_policy[i].type != i + 1) continue;
5fd6695c
VB
166 index[0] = hardware->h_ifindex;
167 index[1] = i + 1;
26836a43 168 if (header_index_add(index, 2,
8b549648 169 &hardware->h_lport.p_med_policy[i]))
26836a43
VB
170 return &hardware->h_lport.p_med_policy[i];
171 }
172 }
173 return header_index_best();
174}
fd6aa9a3 175
8b549648 176static struct lldpd_med_loc *
26836a43
VB
177header_pmedindexed_location_table(struct variable *vp, oid *name, size_t *length,
178 int exact, size_t *var_len, WriteMethod **write_method)
179{
180 struct lldpd_hardware *hardware;
181 int i;
5fd6695c 182 oid index[2];
fd6aa9a3 183
8b549648
VB
184 if (!header_index_init(vp, name, length, exact, var_len, write_method))
185 return NULL;
186 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
4b292b55 187 for (i = 0; i < LLDP_MED_LOCFORMAT_LAST; i++) {
8b549648 188 if (hardware->h_lport.p_med_location[i].format != i + 1)
fd6aa9a3 189 continue;
5fd6695c
VB
190 index[0] = hardware->h_ifindex;
191 index[1] = i + 2;
26836a43 192 if (header_index_add(index, 2,
8b549648 193 &hardware->h_lport.p_med_location[i]))
26836a43 194 return &hardware->h_lport.p_med_location[i];
fd6aa9a3
VB
195 }
196 }
26836a43 197 return header_index_best();
fd6aa9a3
VB
198}
199#endif
200
8b549648
VB
201static struct lldpd_port *
202header_tprindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
203 size_t *var_len, WriteMethod **write_method, int withmed)
43c02e7b 204{
26836a43
VB
205 struct lldpd_hardware *hardware;
206 struct lldpd_port *port;
5fd6695c 207 oid index[3];
43c02e7b 208
8b549648
VB
209 if (!header_index_init(vp, name, length, exact, var_len, write_method))
210 return NULL;
211 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
212 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
4d1a5b39 213 if (SMART_HIDDEN(port)) continue;
1e388a69 214#ifdef ENABLE_LLDPMED
077f7601 215 if (withmed && !port->p_chassis->c_med_cap_available) continue;
1e388a69 216#endif
5fd6695c
VB
217 index[0] = lastchange(port);
218 index[1] = hardware->h_ifindex;
219 index[2] = port->p_chassis->c_index;
8b549648 220 if (header_index_add(index, 3, port)) return port;
26836a43
VB
221 }
222 }
223 return header_index_best();
224}
43c02e7b 225
8b549648
VB
226static struct lldpd_mgmt *
227header_ipindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
228 size_t *var_len, WriteMethod **write_method)
e8c9b6bb
VB
229{
230 struct lldpd_chassis *chassis = LOCAL_CHASSIS(scfg);
e6b36c87 231 struct lldpd_mgmt *mgmt;
af3caa3b 232 oid index[2 + 16];
e8c9b6bb 233
8b549648
VB
234 if (!header_index_init(vp, name, length, exact, var_len, write_method))
235 return NULL;
236 TAILQ_FOREACH (mgmt, &chassis->c_mgmt, m_entries) {
af3caa3b
VB
237 int i;
238 switch (mgmt->m_family) {
8b549648
VB
239 case LLDPD_AF_IPV4:
240 index[0] = 1;
241 break;
242 case LLDPD_AF_IPV6:
243 index[0] = 2;
244 break;
245 default:
246 assert(0);
af3caa3b
VB
247 }
248 index[1] = mgmt->m_addrsize;
8b549648 249 if (index[1] > sizeof(index) - 2) continue; /* Odd... */
af3caa3b
VB
250 for (i = 0; i < index[1]; i++)
251 index[i + 2] = mgmt->m_addr.octets[i];
8b549648 252 if (header_index_add(index, 2 + index[1], mgmt)) return mgmt;
e6b36c87 253 }
e8c9b6bb 254
e6b36c87 255 return header_index_best();
e8c9b6bb
VB
256}
257
8b549648
VB
258static struct lldpd_mgmt *
259header_tpripindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
260 size_t *var_len, WriteMethod **write_method)
26836a43
VB
261{
262 struct lldpd_hardware *hardware;
263 struct lldpd_port *port;
e6b36c87 264 struct lldpd_mgmt *mgmt;
af3caa3b 265 oid index[5 + 16];
43c02e7b 266
8b549648
VB
267 if (!header_index_init(vp, name, length, exact, var_len, write_method))
268 return NULL;
269 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
270 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
4d1a5b39 271 if (SMART_HIDDEN(port)) continue;
8b549648 272 TAILQ_FOREACH (mgmt, &port->p_chassis->c_mgmt, m_entries) {
af3caa3b
VB
273 int i;
274 index[0] = lastchange(port);
275 index[1] = hardware->h_ifindex;
276 index[2] = port->p_chassis->c_index;
277 switch (mgmt->m_family) {
8b549648
VB
278 case LLDPD_AF_IPV4:
279 index[3] = 1;
280 break;
281 case LLDPD_AF_IPV6:
282 index[3] = 2;
283 break;
284 default:
285 assert(0);
af3caa3b
VB
286 }
287 index[4] = mgmt->m_addrsize;
8b549648 288 if (index[4] > sizeof(index) - 5) continue; /* Odd... */
af3caa3b
VB
289 for (i = 0; i < index[4]; i++)
290 index[i + 5] = mgmt->m_addr.octets[i];
291 if (header_index_add(index, 5 + index[4], mgmt))
2eec5540 292 return mgmt;
e6b36c87 293 }
26836a43
VB
294 }
295 }
296 return header_index_best();
297}
298
8ca3da07 299#ifdef ENABLE_CUSTOM
8b549648
VB
300static struct lldpd_custom *
301header_tprcustomindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
302 size_t *var_len, WriteMethod **write_method)
8ca3da07
VB
303{
304 struct lldpd_hardware *hardware;
305 struct lldpd_port *port;
306 struct lldpd_custom *custom;
307 oid index[8];
308 oid idx;
309
8b549648
VB
310 if (!header_index_init(vp, name, length, exact, var_len, write_method))
311 return NULL;
312 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
313 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
8ca3da07
VB
314 if (SMART_HIDDEN(port)) continue;
315 idx = 1;
8b549648 316 TAILQ_FOREACH (custom, &port->p_custom_list, next) {
8ca3da07
VB
317 index[0] = lastchange(port);
318 index[1] = hardware->h_ifindex;
319 index[2] = port->p_chassis->c_index;
320 index[3] = custom->oui[0];
321 index[4] = custom->oui[1];
322 index[5] = custom->oui[2];
323 index[6] = custom->subtype;
324 index[7] = idx++;
8b549648 325 if (header_index_add(index, 8, custom)) return custom;
8ca3da07
VB
326 }
327 }
328 }
329 return header_index_best();
330}
331#endif
332
1e388a69 333#ifdef ENABLE_LLDPMED
8b549648
VB
334# define TPR_VARIANT_MED_POLICY 2
335# define TPR_VARIANT_MED_LOCATION 3
336static void *
337header_tprmedindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
338 size_t *var_len, WriteMethod **write_method, int variant)
26836a43
VB
339{
340 struct lldpd_hardware *hardware;
341 struct lldpd_port *port;
342 int j;
5fd6695c 343 oid index[4];
26836a43 344
8b549648
VB
345 if (!header_index_init(vp, name, length, exact, var_len, write_method))
346 return NULL;
347 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
348 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
4d1a5b39 349 if (SMART_HIDDEN(port)) continue;
077f7601 350 if (!port->p_chassis->c_med_cap_available) continue;
4a2acc8e 351 switch (variant) {
4a2acc8e 352 case TPR_VARIANT_MED_POLICY:
8b549648
VB
353 for (j = 0; j < LLDP_MED_APPTYPE_LAST; j++) {
354 if (port->p_med_policy[j].type != j + 1)
26836a43 355 continue;
5fd6695c
VB
356 index[0] = lastchange(port);
357 index[1] = hardware->h_ifindex;
358 index[2] = port->p_chassis->c_index;
8b549648 359 index[3] = j + 1;
26836a43 360 if (header_index_add(index, 4,
8b549648 361 &port->p_med_policy[j]))
4e22da4c 362 return &port->p_med_policy[j];
26836a43 363 }
4a2acc8e
VB
364 break;
365 case TPR_VARIANT_MED_LOCATION:
8b549648
VB
366 for (j = 0; j < LLDP_MED_LOCFORMAT_LAST; j++) {
367 if (port->p_med_location[j].format != j + 1)
26836a43 368 continue;
5fd6695c
VB
369 index[0] = lastchange(port);
370 index[1] = hardware->h_ifindex;
371 index[2] = port->p_chassis->c_index;
8b549648 372 index[3] = j + 2;
26836a43 373 if (header_index_add(index, 4,
8b549648 374 &port->p_med_location[j]))
4e22da4c 375 return &port->p_med_location[j];
26836a43 376 }
4a2acc8e 377 break;
4a2acc8e 378 }
43c02e7b
VB
379 }
380 }
26836a43 381 return header_index_best();
43c02e7b 382}
1e388a69 383#endif
43c02e7b 384
a1347cd8 385#ifdef ENABLE_DOT1
8b549648
VB
386static struct lldpd_vlan *
387header_pvindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
388 size_t *var_len, WriteMethod **write_method)
43c02e7b
VB
389{
390 struct lldpd_hardware *hardware;
8b549648 391 struct lldpd_vlan *vlan;
43c02e7b 392
8b549648
VB
393 if (!header_index_init(vp, name, length, exact, var_len, write_method))
394 return NULL;
395 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
396 TAILQ_FOREACH (vlan, &hardware->h_lport.p_vlans, v_entries) {
397 oid index[2] = { hardware->h_ifindex, vlan->v_vid };
398 if (header_index_add(index, 2, vlan)) return vlan;
43c02e7b
VB
399 }
400 }
26836a43 401 return header_index_best();
43c02e7b
VB
402}
403
8b549648
VB
404static struct lldpd_vlan *
405header_tprvindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
406 size_t *var_len, WriteMethod **write_method)
43c02e7b
VB
407{
408 struct lldpd_hardware *hardware;
7a53c5b9 409 struct lldpd_port *port;
8b549648 410 struct lldpd_vlan *vlan;
43c02e7b 411
8b549648
VB
412 if (!header_index_init(vp, name, length, exact, var_len, write_method))
413 return NULL;
414 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
415 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
4d1a5b39 416 if (SMART_HIDDEN(port)) continue;
8b549648
VB
417 TAILQ_FOREACH (vlan, &port->p_vlans, v_entries) {
418 oid index[4] = { lastchange(port), hardware->h_ifindex,
419 port->p_chassis->c_index, vlan->v_vid };
420 if (header_index_add(index, 4, vlan)) return vlan;
26836a43 421 }
43c02e7b
VB
422 }
423 }
26836a43 424 return header_index_best();
43c02e7b 425}
26836a43 426
8b549648
VB
427static struct lldpd_ppvid *
428header_pppvidindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
429 size_t *var_len, WriteMethod **write_method)
dccc6964
VB
430{
431 struct lldpd_hardware *hardware;
8b549648 432 struct lldpd_ppvid *ppvid;
dccc6964 433
8b549648
VB
434 if (!header_index_init(vp, name, length, exact, var_len, write_method))
435 return NULL;
436 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
437 TAILQ_FOREACH (ppvid, &hardware->h_lport.p_ppvids, p_entries) {
438 oid index[2] = { hardware->h_ifindex, ppvid->p_ppvid };
439 if (header_index_add(index, 2, ppvid)) return ppvid;
dccc6964
VB
440 }
441 }
26836a43 442 return header_index_best();
dccc6964 443}
26836a43 444
8b549648
VB
445static struct lldpd_ppvid *
446header_tprppvidindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
447 size_t *var_len, WriteMethod **write_method)
dccc6964
VB
448{
449 struct lldpd_hardware *hardware;
450 struct lldpd_port *port;
8b549648 451 struct lldpd_ppvid *ppvid;
dccc6964 452
8b549648
VB
453 if (!header_index_init(vp, name, length, exact, var_len, write_method))
454 return NULL;
455 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
456 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
4d1a5b39 457 if (SMART_HIDDEN(port)) continue;
8b549648
VB
458 TAILQ_FOREACH (ppvid, &port->p_ppvids, p_entries) {
459 oid index[4] = { lastchange(port), hardware->h_ifindex,
460 port->p_chassis->c_index, ppvid->p_ppvid };
461 if (header_index_add(index, 4, ppvid)) return ppvid;
462 }
dccc6964
VB
463 }
464 }
26836a43 465 return header_index_best();
dccc6964 466}
26836a43 467
8b549648
VB
468static struct lldpd_pi *
469header_ppiindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
470 size_t *var_len, WriteMethod **write_method)
fbb9deaa
VB
471{
472 struct lldpd_hardware *hardware;
8b549648 473 struct lldpd_pi *pi;
fbb9deaa 474
8b549648
VB
475 if (!header_index_init(vp, name, length, exact, var_len, write_method))
476 return NULL;
477 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
478 TAILQ_FOREACH (pi, &hardware->h_lport.p_pids, p_entries) {
26836a43 479 oid index[2] = { hardware->h_ifindex,
8b549648
VB
480 frame_checksum((const u_char *)pi->p_pi, pi->p_pi_len,
481 0) };
482 if (header_index_add(index, 2, pi)) return pi;
fbb9deaa
VB
483 }
484 }
26836a43 485 return header_index_best();
fbb9deaa 486}
26836a43 487
8b549648
VB
488static struct lldpd_pi *
489header_tprpiindexed_table(struct variable *vp, oid *name, size_t *length, int exact,
490 size_t *var_len, WriteMethod **write_method)
fbb9deaa
VB
491{
492 struct lldpd_hardware *hardware;
493 struct lldpd_port *port;
8b549648 494 struct lldpd_pi *pi;
fbb9deaa 495
8b549648
VB
496 if (!header_index_init(vp, name, length, exact, var_len, write_method))
497 return NULL;
498 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
499 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
4d1a5b39 500 if (SMART_HIDDEN(port)) continue;
8b549648
VB
501 TAILQ_FOREACH (pi, &port->p_pids, p_entries) {
502 oid index[4] = { lastchange(port), hardware->h_ifindex,
503 port->p_chassis->c_index,
504 frame_checksum((const u_char *)pi->p_pi,
505 pi->p_pi_len, 0) };
506 if (header_index_add(index, 4, pi)) return pi;
507 }
fbb9deaa
VB
508 }
509 }
26836a43 510 return header_index_best();
fbb9deaa 511}
a1347cd8 512#endif
43c02e7b
VB
513
514/* Scalars */
515#define LLDP_SNMP_TXINTERVAL 1
516#define LLDP_SNMP_TXMULTIPLIER 2
517#define LLDP_SNMP_REINITDELAY 3
518#define LLDP_SNMP_TXDELAY 4
519#define LLDP_SNMP_NOTIFICATION 5
520#define LLDP_SNMP_LASTUPDATE 6
521#define LLDP_SNMP_STATS_INSERTS 7
522#define LLDP_SNMP_STATS_DELETES 8
523#define LLDP_SNMP_STATS_DROPS 9
524#define LLDP_SNMP_STATS_AGEOUTS 10
f645906c
VB
525/* Chassis */
526#define LLDP_SNMP_CIDSUBTYPE 1
527#define LLDP_SNMP_CID 2
528#define LLDP_SNMP_SYSNAME 3
529#define LLDP_SNMP_SYSDESCR 4
530#define LLDP_SNMP_SYSCAP_SUP 5
531#define LLDP_SNMP_SYSCAP_ENA 6
43c02e7b 532/* Stats */
43c02e7b 533#define LLDP_SNMP_STATS_TX 2
43c02e7b
VB
534#define LLDP_SNMP_STATS_RX_DISCARDED 4
535#define LLDP_SNMP_STATS_RX_ERRORS 5
536#define LLDP_SNMP_STATS_RX 6
537#define LLDP_SNMP_STATS_RX_TLVDISCARDED 7
538#define LLDP_SNMP_STATS_RX_TLVUNRECOGNIZED 8
539#define LLDP_SNMP_STATS_RX_AGEOUTS 9
14e9519e 540/* Ports */
14e9519e
VB
541#define LLDP_SNMP_PIDSUBTYPE 2
542#define LLDP_SNMP_PID 3
543#define LLDP_SNMP_PORTDESC 4
544#define LLDP_SNMP_DOT3_AUTONEG_SUPPORT 5
545#define LLDP_SNMP_DOT3_AUTONEG_ENABLED 6
546#define LLDP_SNMP_DOT3_AUTONEG_ADVERTISED 7
547#define LLDP_SNMP_DOT3_AUTONEG_MAU 8
548#define LLDP_SNMP_DOT3_AGG_STATUS 9
549#define LLDP_SNMP_DOT3_AGG_ID 10
550#define LLDP_SNMP_DOT3_MFS 11
551#define LLDP_SNMP_DOT3_POWER_DEVICETYPE 12
552#define LLDP_SNMP_DOT3_POWER_SUPPORT 13
553#define LLDP_SNMP_DOT3_POWER_ENABLED 14
554#define LLDP_SNMP_DOT3_POWER_PAIRCONTROL 15
555#define LLDP_SNMP_DOT3_POWER_PAIRS 16
556#define LLDP_SNMP_DOT3_POWER_CLASS 17
557#define LLDP_SNMP_DOT3_POWER_TYPE 18
558#define LLDP_SNMP_DOT3_POWER_SOURCE 19
559#define LLDP_SNMP_DOT3_POWER_PRIORITY 20
560#define LLDP_SNMP_DOT3_POWER_REQUESTED 21
561#define LLDP_SNMP_DOT3_POWER_ALLOCATED 22
562#define LLDP_SNMP_DOT1_PVID 23
f645906c
VB
563/* Vlans */
564#define LLDP_SNMP_DOT1_VLANNAME 1
f645906c 565/* Protocol VLAN IDs */
8b549648
VB
566#define LLDP_SNMP_DOT1_PPVLAN_SUPPORTED 2
567#define LLDP_SNMP_DOT1_PPVLAN_ENABLED 3
f645906c 568/* Protocol Identity */
8b549648 569#define LLDP_SNMP_DOT1_PI 1
43c02e7b 570/* Management address */
f645906c
VB
571#define LLDP_SNMP_ADDR_LEN 1
572#define LLDP_SNMP_ADDR_IFSUBTYPE 2
573#define LLDP_SNMP_ADDR_IFID 3
574#define LLDP_SNMP_ADDR_OID 4
8ca3da07
VB
575/* Custom TLVs */
576#define LLDP_SNMP_ORG_DEF_INFO 1
077f7601
VB
577/* LLDP-MED */
578#define LLDP_SNMP_MED_CAP_AVAILABLE 1
579#define LLDP_SNMP_MED_CAP_ENABLED 2
580#define LLDP_SNMP_MED_CLASS 3
581#define LLDP_SNMP_MED_HW 4
582#define LLDP_SNMP_MED_FW 5
583#define LLDP_SNMP_MED_SW 6
584#define LLDP_SNMP_MED_SN 7
585#define LLDP_SNMP_MED_MANUF 8
586#define LLDP_SNMP_MED_MODEL 9
587#define LLDP_SNMP_MED_ASSET 10
588#define LLDP_SNMP_MED_POLICY_VID 11
589#define LLDP_SNMP_MED_POLICY_PRIO 12
590#define LLDP_SNMP_MED_POLICY_DSCP 13
591#define LLDP_SNMP_MED_POLICY_UNKNOWN 14
592#define LLDP_SNMP_MED_POLICY_TAGGED 15
593#define LLDP_SNMP_MED_LOCATION 16
8e44f2dc
VB
594#define LLDP_SNMP_MED_POE_DEVICETYPE 17
595#define LLDP_SNMP_MED_POE_PSE_POWERVAL 19
596#define LLDP_SNMP_MED_POE_PSE_POWERSOURCE 20
597#define LLDP_SNMP_MED_POE_PSE_POWERPRIORITY 21
598#define LLDP_SNMP_MED_POE_PD_POWERVAL 22
599#define LLDP_SNMP_MED_POE_PD_POWERSOURCE 23
600#define LLDP_SNMP_MED_POE_PD_POWERPRIORITY 24
43c02e7b 601
51c72e72
VB
602/* The following macro should be used anytime where the selected OID
603 is finally not returned (for example, when the associated data is
604 not available). In this case, we retry the function with the next
605 OID. */
8b549648
VB
606#define TRYNEXT(X) \
607 do { \
608 if (!exact && (name[*length - 1] < MAX_SUBID)) \
609 return X(vp, name, length, exact, var_len, write_method); \
610 return NULL; \
611 } while (0)
612
613static u_char *
614agent_h_scalars(struct variable *vp, oid *name, size_t *length, int exact,
615 size_t *var_len, WriteMethod **write_method)
43c02e7b
VB
616{
617 static unsigned long long_ret;
618 struct lldpd_hardware *hardware;
7a53c5b9 619 struct lldpd_port *port;
43c02e7b 620
8b549648 621 if (header_generic(vp, name, length, exact, var_len, write_method)) return NULL;
43c02e7b
VB
622
623 switch (vp->magic) {
624 case LLDP_SNMP_TXINTERVAL:
8b549648 625 long_ret = (scfg->g_config.c_tx_interval + 999) / 1000;
43c02e7b
VB
626 return (u_char *)&long_ret;
627 case LLDP_SNMP_TXMULTIPLIER:
74f55c2e 628 long_ret = scfg->g_config.c_tx_hold;
43c02e7b
VB
629 return (u_char *)&long_ret;
630 case LLDP_SNMP_REINITDELAY:
631 long_ret = 1;
632 return (u_char *)&long_ret;
633 case LLDP_SNMP_TXDELAY:
634 long_ret = LLDPD_TX_MSGDELAY;
635 return (u_char *)&long_ret;
636 case LLDP_SNMP_NOTIFICATION:
637 long_ret = 5;
638 return (u_char *)&long_ret;
639 case LLDP_SNMP_LASTUPDATE:
640 long_ret = 0;
8b549648
VB
641 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
642 /* Check if the last removal of a remote port on this local port
643 * was the last change. */
c79467f6
TE
644 if (hardware->h_lport.p_lastremove > long_ret)
645 long_ret = hardware->h_lport.p_lastremove;
8b549648
VB
646 /* Check if any change on the existing remote ports was the last
647 * change. */
648 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
c79467f6
TE
649 if (SMART_HIDDEN(port)) continue;
650 if (port->p_lastchange > long_ret)
651 long_ret = port->p_lastchange;
652 }
42b39485 653 }
8b549648 654 if (long_ret) long_ret = (long_ret - starttime.tv_sec) * 100;
43c02e7b
VB
655 return (u_char *)&long_ret;
656 case LLDP_SNMP_STATS_INSERTS:
657 /* We assume this is equal to valid frames received on all ports */
658 long_ret = 0;
8b549648
VB
659 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries)
660 long_ret += hardware->h_insert_cnt;
43c02e7b
VB
661 return (u_char *)&long_ret;
662 case LLDP_SNMP_STATS_AGEOUTS:
663 long_ret = 0;
8b549648
VB
664 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries)
665 long_ret += hardware->h_ageout_cnt;
43c02e7b
VB
666 return (u_char *)&long_ret;
667 case LLDP_SNMP_STATS_DELETES:
668 long_ret = 0;
8b549648
VB
669 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries)
670 long_ret += hardware->h_delete_cnt;
43c02e7b
VB
671 return (u_char *)&long_ret;
672 case LLDP_SNMP_STATS_DROPS:
43c02e7b 673 long_ret = 0;
8b549648
VB
674 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries)
675 long_ret += hardware->h_drop_cnt;
43c02e7b
VB
676 return (u_char *)&long_ret;
677 default:
678 break;
51c72e72
VB
679 }
680 return NULL;
43c02e7b
VB
681}
682
1d88c843 683#ifdef ENABLE_LLDPMED
8b549648 684static u_char *
f645906c 685agent_v_med_power(struct variable *vp, size_t *var_len, struct lldpd_med_power *power)
8e44f2dc 686{
f645906c 687 static unsigned long long_ret;
8e44f2dc
VB
688
689 switch (vp->magic) {
690 case LLDP_SNMP_MED_POE_DEVICETYPE:
691 switch (power->devicetype) {
4b292b55 692 case LLDP_MED_POW_TYPE_PSE:
8b549648
VB
693 long_ret = 2;
694 break;
4b292b55 695 case LLDP_MED_POW_TYPE_PD:
8b549648
VB
696 long_ret = 3;
697 break;
8e44f2dc 698 case 0:
8b549648
VB
699 long_ret = 4;
700 break;
8e44f2dc
VB
701 default:
702 long_ret = 1;
703 }
f645906c 704 return (u_char *)&long_ret;
8e44f2dc
VB
705 case LLDP_SNMP_MED_POE_PSE_POWERVAL:
706 case LLDP_SNMP_MED_POE_PD_POWERVAL:
707 if (((vp->magic == LLDP_SNMP_MED_POE_PSE_POWERVAL) &&
8b549648 708 (power->devicetype == LLDP_MED_POW_TYPE_PSE)) ||
8e44f2dc 709 ((vp->magic == LLDP_SNMP_MED_POE_PD_POWERVAL) &&
8b549648 710 (power->devicetype == LLDP_MED_POW_TYPE_PD))) {
8e44f2dc 711 long_ret = power->val;
f645906c 712 return (u_char *)&long_ret;
8e44f2dc
VB
713 }
714 break;
715 case LLDP_SNMP_MED_POE_PSE_POWERSOURCE:
8b549648 716 if (power->devicetype == LLDP_MED_POW_TYPE_PSE) {
8e44f2dc 717 switch (power->source) {
4b292b55 718 case LLDP_MED_POW_SOURCE_PRIMARY:
8b549648
VB
719 long_ret = 2;
720 break;
4b292b55 721 case LLDP_MED_POW_SOURCE_BACKUP:
8b549648
VB
722 long_ret = 3;
723 break;
8e44f2dc
VB
724 default:
725 long_ret = 1;
726 }
f645906c 727 return (u_char *)&long_ret;
8e44f2dc
VB
728 }
729 break;
730 case LLDP_SNMP_MED_POE_PD_POWERSOURCE:
8b549648 731 if (power->devicetype == LLDP_MED_POW_TYPE_PD) {
8e44f2dc 732 switch (power->source) {
4b292b55 733 case LLDP_MED_POW_SOURCE_PSE:
8b549648
VB
734 long_ret = 2;
735 break;
4b292b55 736 case LLDP_MED_POW_SOURCE_LOCAL:
8b549648
VB
737 long_ret = 3;
738 break;
4b292b55 739 case LLDP_MED_POW_SOURCE_BOTH:
8b549648
VB
740 long_ret = 4;
741 break;
8e44f2dc
VB
742 default:
743 long_ret = 1;
744 }
f645906c 745 return (u_char *)&long_ret;
8e44f2dc
VB
746 }
747 break;
748 case LLDP_SNMP_MED_POE_PSE_POWERPRIORITY:
749 case LLDP_SNMP_MED_POE_PD_POWERPRIORITY:
750 if (((vp->magic == LLDP_SNMP_MED_POE_PSE_POWERPRIORITY) &&
8b549648 751 (power->devicetype == LLDP_MED_POW_TYPE_PSE)) ||
8e44f2dc 752 ((vp->magic == LLDP_SNMP_MED_POE_PD_POWERPRIORITY) &&
8b549648 753 (power->devicetype == LLDP_MED_POW_TYPE_PD))) {
8e44f2dc 754 switch (power->priority) {
4b292b55 755 case LLDP_MED_POW_PRIO_CRITICAL:
8b549648
VB
756 long_ret = 2;
757 break;
4b292b55 758 case LLDP_MED_POW_PRIO_HIGH:
8b549648
VB
759 long_ret = 3;
760 break;
4b292b55 761 case LLDP_MED_POW_PRIO_LOW:
8b549648
VB
762 long_ret = 4;
763 break;
8e44f2dc
VB
764 default:
765 long_ret = 1;
766 }
f645906c 767 return (u_char *)&long_ret;
8e44f2dc
VB
768 }
769 break;
770 }
771
f645906c 772 return NULL;
8e44f2dc 773}
8b549648
VB
774static u_char *
775agent_h_local_med_power(struct variable *vp, oid *name, size_t *length, int exact,
776 size_t *var_len, WriteMethod **write_method)
1d88c843 777{
5fd6695c 778 struct lldpd_med_power *power = NULL;
8b549648
VB
779 struct lldpd_hardware *hardware;
780 int pse = 0;
5fd6695c 781
8b549648
VB
782 if (!LOCAL_CHASSIS(scfg)->c_med_cap_available) return NULL;
783 if (header_generic(vp, name, length, exact, var_len, write_method)) return NULL;
1d88c843 784
077f7601
VB
785 /* LLDP-MED requires only one device type for all
786 ports. Moreover, a PSE can only have one power source. At
787 least, all PD values are global and not per-port. We try to
788 do our best. For device type, we decide on the number of
789 PD/PSE ports. */
8b549648
VB
790 TAILQ_FOREACH (hardware, &scfg->g_hardware, h_entries) {
791 if (hardware->h_lport.p_med_power.devicetype == LLDP_MED_POW_TYPE_PSE) {
077f7601
VB
792 pse++;
793 if (pse == 1) /* Take this port as a reference */
794 power = &hardware->h_lport.p_med_power;
795 } else if (hardware->h_lport.p_med_power.devicetype ==
8b549648 796 LLDP_MED_POW_TYPE_PD) {
077f7601
VB
797 pse--;
798 if (pse == -1) /* Take this one instead */
799 power = &hardware->h_lport.p_med_power;
8e44f2dc 800 }
077f7601
VB
801 }
802 if (power) {
f645906c 803 u_char *a;
8b549648 804 if ((a = agent_v_med_power(vp, var_len, power)) != NULL) return a;
1dcd4665 805 }
077f7601 806 TRYNEXT(agent_h_local_med_power);
1dcd4665 807}
8b549648
VB
808static u_char *
809agent_h_remote_med_power(struct variable *vp, oid *name, size_t *length, int exact,
810 size_t *var_len, WriteMethod **write_method)
8e44f2dc 811{
077f7601 812 struct lldpd_port *port;
5fd6695c 813 u_char *a;
8e44f2dc 814
8b549648
VB
815 if ((port = header_tprindexed_table(vp, name, length, exact, var_len,
816 write_method, 1)) == NULL)
8e44f2dc 817 return NULL;
8e44f2dc 818
8b549648 819 if ((a = agent_v_med_power(vp, var_len, &port->p_med_power)) != NULL) return a;
077f7601 820 TRYNEXT(agent_h_remote_med_power);
8e44f2dc
VB
821}
822
8b549648
VB
823static u_char *
824agent_v_med(struct variable *vp, size_t *var_len, struct lldpd_chassis *chassis,
825 struct lldpd_port *port)
1d88c843 826{
8b549648 827 static unsigned long long_ret;
077f7601 828 static uint8_t bit;
1d88c843
VB
829
830 switch (vp->magic) {
8b549648
VB
831 case LLDP_SNMP_MED_CLASS:
832 long_ret = chassis->c_med_type;
1be9e1b5 833 return (u_char *)&long_ret;
077f7601 834 case LLDP_SNMP_MED_CAP_AVAILABLE:
1d88c843 835 *var_len = 1;
077f7601 836 bit = swap_bits(chassis->c_med_cap_available);
40ecae87 837 return (u_char *)&bit;
077f7601
VB
838 case LLDP_SNMP_MED_CAP_ENABLED:
839 if (!port) break;
40ecae87 840 *var_len = 1;
7a53c5b9 841 bit = swap_bits(port->p_med_cap_enabled);
1d88c843 842 return (u_char *)&bit;
8e44f2dc 843
8b549648
VB
844# define LLDP_H_MED(magic, variable) \
845 case magic: \
846 if (chassis->variable) { \
847 *var_len = strlen(chassis->variable); \
848 return (u_char *)chassis->variable; \
849 } \
850 break
851
852 LLDP_H_MED(LLDP_SNMP_MED_HW, c_med_hw);
853 LLDP_H_MED(LLDP_SNMP_MED_SW, c_med_sw);
854 LLDP_H_MED(LLDP_SNMP_MED_FW, c_med_fw);
855 LLDP_H_MED(LLDP_SNMP_MED_SN, c_med_sn);
856 LLDP_H_MED(LLDP_SNMP_MED_MANUF, c_med_manuf);
857 LLDP_H_MED(LLDP_SNMP_MED_MODEL, c_med_model);
858 LLDP_H_MED(LLDP_SNMP_MED_ASSET, c_med_asset);
859 }
077f7601
VB
860 return NULL;
861}
8b549648
VB
862static u_char *
863agent_h_local_med(struct variable *vp, oid *name, size_t *length, int exact,
864 size_t *var_len, WriteMethod **write_method)
077f7601 865{
5fd6695c
VB
866 u_char *a;
867
8b549648
VB
868 if (!LOCAL_CHASSIS(scfg)->c_med_cap_available) return NULL;
869 if (header_generic(vp, name, length, exact, var_len, write_method)) return NULL;
077f7601 870
8b549648 871 if ((a = agent_v_med(vp, var_len, LOCAL_CHASSIS(scfg), NULL)) != NULL) return a;
077f7601 872 TRYNEXT(agent_h_local_med);
1d88c843 873}
4a2acc8e 874
8b549648
VB
875static u_char *
876agent_h_remote_med(struct variable *vp, oid *name, size_t *length, int exact,
877 size_t *var_len, WriteMethod **write_method)
4a2acc8e 878{
7a53c5b9 879 struct lldpd_port *port;
5fd6695c 880 u_char *a;
4a2acc8e 881
8b549648
VB
882 if ((port = header_tprindexed_table(vp, name, length, exact, var_len,
883 write_method, 1)) == NULL)
4a2acc8e
VB
884 return NULL;
885
8b549648 886 if ((a = agent_v_med(vp, var_len, port->p_chassis, port)) != NULL) return a;
077f7601
VB
887 TRYNEXT(agent_h_remote_med);
888}
4a2acc8e 889
8b549648 890static u_char *
077f7601 891agent_v_med_policy(struct variable *vp, size_t *var_len,
8b549648 892 struct lldpd_med_policy *policy)
077f7601 893{
8b549648 894 static unsigned long long_ret;
4a2acc8e
VB
895
896 switch (vp->magic) {
8b549648
VB
897 case LLDP_SNMP_MED_POLICY_VID:
898 long_ret = policy->vid;
4a2acc8e 899 return (u_char *)&long_ret;
077f7601 900 case LLDP_SNMP_MED_POLICY_PRIO:
4a2acc8e
VB
901 long_ret = policy->priority;
902 return (u_char *)&long_ret;
077f7601 903 case LLDP_SNMP_MED_POLICY_DSCP:
4a2acc8e
VB
904 long_ret = policy->dscp;
905 return (u_char *)&long_ret;
077f7601 906 case LLDP_SNMP_MED_POLICY_UNKNOWN:
8b549648 907 long_ret = policy->unknown ? 1 : 2;
4a2acc8e 908 return (u_char *)&long_ret;
077f7601 909 case LLDP_SNMP_MED_POLICY_TAGGED:
8b549648 910 long_ret = policy->tagged ? 1 : 2;
4a2acc8e
VB
911 return (u_char *)&long_ret;
912 default:
913 return NULL;
8b549648 914 }
4a2acc8e 915}
8b549648
VB
916static u_char *
917agent_h_remote_med_policy(struct variable *vp, oid *name, size_t *length, int exact,
918 size_t *var_len, WriteMethod **write_method)
4a2acc8e 919{
077f7601 920 struct lldpd_med_policy *policy;
4a2acc8e 921
8b549648
VB
922 if ((policy = (struct lldpd_med_policy *)header_tprmedindexed_table(vp, name,
923 length, exact, var_len, write_method, TPR_VARIANT_MED_POLICY)) == NULL)
4a2acc8e
VB
924 return NULL;
925
077f7601
VB
926 return agent_v_med_policy(vp, var_len, policy);
927}
8b549648
VB
928static u_char *
929agent_h_local_med_policy(struct variable *vp, oid *name, size_t *length, int exact,
930 size_t *var_len, WriteMethod **write_method)
077f7601
VB
931{
932 struct lldpd_med_policy *policy;
933
8b549648
VB
934 if ((policy = (struct lldpd_med_policy *)header_pmedindexed_policy_table(vp,
935 name, length, exact, var_len, write_method)) == NULL)
077f7601 936 return NULL;
4a2acc8e 937
077f7601
VB
938 return agent_v_med_policy(vp, var_len, policy);
939}
4a2acc8e 940
8b549648 941static u_char *
077f7601 942agent_v_med_location(struct variable *vp, size_t *var_len,
8b549648 943 struct lldpd_med_loc *location)
077f7601 944{
4a2acc8e 945 switch (vp->magic) {
8b549648 946 case LLDP_SNMP_MED_LOCATION:
4a2acc8e
VB
947 *var_len = location->data_len;
948 return (u_char *)location->data;
949 default:
950 return NULL;
8b549648 951 }
077f7601 952}
8b549648
VB
953static u_char *
954agent_h_remote_med_location(struct variable *vp, oid *name, size_t *length, int exact,
955 size_t *var_len, WriteMethod **write_method)
077f7601
VB
956{
957 struct lldpd_med_loc *location;
958
8b549648
VB
959 if ((location = (struct lldpd_med_loc *)header_tprmedindexed_table(vp, name,
960 length, exact, var_len, write_method, TPR_VARIANT_MED_LOCATION)) ==
961 NULL)
077f7601
VB
962 return NULL;
963
964 return agent_v_med_location(vp, var_len, location);
965}
8b549648
VB
966static u_char *
967agent_h_local_med_location(struct variable *vp, oid *name, size_t *length, int exact,
968 size_t *var_len, WriteMethod **write_method)
077f7601
VB
969{
970 struct lldpd_med_loc *location;
971
8b549648
VB
972 if ((location = (struct lldpd_med_loc *)header_pmedindexed_location_table(vp,
973 name, length, exact, var_len, write_method)) == NULL)
077f7601
VB
974 return NULL;
975
976 return agent_v_med_location(vp, var_len, location);
4a2acc8e 977}
1d88c843
VB
978#endif
979
8b549648
VB
980static u_char *
981agent_v_chassis(struct variable *vp, size_t *var_len, struct lldpd_chassis *chassis)
43c02e7b
VB
982{
983 static uint8_t bit;
8b549648 984 static unsigned long long_ret;
43c02e7b 985
43c02e7b 986 switch (vp->magic) {
f645906c 987 case LLDP_SNMP_CIDSUBTYPE:
8b549648 988 long_ret = chassis->c_id_subtype;
43c02e7b 989 return (u_char *)&long_ret;
f645906c
VB
990 case LLDP_SNMP_CID:
991 *var_len = chassis->c_id_len;
992 return (u_char *)chassis->c_id;
993 case LLDP_SNMP_SYSNAME:
12313820 994 if (!chassis->c_name || *chassis->c_name == '\0') break;
f645906c
VB
995 *var_len = strlen(chassis->c_name);
996 return (u_char *)chassis->c_name;
997 case LLDP_SNMP_SYSDESCR:
12313820 998 if (!chassis->c_descr || *chassis->c_descr == '\0') break;
f645906c
VB
999 *var_len = strlen(chassis->c_descr);
1000 return (u_char *)chassis->c_descr;
1001 case LLDP_SNMP_SYSCAP_SUP:
43c02e7b 1002 *var_len = 1;
f645906c 1003 bit = swap_bits(chassis->c_cap_available);
43c02e7b 1004 return (u_char *)&bit;
f645906c 1005 case LLDP_SNMP_SYSCAP_ENA:
43c02e7b 1006 *var_len = 1;
f645906c 1007 bit = swap_bits(chassis->c_cap_enabled);
43c02e7b
VB
1008 return (u_char *)&bit;
1009 default:
1010 break;
8b549648 1011 }
12313820 1012 return NULL;
f645906c 1013}
8b549648
VB
1014static u_char *
1015agent_h_local_chassis(struct variable *vp, oid *name, size_t *length, int exact,
1016 size_t *var_len, WriteMethod **write_method)
f645906c 1017{
351a4b1d
VB
1018 u_char *a;
1019
8b549648 1020 if (header_generic(vp, name, length, exact, var_len, write_method)) return NULL;
f645906c 1021
8b549648 1022 if ((a = agent_v_chassis(vp, var_len, LOCAL_CHASSIS(scfg))) != NULL) return a;
351a4b1d 1023 TRYNEXT(agent_h_local_chassis);
f645906c 1024}
8b549648
VB
1025static u_char *
1026agent_h_remote_chassis(struct variable *vp, oid *name, size_t *length, int exact,
1027 size_t *var_len, WriteMethod **write_method)
f645906c
VB
1028{
1029 struct lldpd_port *port;
351a4b1d 1030 u_char *a;
f645906c 1031
8b549648
VB
1032 if ((port = header_tprindexed_table(vp, name, length, exact, var_len,
1033 write_method, 0)) == NULL)
f645906c
VB
1034 return NULL;
1035
8b549648 1036 if ((a = agent_v_chassis(vp, var_len, port->p_chassis)) != NULL) return a;
351a4b1d 1037 TRYNEXT(agent_h_remote_chassis);
43c02e7b
VB
1038}
1039
8b549648
VB
1040static u_char *
1041agent_h_stats(struct variable *vp, oid *name, size_t *length, int exact,
1042 size_t *var_len, WriteMethod **write_method)
43c02e7b
VB
1043{
1044 static unsigned long long_ret;
1045 struct lldpd_hardware *hardware;
1046
8b549648
VB
1047 if ((hardware = header_portindexed_table(vp, name, length, exact, var_len,
1048 write_method)) == NULL)
43c02e7b
VB
1049 return NULL;
1050
1051 switch (vp->magic) {
1052 case LLDP_SNMP_STATS_TX:
8b549648
VB
1053 long_ret = hardware->h_tx_cnt;
1054 return (u_char *)&long_ret;
43c02e7b 1055 case LLDP_SNMP_STATS_RX:
8b549648 1056 long_ret = hardware->h_rx_cnt;
43c02e7b
VB
1057 return (u_char *)&long_ret;
1058 case LLDP_SNMP_STATS_RX_DISCARDED:
1059 case LLDP_SNMP_STATS_RX_ERRORS:
37387046
VB
1060 /* We discard only frame with errors. Therefore, the two values
1061 * are equal */
8b549648 1062 long_ret = hardware->h_rx_discarded_cnt;
43c02e7b
VB
1063 return (u_char *)&long_ret;
1064 case LLDP_SNMP_STATS_RX_TLVDISCARDED:
1065 case LLDP_SNMP_STATS_RX_TLVUNRECOGNIZED:
37387046
VB
1066 /* We discard only unrecognized TLV. Malformed TLV
1067 implies dropping the whole frame */
1068 long_ret = hardware->h_rx_unrecognized_cnt;
43c02e7b
VB
1069 return (u_char *)&long_ret;
1070 case LLDP_SNMP_STATS_RX_AGEOUTS:
8b549648 1071 long_ret = hardware->h_ageout_cnt;
43c02e7b
VB
1072 return (u_char *)&long_ret;
1073 default:
351a4b1d 1074 return NULL;
8b549648 1075 }
43c02e7b
VB
1076}
1077
a1347cd8 1078#ifdef ENABLE_DOT1
8b549648 1079static u_char *
f645906c 1080agent_v_vlan(struct variable *vp, size_t *var_len, struct lldpd_vlan *vlan)
43c02e7b 1081{
43c02e7b 1082 switch (vp->magic) {
f645906c 1083 case LLDP_SNMP_DOT1_VLANNAME:
43c02e7b
VB
1084 *var_len = strlen(vlan->v_name);
1085 return (u_char *)vlan->v_name;
1086 default:
351a4b1d 1087 return NULL;
8b549648 1088 }
43c02e7b 1089}
8b549648
VB
1090static u_char *
1091agent_h_local_vlan(struct variable *vp, oid *name, size_t *length, int exact,
1092 size_t *var_len, WriteMethod **write_method)
f645906c
VB
1093{
1094 struct lldpd_vlan *vlan;
1095
8b549648
VB
1096 if ((vlan = header_pvindexed_table(vp, name, length, exact, var_len,
1097 write_method)) == NULL)
f645906c 1098 return NULL;
43c02e7b 1099
f645906c
VB
1100 return agent_v_vlan(vp, var_len, vlan);
1101}
8b549648
VB
1102static u_char *
1103agent_h_remote_vlan(struct variable *vp, oid *name, size_t *length, int exact,
1104 size_t *var_len, WriteMethod **write_method)
43c02e7b
VB
1105{
1106 struct lldpd_vlan *vlan;
1107
8b549648
VB
1108 if ((vlan = header_tprvindexed_table(vp, name, length, exact, var_len,
1109 write_method)) == NULL)
43c02e7b
VB
1110 return NULL;
1111
f645906c
VB
1112 return agent_v_vlan(vp, var_len, vlan);
1113}
1114
8b549648 1115static u_char *
f645906c
VB
1116agent_v_ppvid(struct variable *vp, size_t *var_len, struct lldpd_ppvid *ppvid)
1117{
1118 static unsigned long long_ret;
1119
43c02e7b 1120 switch (vp->magic) {
f645906c 1121 case LLDP_SNMP_DOT1_PPVLAN_SUPPORTED:
8b549648 1122 long_ret = (ppvid->p_cap_status & LLDP_PPVID_CAP_SUPPORTED) ? 1 : 2;
f645906c
VB
1123 return (u_char *)&long_ret;
1124 case LLDP_SNMP_DOT1_PPVLAN_ENABLED:
8b549648 1125 long_ret = (ppvid->p_cap_status & LLDP_PPVID_CAP_ENABLED) ? 1 : 2;
dccc6964
VB
1126 return (u_char *)&long_ret;
1127 default:
351a4b1d 1128 return NULL;
8b549648 1129 }
dccc6964 1130}
8b549648
VB
1131static u_char *
1132agent_h_local_ppvid(struct variable *vp, oid *name, size_t *length, int exact,
1133 size_t *var_len, WriteMethod **write_method)
dccc6964
VB
1134{
1135 struct lldpd_ppvid *ppvid;
dccc6964 1136
8b549648
VB
1137 if ((ppvid = header_pppvidindexed_table(vp, name, length, exact, var_len,
1138 write_method)) == NULL)
dccc6964
VB
1139 return NULL;
1140
f645906c 1141 return agent_v_ppvid(vp, var_len, ppvid);
dccc6964
VB
1142}
1143
8b549648
VB
1144static u_char *
1145agent_h_remote_ppvid(struct variable *vp, oid *name, size_t *length, int exact,
1146 size_t *var_len, WriteMethod **write_method)
dccc6964
VB
1147{
1148 struct lldpd_ppvid *ppvid;
dccc6964 1149
8b549648
VB
1150 if ((ppvid = header_tprppvidindexed_table(vp, name, length, exact, var_len,
1151 write_method)) == NULL)
dccc6964
VB
1152 return NULL;
1153
f645906c
VB
1154 return agent_v_ppvid(vp, var_len, ppvid);
1155}
1156
8b549648 1157static u_char *
f645906c
VB
1158agent_v_pi(struct variable *vp, size_t *var_len, struct lldpd_pi *pi)
1159{
dccc6964 1160 switch (vp->magic) {
f645906c
VB
1161 case LLDP_SNMP_DOT1_PI:
1162 *var_len = pi->p_pi_len;
1163 return (u_char *)pi->p_pi;
43c02e7b 1164 default:
351a4b1d 1165 return NULL;
8b549648 1166 }
43c02e7b 1167}
8b549648
VB
1168static u_char *
1169agent_h_local_pi(struct variable *vp, oid *name, size_t *length, int exact,
1170 size_t *var_len, WriteMethod **write_method)
351a4b1d 1171{
fbb9deaa
VB
1172 struct lldpd_pi *pi;
1173
8b549648
VB
1174 if ((pi = header_ppiindexed_table(vp, name, length, exact, var_len,
1175 write_method)) == NULL)
fbb9deaa
VB
1176 return NULL;
1177
f645906c 1178 return agent_v_pi(vp, var_len, pi);
fbb9deaa 1179}
8b549648
VB
1180static u_char *
1181agent_h_remote_pi(struct variable *vp, oid *name, size_t *length, int exact,
1182 size_t *var_len, WriteMethod **write_method)
fbb9deaa
VB
1183{
1184 struct lldpd_pi *pi;
1185
8b549648
VB
1186 if ((pi = header_tprpiindexed_table(vp, name, length, exact, var_len,
1187 write_method)) == NULL)
fbb9deaa
VB
1188 return NULL;
1189
f645906c 1190 return agent_v_pi(vp, var_len, pi);
fbb9deaa 1191}
a1347cd8 1192#endif
43c02e7b 1193
8b549648 1194static u_char *
14e9519e 1195agent_v_port(struct variable *vp, size_t *var_len, struct lldpd_port *port)
43c02e7b 1196{
14e9519e 1197#ifdef ENABLE_DOT3
4e22da4c 1198 static uint16_t short_ret;
43c02e7b 1199 static uint8_t bit;
14e9519e 1200#endif
8b549648 1201 static unsigned long long_ret;
43c02e7b 1202
43c02e7b 1203 switch (vp->magic) {
8b549648
VB
1204 case LLDP_SNMP_PIDSUBTYPE:
1205 long_ret = port->p_id_subtype;
43c02e7b 1206 return (u_char *)&long_ret;
8b549648 1207 case LLDP_SNMP_PID:
7a53c5b9
VB
1208 *var_len = port->p_id_len;
1209 return (u_char *)port->p_id;
8b549648 1210 case LLDP_SNMP_PORTDESC:
12313820 1211 if (!port->p_descr || *port->p_descr == '\0') break;
7a53c5b9
VB
1212 *var_len = strlen(port->p_descr);
1213 return (u_char *)port->p_descr;
a1347cd8 1214#ifdef ENABLE_DOT3
8b549648
VB
1215 case LLDP_SNMP_DOT3_AUTONEG_SUPPORT:
1216 long_ret = 2 - port->p_macphy.autoneg_support;
1217 return (u_char *)&long_ret;
1218 case LLDP_SNMP_DOT3_AUTONEG_ENABLED:
1219 long_ret = 2 - port->p_macphy.autoneg_enabled;
1220 return (u_char *)&long_ret;
1221 case LLDP_SNMP_DOT3_AUTONEG_ADVERTISED:
1222 *var_len = 2;
4e22da4c 1223 short_ret = htons(port->p_macphy.autoneg_advertised);
8b549648
VB
1224 return (u_char *)&short_ret;
1225 case LLDP_SNMP_DOT3_AUTONEG_MAU:
1226 long_ret = port->p_macphy.mau_type;
1227 return (u_char *)&long_ret;
1228 case LLDP_SNMP_DOT3_AGG_STATUS:
1229 bit = swap_bits((port->p_aggregid > 0) ? 3 : 0);
1230 *var_len = 1;
1231 return (u_char *)&bit;
1232 case LLDP_SNMP_DOT3_AGG_ID:
1233 long_ret = port->p_aggregid;
1234 return (u_char *)&long_ret;
1235 case LLDP_SNMP_DOT3_MFS:
4e22da4c
VB
1236 if (port->p_mfs) {
1237 long_ret = port->p_mfs;
1238 return (u_char *)&long_ret;
1239 }
1240 break;
14e9519e 1241 case LLDP_SNMP_DOT3_POWER_DEVICETYPE:
befbdf89 1242 if (port->p_power.devicetype) {
8b549648
VB
1243 long_ret =
1244 (port->p_power.devicetype == LLDP_DOT3_POWER_PSE) ? 1 : 2;
befbdf89
VB
1245 return (u_char *)&long_ret;
1246 }
1247 break;
14e9519e 1248 case LLDP_SNMP_DOT3_POWER_SUPPORT:
befbdf89 1249 if (port->p_power.devicetype) {
8b549648 1250 long_ret = (port->p_power.supported) ? 1 : 2;
befbdf89
VB
1251 return (u_char *)&long_ret;
1252 }
1253 break;
14e9519e 1254 case LLDP_SNMP_DOT3_POWER_ENABLED:
befbdf89 1255 if (port->p_power.devicetype) {
8b549648 1256 long_ret = (port->p_power.enabled) ? 1 : 2;
befbdf89
VB
1257 return (u_char *)&long_ret;
1258 }
1259 break;
14e9519e 1260 case LLDP_SNMP_DOT3_POWER_PAIRCONTROL:
befbdf89 1261 if (port->p_power.devicetype) {
8b549648 1262 long_ret = (port->p_power.paircontrol) ? 1 : 2;
befbdf89
VB
1263 return (u_char *)&long_ret;
1264 }
1265 break;
14e9519e 1266 case LLDP_SNMP_DOT3_POWER_PAIRS:
befbdf89
VB
1267 if (port->p_power.devicetype) {
1268 long_ret = port->p_power.pairs;
1269 return (u_char *)&long_ret;
1270 }
1271 break;
14e9519e 1272 case LLDP_SNMP_DOT3_POWER_CLASS:
befbdf89
VB
1273 if (port->p_power.devicetype && port->p_power.class) {
1274 long_ret = port->p_power.class;
1275 return (u_char *)&long_ret;
1276 }
1277 break;
14e9519e 1278 case LLDP_SNMP_DOT3_POWER_TYPE:
608cb51c
VB
1279 if (port->p_power.devicetype &&
1280 port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
1281 *var_len = 1;
1282 bit = (((port->p_power.powertype ==
8b549648
VB
1283 LLDP_DOT3_POWER_8023AT_TYPE1) ?
1284 0 :
1285 1)
1286 << 7) |
1287 (((port->p_power.devicetype == LLDP_DOT3_POWER_PSE) ? 0 : 1)
1288 << 6);
608cb51c
VB
1289 return (u_char *)&bit;
1290 }
1291 break;
14e9519e 1292 case LLDP_SNMP_DOT3_POWER_SOURCE:
608cb51c
VB
1293 if (port->p_power.devicetype &&
1294 port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
1295 *var_len = 1;
8b549648 1296 bit = swap_bits(port->p_power.source % (1 << 2));
608cb51c
VB
1297 return (u_char *)&bit;
1298 }
1299 break;
14e9519e 1300 case LLDP_SNMP_DOT3_POWER_PRIORITY:
608cb51c
VB
1301 if (port->p_power.devicetype &&
1302 port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
4e22da4c
VB
1303 /* See 30.12.2.1.16. This seems defined in reverse order... */
1304 long_ret = 4 - port->p_power.priority;
608cb51c
VB
1305 return (u_char *)&long_ret;
1306 }
1307 break;
14e9519e 1308 case LLDP_SNMP_DOT3_POWER_REQUESTED:
608cb51c
VB
1309 if (port->p_power.devicetype &&
1310 port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
1311 long_ret = port->p_power.requested;
1312 return (u_char *)&long_ret;
1313 }
1314 break;
14e9519e 1315 case LLDP_SNMP_DOT3_POWER_ALLOCATED:
608cb51c
VB
1316 if (port->p_power.devicetype &&
1317 port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
1318 long_ret = port->p_power.allocated;
1319 return (u_char *)&long_ret;
1320 }
1321 break;
75b3469d
VB
1322#endif
1323#ifdef ENABLE_DOT1
8b549648
VB
1324 case LLDP_SNMP_DOT1_PVID:
1325 long_ret = port->p_pvid;
1326 return (u_char *)&long_ret;
a1347cd8 1327#endif
43c02e7b
VB
1328 default:
1329 break;
8b549648 1330 }
14e9519e
VB
1331 return NULL;
1332}
8b549648
VB
1333static u_char *
1334agent_h_remote_port(struct variable *vp, oid *name, size_t *length, int exact,
1335 size_t *var_len, WriteMethod **write_method)
14e9519e
VB
1336{
1337 struct lldpd_port *port;
1338 u_char *a;
1339
8b549648
VB
1340 if ((port = header_tprindexed_table(vp, name, length, exact, var_len,
1341 write_method, 0)) == NULL)
14e9519e
VB
1342 return NULL;
1343
8b549648 1344 if ((a = agent_v_port(vp, var_len, port)) != NULL) return a;
077f7601 1345 TRYNEXT(agent_h_remote_port);
14e9519e 1346}
8b549648
VB
1347static u_char *
1348agent_h_local_port(struct variable *vp, oid *name, size_t *length, int exact,
1349 size_t *var_len, WriteMethod **write_method)
14e9519e
VB
1350{
1351 struct lldpd_hardware *hardware;
1352 u_char *a;
1353
8b549648
VB
1354 if ((hardware = header_portindexed_table(vp, name, length, exact, var_len,
1355 write_method)) == NULL)
14e9519e
VB
1356 return NULL;
1357
8b549648 1358 if ((a = agent_v_port(vp, var_len, &hardware->h_lport)) != NULL) return a;
077f7601 1359 TRYNEXT(agent_h_local_port);
43c02e7b
VB
1360}
1361
8b549648 1362static u_char *
2eec5540 1363agent_v_management(struct variable *vp, size_t *var_len, struct lldpd_mgmt *mgmt)
43c02e7b 1364{
8b549648
VB
1365 static unsigned long int long_ret;
1366 static oid zeroDotZero[2] = { 0, 0 };
43c02e7b
VB
1367
1368 switch (vp->magic) {
8b549648
VB
1369 case LLDP_SNMP_ADDR_LEN:
1370 long_ret = mgmt->m_addrsize + 1;
1371 return (u_char *)&long_ret;
1372 case LLDP_SNMP_ADDR_IFSUBTYPE:
1373 if (mgmt->m_iface != 0)
1374 long_ret = LLDP_MGMT_IFACE_IFINDEX;
1375 else
1376 long_ret = 1;
1377 return (u_char *)&long_ret;
1378 case LLDP_SNMP_ADDR_IFID:
1379 long_ret = mgmt->m_iface;
1380 return (u_char *)&long_ret;
1381 case LLDP_SNMP_ADDR_OID:
1382 *var_len = sizeof(zeroDotZero);
1383 return (u_char *)zeroDotZero;
43c02e7b 1384 default:
351a4b1d 1385 return NULL;
8b549648 1386 }
43c02e7b 1387}
8b549648
VB
1388static u_char *
1389agent_h_local_management(struct variable *vp, oid *name, size_t *length, int exact,
1390 size_t *var_len, WriteMethod **write_method)
43c02e7b 1391{
26836a43 1392
2eec5540 1393 struct lldpd_mgmt *mgmt;
e8c9b6bb 1394
8b549648
VB
1395 if ((mgmt = header_ipindexed_table(vp, name, length, exact, var_len,
1396 write_method)) == NULL)
e8c9b6bb
VB
1397 return NULL;
1398
2eec5540 1399 return agent_v_management(vp, var_len, mgmt);
43c02e7b 1400}
8b549648
VB
1401static u_char *
1402agent_h_remote_management(struct variable *vp, oid *name, size_t *length, int exact,
1403 size_t *var_len, WriteMethod **write_method)
43c02e7b 1404{
2eec5540 1405 struct lldpd_mgmt *mgmt;
43c02e7b 1406
8b549648
VB
1407 if ((mgmt = header_tpripindexed_table(vp, name, length, exact, var_len,
1408 write_method)) == NULL)
43c02e7b
VB
1409 return NULL;
1410
8b549648 1411 return agent_v_management(vp, var_len, mgmt);
43c02e7b
VB
1412}
1413
8ca3da07 1414#ifdef ENABLE_CUSTOM
8b549648 1415static u_char *
8ca3da07
VB
1416agent_v_custom(struct variable *vp, size_t *var_len, struct lldpd_custom *custom)
1417{
1418 switch (vp->magic) {
8b549648 1419 case LLDP_SNMP_ORG_DEF_INFO:
8ca3da07
VB
1420 *var_len = custom->oui_info_len;
1421 return (u_char *)custom->oui_info;
1422 default:
351a4b1d 1423 return NULL;
8b549648 1424 }
8ca3da07 1425}
8b549648
VB
1426static u_char *
1427agent_h_remote_custom(struct variable *vp, oid *name, size_t *length, int exact,
1428 size_t *var_len, WriteMethod **write_method)
8ca3da07
VB
1429{
1430 struct lldpd_custom *custom;
1431
8b549648
VB
1432 if ((custom = header_tprcustomindexed_table(vp, name, length, exact, var_len,
1433 write_method)) == NULL)
8ca3da07
VB
1434 return NULL;
1435
8b549648 1436 return agent_v_custom(vp, var_len, custom);
8ca3da07
VB
1437}
1438#endif
1439
f645906c
VB
1440/*
1441 Here is how it works: a agent_h_*() function will handle incoming
1442 requests. It will use an appropriate header_*indexed_table()
1443 function to grab the appropriate structure that was queried (a port,
1444 a chassis, ...). It will then delegate to a agent_v_*() function the
1445 responsability to extract the appropriate answer.
1446
1447 agent_h_*() functions and header_*indexed_table() are not shared
1448 between remote and not remote version while agent_v_*() functions
1449 are the same for both version.
1450*/
1451
4e22da4c
VB
1452/* For testing purposes, keep this structure ordered by increasing OID! */
1453struct variable8 agent_lldp_vars[] = {
43c02e7b 1454 /* Scalars */
8b549648
VB
1455 { LLDP_SNMP_TXINTERVAL, ASN_INTEGER, RONLY, agent_h_scalars, 3, { 1, 1, 1 } },
1456 { LLDP_SNMP_TXMULTIPLIER, ASN_INTEGER, RONLY, agent_h_scalars, 3, { 1, 1, 2 } },
1457 { LLDP_SNMP_REINITDELAY, ASN_INTEGER, RONLY, agent_h_scalars, 3, { 1, 1, 3 } },
1458 { LLDP_SNMP_TXDELAY, ASN_INTEGER, RONLY, agent_h_scalars, 3, { 1, 1, 4 } },
1459 { LLDP_SNMP_NOTIFICATION, ASN_INTEGER, RONLY, agent_h_scalars, 3, { 1, 1, 5 } },
1460 { LLDP_SNMP_LASTUPDATE, ASN_TIMETICKS, RONLY, agent_h_scalars, 3, { 1, 2, 1 } },
1461 { LLDP_SNMP_STATS_INSERTS, ASN_GAUGE, RONLY, agent_h_scalars, 3, { 1, 2, 2 } },
1462 { LLDP_SNMP_STATS_DELETES, ASN_GAUGE, RONLY, agent_h_scalars, 3, { 1, 2, 3 } },
1463 { LLDP_SNMP_STATS_DROPS, ASN_GAUGE, RONLY, agent_h_scalars, 3, { 1, 2, 4 } },
1464 { LLDP_SNMP_STATS_AGEOUTS, ASN_GAUGE, RONLY, agent_h_scalars, 3, { 1, 2, 5 } },
43c02e7b 1465 /* Stats */
8b549648
VB
1466 { LLDP_SNMP_STATS_TX, ASN_COUNTER, RONLY, agent_h_stats, 5, { 1, 2, 6, 1, 2 } },
1467 { LLDP_SNMP_STATS_RX_DISCARDED, ASN_COUNTER, RONLY, agent_h_stats, 5,
1468 { 1, 2, 7, 1, 2 } },
1469 { LLDP_SNMP_STATS_RX_ERRORS, ASN_COUNTER, RONLY, agent_h_stats, 5,
1470 { 1, 2, 7, 1, 3 } },
1471 { LLDP_SNMP_STATS_RX, ASN_COUNTER, RONLY, agent_h_stats, 5, { 1, 2, 7, 1, 4 } },
1472 { LLDP_SNMP_STATS_RX_TLVDISCARDED, ASN_COUNTER, RONLY, agent_h_stats, 5,
1473 { 1, 2, 7, 1, 5 } },
1474 { LLDP_SNMP_STATS_RX_TLVUNRECOGNIZED, ASN_COUNTER, RONLY, agent_h_stats, 5,
1475 { 1, 2, 7, 1, 6 } },
1476 { LLDP_SNMP_STATS_RX_AGEOUTS, ASN_GAUGE, RONLY, agent_h_stats, 5,
1477 { 1, 2, 7, 1, 7 } },
4e22da4c 1478 /* Local chassis */
8b549648
VB
1479 { LLDP_SNMP_CIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_chassis, 3,
1480 { 1, 3, 1 } },
1481 { LLDP_SNMP_CID, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3, { 1, 3, 2 } },
1482 { LLDP_SNMP_SYSNAME, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3,
1483 { 1, 3, 3 } },
1484 { LLDP_SNMP_SYSDESCR, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3,
1485 { 1, 3, 4 } },
1486 { LLDP_SNMP_SYSCAP_SUP, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3,
1487 { 1, 3, 5 } },
1488 { LLDP_SNMP_SYSCAP_ENA, ASN_OCTET_STR, RONLY, agent_h_local_chassis, 3,
1489 { 1, 3, 6 } },
43c02e7b 1490 /* Local ports */
8b549648
VB
1491 { LLDP_SNMP_PIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_port, 5,
1492 { 1, 3, 7, 1, 2 } },
1493 { LLDP_SNMP_PID, ASN_OCTET_STR, RONLY, agent_h_local_port, 5,
1494 { 1, 3, 7, 1, 3 } },
1495 { LLDP_SNMP_PORTDESC, ASN_OCTET_STR, RONLY, agent_h_local_port, 5,
1496 { 1, 3, 7, 1, 4 } },
1497 /* Local management address */
1498 { LLDP_SNMP_ADDR_LEN, ASN_INTEGER, RONLY, agent_h_local_management, 5,
1499 { 1, 3, 8, 1, 3 } },
1500 { LLDP_SNMP_ADDR_IFSUBTYPE, ASN_INTEGER, RONLY, agent_h_local_management, 5,
1501 { 1, 3, 8, 1, 4 } },
1502 { LLDP_SNMP_ADDR_IFID, ASN_INTEGER, RONLY, agent_h_local_management, 5,
1503 { 1, 3, 8, 1, 5 } },
1504 { LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_local_management, 5,
1505 { 1, 3, 8, 1, 6 } },
1506 /* Remote ports */
1507 { LLDP_SNMP_CIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_chassis, 5,
1508 { 1, 4, 1, 1, 4 } },
1509 { LLDP_SNMP_CID, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5,
1510 { 1, 4, 1, 1, 5 } },
1511 { LLDP_SNMP_PIDSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_port, 5,
1512 { 1, 4, 1, 1, 6 } },
1513 { LLDP_SNMP_PID, ASN_OCTET_STR, RONLY, agent_h_remote_port, 5,
1514 { 1, 4, 1, 1, 7 } },
1515 { LLDP_SNMP_PORTDESC, ASN_OCTET_STR, RONLY, agent_h_remote_port, 5,
1516 { 1, 4, 1, 1, 8 } },
1517 { LLDP_SNMP_SYSNAME, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5,
1518 { 1, 4, 1, 1, 9 } },
1519 { LLDP_SNMP_SYSDESCR, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5,
1520 { 1, 4, 1, 1, 10 } },
1521 { LLDP_SNMP_SYSCAP_SUP, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5,
1522 { 1, 4, 1, 1, 11 } },
1523 { LLDP_SNMP_SYSCAP_ENA, ASN_OCTET_STR, RONLY, agent_h_remote_chassis, 5,
1524 { 1, 4, 1, 1, 12 } },
4e22da4c 1525 /* Remote management address */
8b549648
VB
1526 { LLDP_SNMP_ADDR_IFSUBTYPE, ASN_INTEGER, RONLY, agent_h_remote_management, 5,
1527 { 1, 4, 2, 1, 3 } },
1528 { LLDP_SNMP_ADDR_IFID, ASN_INTEGER, RONLY, agent_h_remote_management, 5,
1529 { 1, 4, 2, 1, 4 } },
1530 { LLDP_SNMP_ADDR_OID, ASN_OBJECT_ID, RONLY, agent_h_remote_management, 5,
1531 { 1, 4, 2, 1, 5 } },
8ca3da07
VB
1532#ifdef ENABLE_CUSTOM
1533 /* Custom TLVs */
8b549648
VB
1534 { LLDP_SNMP_ORG_DEF_INFO, ASN_OCTET_STR, RONLY, agent_h_remote_custom, 5,
1535 { 1, 4, 4, 1, 4 } },
8ca3da07 1536#endif
a1347cd8 1537#ifdef ENABLE_DOT3
8ca3da07 1538 /* Dot3, local ports */
8b549648
VB
1539 { LLDP_SNMP_DOT3_AUTONEG_SUPPORT, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1540 { 1, 5, 4623, 1, 2, 1, 1, 1 } },
1541 { LLDP_SNMP_DOT3_AUTONEG_ENABLED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1542 { 1, 5, 4623, 1, 2, 1, 1, 2 } },
1543 { LLDP_SNMP_DOT3_AUTONEG_ADVERTISED, ASN_OCTET_STR, RONLY, agent_h_local_port,
1544 8, { 1, 5, 4623, 1, 2, 1, 1, 3 } },
1545 { LLDP_SNMP_DOT3_AUTONEG_MAU, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1546 { 1, 5, 4623, 1, 2, 1, 1, 4 } },
1547 { LLDP_SNMP_DOT3_POWER_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1548 { 1, 5, 4623, 1, 2, 2, 1, 1 } },
1549 { LLDP_SNMP_DOT3_POWER_SUPPORT, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1550 { 1, 5, 4623, 1, 2, 2, 1, 2 } },
1551 { LLDP_SNMP_DOT3_POWER_ENABLED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1552 { 1, 5, 4623, 1, 2, 2, 1, 3 } },
1553 { LLDP_SNMP_DOT3_POWER_PAIRCONTROL, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1554 { 1, 5, 4623, 1, 2, 2, 1, 4 } },
1555 { LLDP_SNMP_DOT3_POWER_PAIRS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1556 { 1, 5, 4623, 1, 2, 2, 1, 5 } },
1557 { LLDP_SNMP_DOT3_POWER_CLASS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1558 { 1, 5, 4623, 1, 2, 2, 1, 6 } },
1559 { LLDP_SNMP_DOT3_POWER_TYPE, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
1560 { 1, 5, 4623, 1, 2, 2, 1, 7 } },
1561 { LLDP_SNMP_DOT3_POWER_SOURCE, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
1562 { 1, 5, 4623, 1, 2, 2, 1, 8 } },
1563 { LLDP_SNMP_DOT3_POWER_PRIORITY, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1564 { 1, 5, 4623, 1, 2, 2, 1, 9 } },
1565 { LLDP_SNMP_DOT3_POWER_REQUESTED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1566 { 1, 5, 4623, 1, 2, 2, 1, 10 } },
1567 { LLDP_SNMP_DOT3_POWER_ALLOCATED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1568 { 1, 5, 4623, 1, 2, 2, 1, 11 } },
1569 { LLDP_SNMP_DOT3_AGG_STATUS, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
1570 { 1, 5, 4623, 1, 2, 3, 1, 1 } },
1571 { LLDP_SNMP_DOT3_AGG_ID, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1572 { 1, 5, 4623, 1, 2, 3, 1, 2 } },
1573 { LLDP_SNMP_DOT3_MFS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1574 { 1, 5, 4623, 1, 2, 4, 1, 1 } },
75b3469d 1575#endif
8b549648 1576/* Dot3, remote ports */
a1347cd8 1577#ifdef ENABLE_DOT3
8b549648
VB
1578 { LLDP_SNMP_DOT3_AUTONEG_SUPPORT, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1579 { 1, 5, 4623, 1, 3, 1, 1, 1 } },
1580 { LLDP_SNMP_DOT3_AUTONEG_ENABLED, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1581 { 1, 5, 4623, 1, 3, 1, 1, 2 } },
1582 { LLDP_SNMP_DOT3_AUTONEG_ADVERTISED, ASN_OCTET_STR, RONLY, agent_h_remote_port,
1583 8, { 1, 5, 4623, 1, 3, 1, 1, 3 } },
1584 { LLDP_SNMP_DOT3_AUTONEG_MAU, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1585 { 1, 5, 4623, 1, 3, 1, 1, 4 } },
1586 { LLDP_SNMP_DOT3_POWER_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1587 { 1, 5, 4623, 1, 3, 2, 1, 1 } },
1588 { LLDP_SNMP_DOT3_POWER_SUPPORT, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1589 { 1, 5, 4623, 1, 3, 2, 1, 2 } },
1590 { LLDP_SNMP_DOT3_POWER_ENABLED, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1591 { 1, 5, 4623, 1, 3, 2, 1, 3 } },
1592 { LLDP_SNMP_DOT3_POWER_PAIRCONTROL, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1593 { 1, 5, 4623, 1, 3, 2, 1, 4 } },
1594 { LLDP_SNMP_DOT3_POWER_PAIRS, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1595 { 1, 5, 4623, 1, 3, 2, 1, 5 } },
1596 { LLDP_SNMP_DOT3_POWER_CLASS, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1597 { 1, 5, 4623, 1, 3, 2, 1, 6 } },
1598 { LLDP_SNMP_DOT3_POWER_TYPE, ASN_OCTET_STR, RONLY, agent_h_remote_port, 8,
1599 { 1, 5, 4623, 1, 3, 2, 1, 7 } },
1600 { LLDP_SNMP_DOT3_POWER_SOURCE, ASN_OCTET_STR, RONLY, agent_h_remote_port, 8,
1601 { 1, 5, 4623, 1, 3, 2, 1, 8 } },
1602 { LLDP_SNMP_DOT3_POWER_PRIORITY, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1603 { 1, 5, 4623, 1, 3, 2, 1, 9 } },
1604 { LLDP_SNMP_DOT3_POWER_REQUESTED, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1605 { 1, 5, 4623, 1, 3, 2, 1, 10 } },
1606 { LLDP_SNMP_DOT3_POWER_ALLOCATED, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1607 { 1, 5, 4623, 1, 3, 2, 1, 11 } },
1608 { LLDP_SNMP_DOT3_AGG_STATUS, ASN_OCTET_STR, RONLY, agent_h_remote_port, 8,
1609 { 1, 5, 4623, 1, 3, 3, 1, 1 } },
1610 { LLDP_SNMP_DOT3_AGG_ID, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1611 { 1, 5, 4623, 1, 3, 3, 1, 2 } },
1612 { LLDP_SNMP_DOT3_MFS, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1613 { 1, 5, 4623, 1, 3, 4, 1, 1 } },
a1347cd8 1614#endif
1d88c843
VB
1615#ifdef ENABLE_LLDPMED
1616 /* LLDP-MED local */
8b549648
VB
1617 { LLDP_SNMP_MED_CLASS, ASN_INTEGER, RONLY, agent_h_local_med, 6,
1618 { 1, 5, 4795, 1, 1, 1 } },
1619 { LLDP_SNMP_MED_POLICY_VID, ASN_INTEGER, RONLY, agent_h_local_med_policy, 8,
1620 { 1, 5, 4795, 1, 2, 1, 1, 2 } },
1621 { LLDP_SNMP_MED_POLICY_PRIO, ASN_INTEGER, RONLY, agent_h_local_med_policy, 8,
1622 { 1, 5, 4795, 1, 2, 1, 1, 3 } },
1623 { LLDP_SNMP_MED_POLICY_DSCP, ASN_INTEGER, RONLY, agent_h_local_med_policy, 8,
1624 { 1, 5, 4795, 1, 2, 1, 1, 4 } },
1625 { LLDP_SNMP_MED_POLICY_UNKNOWN, ASN_INTEGER, RONLY, agent_h_local_med_policy, 8,
1626 { 1, 5, 4795, 1, 2, 1, 1, 5 } },
1627 { LLDP_SNMP_MED_POLICY_TAGGED, ASN_INTEGER, RONLY, agent_h_local_med_policy, 8,
1628 { 1, 5, 4795, 1, 2, 1, 1, 6 } },
1629 { LLDP_SNMP_MED_HW, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1630 { 1, 5, 4795, 1, 2, 2 } },
1631 { LLDP_SNMP_MED_FW, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1632 { 1, 5, 4795, 1, 2, 3 } },
1633 { LLDP_SNMP_MED_SW, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1634 { 1, 5, 4795, 1, 2, 4 } },
1635 { LLDP_SNMP_MED_SN, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1636 { 1, 5, 4795, 1, 2, 5 } },
1637 { LLDP_SNMP_MED_MANUF, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1638 { 1, 5, 4795, 1, 2, 6 } },
1639 { LLDP_SNMP_MED_MODEL, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1640 { 1, 5, 4795, 1, 2, 7 } },
1641 { LLDP_SNMP_MED_ASSET, ASN_OCTET_STR, RONLY, agent_h_local_med, 6,
1642 { 1, 5, 4795, 1, 2, 8 } },
1643 { LLDP_SNMP_MED_LOCATION, ASN_OCTET_STR, RONLY, agent_h_local_med_location, 8,
1644 { 1, 5, 4795, 1, 2, 9, 1, 2 } },
1645 { LLDP_SNMP_MED_POE_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_local_med_power, 6,
1646 { 1, 5, 4795, 1, 2, 10 } },
1647 { LLDP_SNMP_MED_POE_PSE_POWERVAL, ASN_GAUGE, RONLY, agent_h_local_med_power, 8,
1648 { 1, 5, 4795, 1, 2, 11, 1, 1 } },
1649 { LLDP_SNMP_MED_POE_PSE_POWERPRIORITY, ASN_INTEGER, RONLY,
1650 agent_h_local_med_power, 8, { 1, 5, 4795, 1, 2, 11, 1, 2 } },
1651 { LLDP_SNMP_MED_POE_PSE_POWERSOURCE, ASN_INTEGER, RONLY,
1652 agent_h_local_med_power, 6, { 1, 5, 4795, 1, 2, 12 } },
1653 { LLDP_SNMP_MED_POE_PD_POWERVAL, ASN_GAUGE, RONLY, agent_h_local_med_power, 6,
1654 { 1, 5, 4795, 1, 2, 13 } },
1655 { LLDP_SNMP_MED_POE_PD_POWERSOURCE, ASN_INTEGER, RONLY, agent_h_local_med_power,
1656 6, { 1, 5, 4795, 1, 2, 14 } },
1657 { LLDP_SNMP_MED_POE_PD_POWERPRIORITY, ASN_INTEGER, RONLY,
1658 agent_h_local_med_power, 6, { 1, 5, 4795, 1, 2, 15 } },
1d88c843 1659 /* LLDP-MED remote */
8b549648
VB
1660 { LLDP_SNMP_MED_CAP_AVAILABLE, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1661 { 1, 5, 4795, 1, 3, 1, 1, 1 } },
1662 { LLDP_SNMP_MED_CAP_ENABLED, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1663 { 1, 5, 4795, 1, 3, 1, 1, 2 } },
1664 { LLDP_SNMP_MED_CLASS, ASN_INTEGER, RONLY, agent_h_remote_med, 8,
1665 { 1, 5, 4795, 1, 3, 1, 1, 3 } },
1666 { LLDP_SNMP_MED_POLICY_VID, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
1667 { 1, 5, 4795, 1, 3, 2, 1, 2 } },
1668 { LLDP_SNMP_MED_POLICY_PRIO, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
1669 { 1, 5, 4795, 1, 3, 2, 1, 3 } },
1670 { LLDP_SNMP_MED_POLICY_DSCP, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
1671 { 1, 5, 4795, 1, 3, 2, 1, 4 } },
1672 { LLDP_SNMP_MED_POLICY_UNKNOWN, ASN_INTEGER, RONLY, agent_h_remote_med_policy,
1673 8, { 1, 5, 4795, 1, 3, 2, 1, 5 } },
1674 { LLDP_SNMP_MED_POLICY_TAGGED, ASN_INTEGER, RONLY, agent_h_remote_med_policy, 8,
1675 { 1, 5, 4795, 1, 3, 2, 1, 6 } },
1676 { LLDP_SNMP_MED_HW, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1677 { 1, 5, 4795, 1, 3, 3, 1, 1 } },
1678 { LLDP_SNMP_MED_FW, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1679 { 1, 5, 4795, 1, 3, 3, 1, 2 } },
1680 { LLDP_SNMP_MED_SW, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1681 { 1, 5, 4795, 1, 3, 3, 1, 3 } },
1682 { LLDP_SNMP_MED_SN, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1683 { 1, 5, 4795, 1, 3, 3, 1, 4 } },
1684 { LLDP_SNMP_MED_MANUF, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1685 { 1, 5, 4795, 1, 3, 3, 1, 5 } },
1686 { LLDP_SNMP_MED_MODEL, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1687 { 1, 5, 4795, 1, 3, 3, 1, 6 } },
1688 { LLDP_SNMP_MED_ASSET, ASN_OCTET_STR, RONLY, agent_h_remote_med, 8,
1689 { 1, 5, 4795, 1, 3, 3, 1, 7 } },
1690 { LLDP_SNMP_MED_LOCATION, ASN_OCTET_STR, RONLY, agent_h_remote_med_location, 8,
1691 { 1, 5, 4795, 1, 3, 4, 1, 2 } },
1692 { LLDP_SNMP_MED_POE_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_remote_med_power, 8,
1693 { 1, 5, 4795, 1, 3, 5, 1, 1 } },
1694 { LLDP_SNMP_MED_POE_PSE_POWERVAL, ASN_GAUGE, RONLY, agent_h_remote_med_power, 8,
1695 { 1, 5, 4795, 1, 3, 6, 1, 1 } },
1696 { LLDP_SNMP_MED_POE_PSE_POWERSOURCE, ASN_INTEGER, RONLY,
1697 agent_h_remote_med_power, 8, { 1, 5, 4795, 1, 3, 6, 1, 2 } },
1698 { LLDP_SNMP_MED_POE_PSE_POWERPRIORITY, ASN_INTEGER, RONLY,
1699 agent_h_remote_med_power, 8, { 1, 5, 4795, 1, 3, 6, 1, 3 } },
1700 { LLDP_SNMP_MED_POE_PD_POWERVAL, ASN_GAUGE, RONLY, agent_h_remote_med_power, 8,
1701 { 1, 5, 4795, 1, 3, 7, 1, 1 } },
1702 { LLDP_SNMP_MED_POE_PD_POWERSOURCE, ASN_INTEGER, RONLY,
1703 agent_h_remote_med_power, 8, { 1, 5, 4795, 1, 3, 7, 1, 2 } },
1704 { LLDP_SNMP_MED_POE_PD_POWERPRIORITY, ASN_INTEGER, RONLY,
1705 agent_h_remote_med_power, 8, { 1, 5, 4795, 1, 3, 7, 1, 3 } },
4e22da4c 1706#endif
8b549648 1707/* Dot1, local and remote ports */
4e22da4c 1708#ifdef ENABLE_DOT1
8b549648
VB
1709 { LLDP_SNMP_DOT1_PVID, ASN_INTEGER, RONLY, agent_h_local_port, 8,
1710 { 1, 5, 32962, 1, 2, 1, 1, 1 } },
1711 { LLDP_SNMP_DOT1_PPVLAN_SUPPORTED, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
1712 { 1, 5, 32962, 1, 2, 2, 1, 2 } },
1713 { LLDP_SNMP_DOT1_PPVLAN_ENABLED, ASN_INTEGER, RONLY, agent_h_local_ppvid, 8,
1714 { 1, 5, 32962, 1, 2, 2, 1, 3 } },
1715 { LLDP_SNMP_DOT1_VLANNAME, ASN_OCTET_STR, RONLY, agent_h_local_vlan, 8,
1716 { 1, 5, 32962, 1, 2, 3, 1, 2 } },
1717 { LLDP_SNMP_DOT1_PI, ASN_OCTET_STR, RONLY, agent_h_local_pi, 8,
1718 { 1, 5, 32962, 1, 2, 4, 1, 2 } },
4e22da4c
VB
1719#endif
1720#ifdef ENABLE_DOT1
8b549648
VB
1721 { LLDP_SNMP_DOT1_PVID, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
1722 { 1, 5, 32962, 1, 3, 1, 1, 1 } },
1723 { LLDP_SNMP_DOT1_PPVLAN_SUPPORTED, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
1724 { 1, 5, 32962, 1, 3, 2, 1, 2 } },
1725 { LLDP_SNMP_DOT1_PPVLAN_ENABLED, ASN_INTEGER, RONLY, agent_h_remote_ppvid, 8,
1726 { 1, 5, 32962, 1, 3, 2, 1, 3 } },
1727 /* Remote vlans */
1728 { LLDP_SNMP_DOT1_VLANNAME, ASN_OCTET_STR, RONLY, agent_h_remote_vlan, 8,
1729 { 1, 5, 32962, 1, 3, 3, 1, 2 } },
4e22da4c 1730 /* Protocol identity */
8b549648
VB
1731 { LLDP_SNMP_DOT1_PI, ASN_OCTET_STR, RONLY, agent_h_remote_pi, 8,
1732 { 1, 5, 32962, 1, 3, 4, 1, 2 } },
1d88c843 1733#endif
43c02e7b 1734};
8b549648
VB
1735size_t
1736agent_lldp_vars_size(void)
1737{
1738 return sizeof(agent_lldp_vars) / sizeof(struct variable8);
4e22da4c
VB
1739}
1740
25de85a4
VB
1741/**
1742 * Send a notification about a change in one remote neighbor.
1743 *
1744 * @param hardware Interface on which the change has happened.
1745 * @param type Type of change (add, delete, update)
1746 * @param rport Changed remote port
1747 */
1748void
8b549648 1749agent_notify(struct lldpd_hardware *hardware, int type, struct lldpd_port *rport)
25de85a4
VB
1750{
1751 struct lldpd_hardware *h;
1752
1753 /* OID of the notification */
1754 oid notification_oid[] = { LLDP_OID, 0, 0, 1 };
1755 size_t notification_oid_len = OID_LENGTH(notification_oid);
1756 /* OID for snmpTrapOID.0 */
1757 oid objid_snmptrap[] = { SNMPTRAP_OID };
1758 size_t objid_snmptrap_len = OID_LENGTH(objid_snmptrap);
1759
1760 /* Other OID */
8b549648 1761 oid inserts_oid[] = { LLDP_OID, 1, 2, 2 };
25de85a4
VB
1762 size_t inserts_oid_len = OID_LENGTH(inserts_oid);
1763 unsigned long inserts = 0;
1764
8b549648 1765 oid deletes_oid[] = { LLDP_OID, 1, 2, 3 };
25de85a4
VB
1766 size_t deletes_oid_len = OID_LENGTH(deletes_oid);
1767 unsigned long deletes = 0;
1768
8b549648 1769 oid drops_oid[] = { LLDP_OID, 1, 2, 4 };
25de85a4
VB
1770 size_t drops_oid_len = OID_LENGTH(drops_oid);
1771 unsigned long drops = 0;
1772
8b549648 1773 oid ageouts_oid[] = { LLDP_OID, 1, 2, 5 };
25de85a4
VB
1774 size_t ageouts_oid_len = OID_LENGTH(ageouts_oid);
1775 unsigned long ageouts = 0;
1776
1777 /* We also add some extra. Easy ones. */
8b549648 1778 oid locport_oid[] = { LLDP_OID, 1, 3, 7, 1, 4, hardware->h_ifindex };
25de85a4 1779 size_t locport_oid_len = OID_LENGTH(locport_oid);
8b549648
VB
1780 oid sysname_oid[] = { LLDP_OID, 1, 4, 1, 1, 9, lastchange(rport),
1781 hardware->h_ifindex, rport->p_chassis->c_index };
25de85a4 1782 size_t sysname_oid_len = OID_LENGTH(sysname_oid);
8b549648
VB
1783 oid portdescr_oid[] = { LLDP_OID, 1, 4, 1, 1, 8, lastchange(rport),
1784 hardware->h_ifindex, rport->p_chassis->c_index };
25de85a4
VB
1785 size_t portdescr_oid_len = OID_LENGTH(portdescr_oid);
1786
1787 netsnmp_variable_list *notification_vars = NULL;
1788
be6db893
VB
1789 if (!hardware->h_cfg->g_snmp) return;
1790
6f8925be
VB
1791 switch (type) {
1792 case NEIGHBOR_CHANGE_DELETED:
1793 log_debug("snmp", "send notification for neighbor deleted on %s",
1794 hardware->h_ifname);
1795 break;
1796 case NEIGHBOR_CHANGE_UPDATED:
1797 log_debug("snmp", "send notification for neighbor updated on %s",
1798 hardware->h_ifname);
1799 break;
1800 case NEIGHBOR_CHANGE_ADDED:
1801 log_debug("snmp", "send notification for neighbor added on %s",
1802 hardware->h_ifname);
1803 break;
1804 }
1805
8b549648 1806 TAILQ_FOREACH (h, &hardware->h_cfg->g_hardware, h_entries) {
25de85a4
VB
1807 inserts += h->h_insert_cnt;
1808 deletes += h->h_delete_cnt;
1809 ageouts += h->h_ageout_cnt;
8b549648 1810 drops += h->h_drop_cnt;
25de85a4
VB
1811 }
1812
1813 /* snmpTrapOID */
8b549648
VB
1814 snmp_varlist_add_variable(&notification_vars, objid_snmptrap,
1815 objid_snmptrap_len, ASN_OBJECT_ID, (u_char *)notification_oid,
25de85a4
VB
1816 notification_oid_len * sizeof(oid));
1817
8b549648
VB
1818 snmp_varlist_add_variable(&notification_vars, inserts_oid, inserts_oid_len,
1819 ASN_GAUGE, (u_char *)&inserts, sizeof(inserts));
1820 snmp_varlist_add_variable(&notification_vars, deletes_oid, deletes_oid_len,
1821 ASN_GAUGE, (u_char *)&deletes, sizeof(inserts));
1822 snmp_varlist_add_variable(&notification_vars, drops_oid, drops_oid_len,
1823 ASN_GAUGE, (u_char *)&drops, sizeof(drops));
1824 snmp_varlist_add_variable(&notification_vars, ageouts_oid, ageouts_oid_len,
1825 ASN_GAUGE, (u_char *)&ageouts, sizeof(ageouts));
25de85a4
VB
1826
1827 if (type != NEIGHBOR_CHANGE_DELETED) {
8b549648
VB
1828 snmp_varlist_add_variable(&notification_vars, locport_oid,
1829 locport_oid_len, ASN_OCTET_STR, (u_char *)hardware->h_ifname,
25de85a4 1830 strnlen(hardware->h_ifname, IFNAMSIZ));
12313820 1831 if (rport->p_chassis->c_name && *rport->p_chassis->c_name != '\0') {
8b549648
VB
1832 snmp_varlist_add_variable(&notification_vars, sysname_oid,
1833 sysname_oid_len, ASN_OCTET_STR,
25de85a4
VB
1834 (u_char *)rport->p_chassis->c_name,
1835 strlen(rport->p_chassis->c_name));
1836 }
1837 if (rport->p_descr) {
8b549648
VB
1838 snmp_varlist_add_variable(&notification_vars, portdescr_oid,
1839 portdescr_oid_len, ASN_OCTET_STR, (u_char *)rport->p_descr,
25de85a4
VB
1840 strlen(rport->p_descr));
1841 }
1842 }
1843
8b549648
VB
1844 log_debug("snmp", "sending SNMP trap (%ld, %ld, %ld)", inserts, deletes,
1845 ageouts);
25de85a4
VB
1846 send_v2trap(notification_vars);
1847 snmp_free_varbind(notification_vars);
1848}
1849
350cd695
VB
1850/* Logging NetSNMP messages */
1851static int
8b549648
VB
1852agent_log_callback(int major, int minor, void *serverarg, void *clientarg)
1853{
1854 struct snmp_log_message *slm = (struct snmp_log_message *)serverarg;
1855 char *msg = strdup(slm->msg);
1856 (void)major;
1857 (void)minor;
1858 (void)clientarg;
1859
1860 if (msg && msg[strlen(msg) - 1] == '\n') msg[strlen(msg) - 1] = '\0';
1861 switch (slm->priority) {
1862 case LOG_EMERG:
1863 log_warnx("libsnmp", "%s", msg ? msg : slm->msg);
1864 break;
1865 case LOG_ALERT:
1866 log_warnx("libsnmp", "%s", msg ? msg : slm->msg);
1867 break;
1868 case LOG_CRIT:
1869 log_warnx("libsnmp", "%s", msg ? msg : slm->msg);
1870 break;
1871 case LOG_ERR:
1872 log_warnx("libsnmp", "%s", msg ? msg : slm->msg);
1873 break;
1874 case LOG_WARNING:
1875 log_warnx("libsnmp", "%s", msg ? msg : slm->msg);
1876 break;
1877 case LOG_NOTICE:
1878 log_info("libsnmp", "%s", msg ? msg : slm->msg);
1879 break;
1880 case LOG_INFO:
1881 log_info("libsnmp", "%s", msg ? msg : slm->msg);
1882 break;
1883 case LOG_DEBUG:
1884 log_debug("libsnmp", "%s", msg ? msg : slm->msg);
1885 break;
1886 }
1887 free(msg);
1888 return SNMP_ERR_NOERROR;
350cd695 1889}
43c02e7b
VB
1890
1891void
83d4b776 1892agent_init(struct lldpd *cfg, const char *agentx)
43c02e7b
VB
1893{
1894 int rc;
43c02e7b 1895
6f8925be 1896 log_info("snmp", "enable SNMP subagent");
43c02e7b 1897 netsnmp_enable_subagent();
6f8925be
VB
1898
1899 log_debug("snmp", "enable logging");
43c02e7b 1900 snmp_disable_log();
350cd695 1901 snmp_enable_calllog();
8b549648
VB
1902 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING,
1903 agent_log_callback, NULL);
43c02e7b
VB
1904
1905 scfg = cfg;
1906
37954d62 1907 /* We are chrooted, we don't want to handle persistent states */
8b549648
VB
1908 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE,
1909 TRUE);
37954d62
VB
1910 /* Do not load any MIB */
1911 setenv("MIBS", "", 1);
350cd695 1912 setenv("MIBDIRS", "/dev/null", 1);
43c02e7b 1913
71a7dbb3 1914#ifdef ENABLE_PRIVSEP
d72a05d4 1915 /* We provide our UNIX domain transport */
6f8925be 1916 log_debug("snmp", "register UNIX domain transport");
d72a05d4 1917 agent_priv_register_domain();
71a7dbb3 1918#endif
d72a05d4 1919
bbea66e1
V
1920 if (agentx)
1921 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
8b549648 1922 NETSNMP_DS_AGENT_X_SOCKET, agentx);
37954d62 1923 init_agent("lldpAgent");
4e22da4c 1924 REGISTER_MIB("lldp", agent_lldp_vars, variable8, lldp_oid);
43c02e7b
VB
1925 init_snmp("lldpAgent");
1926
6f8925be 1927 log_debug("snmp", "register to sysORTable");
43c02e7b 1928 if ((rc = register_sysORTable(lldp_oid, OID_LENGTH(lldp_oid),
8b549648 1929 "lldpMIB implementation by lldpd")) != 0)
6f8925be 1930 log_warnx("snmp", "unable to register to sysORTable (%d)", rc);
43c02e7b
VB
1931}
1932
1933void
1934agent_shutdown()
1935{
6f8925be 1936 log_debug("snmp", "agent shutdown");
43c02e7b
VB
1937 unregister_sysORTable(lldp_oid, OID_LENGTH(lldp_oid));
1938 snmp_shutdown("lldpAgent");
1939}