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