1 /*
2 * Interfaces MIB group implementation - interfaces.c
3 *
4 */
5
6 /* Portions of this file are subject to the following copyright(s). See
7 * the Net-SNMP's COPYING file for more details and other copyrights
8 * that may apply:
9 */
10 /*
11 * Portions of this file are copyrighted by:
12 * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
13 * Use is subject to license terms specified in the COPYING file
14 * distributed with the Net-SNMP package.
15 *
16 * Portions of this file are copyrighted by:
17 * Copyright (c) 2016 VMware, Inc. All rights reserved.
18 * Use is subject to license terms specified in the COPYING file
19 * distributed with the Net-SNMP package.
20 */
21
22 #include <net-snmp/net-snmp-config.h>
23 #include <net-snmp/net-snmp-features.h>
24
25 netsnmp_feature_provide(interface_legacy);
26
27 #if defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && !defined(NETSNMP_IFNET_NEEDS_KERNEL_LATE)
28 #define _KERNEL 1
29 #define _I_DEFINED_KERNEL
30 #endif
31
32 #if HAVE_STRING_H
33 #include <string.h>
34 #else
35 #include <strings.h>
36 #endif
37
38 #if HAVE_STDLIB_H
39 #include <stdlib.h>
40 #endif
41 #if HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #if HAVE_SYS_PARAM_H
45 #include <sys/param.h>
46 #endif
47 #include <sys/types.h>
48 #if defined(NETSNMP_IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && defined(NETSNMP_IFNET_NEEDS_KERNEL_LATE)
49 #define _KERNEL 1
50 #define _I_DEFINED_KERNEL
51 #endif
52 #if HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
54 #endif
55 #ifndef STREAM_NEEDS_KERNEL_ISLANDS
56 #if HAVE_SYS_STREAM_H
57 #include <sys/stream.h>
58 #endif
59 #endif
60 #if HAVE_SYS_SOCKETVAR_H
61 #include <sys/socketvar.h>
62 #endif
63
64 #if TIME_WITH_SYS_TIME
65 # include <sys/time.h>
66 # include <time.h>
67 #else
68 # if HAVE_SYS_TIME_H
69 # include <sys/time.h>
70 # else
71 # include <time.h>
72 # endif
73 #endif
74 #if HAVE_SYS_SOCKIO_H
75 #include <sys/sockio.h>
76 #endif
77 #if HAVE_FCNTL_H
78 #include <fcntl.h>
79 #endif
80 #if HAVE_SYS_IOCTL_H
81 #include <sys/ioctl.h>
82 #endif
83 #if HAVE_NETINET_IN_H
84 #include <netinet/in.h>
85 #endif
86 #if HAVE_NET_IF_H
87 #include <net/if.h>
88 #endif
89 #if HAVE_NETINET_IN_VAR_H
90 #include <netinet/in_var.h>
91 #endif
92 #if HAVE_NET_IF_VAR_H
93 #include <net/if_var.h>
94 #endif
95 #ifdef _I_DEFINED_KERNEL
96 #undef _KERNEL
97 #endif
98 #ifdef STREAM_NEEDS_KERNEL_ISLANDS
99 #if HAVE_SYS_STREAM_H
100 #include <sys/stream.h>
101 #endif
102 #endif
103 #if HAVE_NET_ROUTE_H
104 #include <net/route.h>
105 #endif
106 #if HAVE_NETINET_IN_SYSTM_H
107 #include <netinet/in_systm.h>
108 #endif
109 #if HAVE_SYS_HASHING_H
110 #include <sys/hashing.h>
111 #endif
112 #if HAVE_NETINET_IN_VAR_H
113 #include <netinet/in_var.h>
114 #endif
115 #if HAVE_NETINET_IP_H
116 #include <netinet/ip.h>
117 #endif
118 #ifdef NETSNMP_ENABLE_IPV6
119 #if HAVE_NETINET_IP6_H
120 #include <netinet/ip6.h>
121 #endif
122 #endif
123 #if HAVE_SYS_QUEUE_H
124 #include <sys/queue.h>
125 #endif
126 #if HAVE_NETINET_IP_VAR_H
127 #include <netinet/ip_var.h>
128 #endif
129 #ifdef NETSNMP_ENABLE_IPV6
130 #if HAVE_NETNETSNMP_ENABLE_IPV6_IP6_VAR_H
131 #include <netinet6/ip6_var.h>
132 #endif
133 #endif
134 #if HAVE_NETINET_IN_PCB_H
135 #include <netinet/in_pcb.h>
136 #endif
137 #if HAVE_NETINET_IF_ETHER_H
138 #include <netinet/if_ether.h>
139 #endif
140 #if HAVE_NET_IF_TYPES_H
141 #include <net/if_types.h>
142 #endif
143 #if HAVE_NET_IF_DL_H
144 #ifndef dynix
145 #include <net/if_dl.h>
146 #else
147 #include <sys/net/if_dl.h>
148 #endif
149 #endif
150 #if HAVE_INET_MIB2_H
151 #include <inet/mib2.h>
152 #endif
153 #if HAVE_IOCTLS_H
154 #include <ioctls.h>
155 #endif
156
157 #ifdef solaris2
158 # include <errno.h>
159 #include "kernel_sunos5.h"
160 #else
161 #include "kernel.h"
162 #endif
163
164 #ifdef hpux
165 #include <sys/mib.h>
166 #include <netinet/mib_kern.h>
167 #endif /* hpux */
168
169 #if defined(cygwin) || defined(mingw32)
170 #include <windows.h>
171 #endif
172
173 #if HAVE_SYS_SYSCTL_H
174 #include <sys/sysctl.h>
175
176 #if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
177 # define USE_SYSCTL_IFLIST
178 #else
179 # if defined(CTL_NET) && !defined(freebsd2) && !defined(netbsd1)
180 # ifdef PF_ROUTE
181 # ifdef NET_RT_IFLIST
182 # ifndef netbsd1
183 # define USE_SYSCTL_IFLIST
184 # endif
185 # endif
186 # endif
187 # endif
188 #endif /* defined(freebsd3) */
189 #endif /* HAVE_SYS_SYSCTL_H */
190
191 #if HAVE_OSRELDATE_H
192 #include <osreldate.h>
193 #endif
194 #ifdef NETSNMP_CAN_USE_SYSCTL
195 #include <sys/sysctl.h>
196 #endif
197
198 #include <net-snmp/net-snmp-includes.h>
199 #include <net-snmp/agent/net-snmp-agent-includes.h>
200 #include <net-snmp/agent/auto_nlist.h>
201 #include <net-snmp/agent/sysORTable.h>
202 #include <net-snmp/data_access/interface.h>
203
204 #include "interfaces.h"
205 #include "struct.h"
206 #include "util_funcs.h"
207 #include "util_funcs/header_generic.h"
208
209 /* if you want caching enabled for speed retrieval purposes, set this to 5?*/
210 #define MINLOADFREQ 0 /* min reload frequency in seconds */
211 #ifdef linux
212 static unsigned long LastLoad = 0; /* ET in secs at last table load */
213 #endif
214
215 #define starttime (*(const struct timeval*)netsnmp_get_agent_starttime())
216
217 struct variable3 interfaces_variables[] = {
218 {NETSNMP_IFNUMBER, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
219 var_interfaces, 1, {1}},
220 {NETSNMP_IFINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
221 var_ifEntry, 3, {2, 1, 1}},
222 {NETSNMP_IFDESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
223 var_ifEntry, 3, {2, 1, 2}},
224 {NETSNMP_IFTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
225 var_ifEntry, 3, {2, 1, 3}},
226 {NETSNMP_IFMTU, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
227 var_ifEntry, 3, {2, 1, 4}},
228 {NETSNMP_IFSPEED, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
229 var_ifEntry, 3, {2, 1, 5}},
230 {NETSNMP_IFPHYSADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
231 var_ifEntry, 3, {2, 1, 6}},
232 #ifndef NETSNMP_NO_WRITE_SUPPORT
233 #if defined (WIN32) || defined (cygwin)
234 {NETSNMP_IFADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
235 var_ifEntry, 3, {2, 1, 7}},
236 #else
237 {NETSNMP_IFADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
238 var_ifEntry, 3, {2, 1, 7}},
239 #endif
240 #else /* !NETSNMP_NO_WRITE_SUPPORT */
241 {NETSNMP_IFADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
242 var_ifEntry, 3, {2, 1, 7}},
243 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
244 {NETSNMP_IFOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
245 var_ifEntry, 3, {2, 1, 8}},
246 {NETSNMP_IFLASTCHANGE, ASN_TIMETICKS, NETSNMP_OLDAPI_RONLY,
247 var_ifEntry, 3, {2, 1, 9}},
248 {NETSNMP_IFINOCTETS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
249 var_ifEntry, 3, {2, 1, 10}},
250 {NETSNMP_IFINUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
251 var_ifEntry, 3, {2, 1, 11}},
252 {NETSNMP_IFINNUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
253 var_ifEntry, 3, {2, 1, 12}},
254 {NETSNMP_IFINDISCARDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
255 var_ifEntry, 3, {2, 1, 13}},
256 {NETSNMP_IFINERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
257 var_ifEntry, 3, {2, 1, 14}},
258 {NETSNMP_IFINUNKNOWNPROTOS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
259 var_ifEntry, 3, {2, 1, 15}},
260 {NETSNMP_IFOUTOCTETS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
261 var_ifEntry, 3, {2, 1, 16}},
262 {NETSNMP_IFOUTUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
263 var_ifEntry, 3, {2, 1, 17}},
264 {NETSNMP_IFOUTNUCASTPKTS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
265 var_ifEntry, 3, {2, 1, 18}},
266 {NETSNMP_IFOUTDISCARDS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
267 var_ifEntry, 3, {2, 1, 19}},
268 {NETSNMP_IFOUTERRORS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
269 var_ifEntry, 3, {2, 1, 20}},
270 {NETSNMP_IFOUTQLEN, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
271 var_ifEntry, 3, {2, 1, 21}},
272 {NETSNMP_IFSPECIFIC, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
273 var_ifEntry, 3, {2, 1, 22}}
274 };
275
276 /*
277 * Define the OID pointer to the top of the mib tree that we're
278 * registering underneath, and the OID of the MIB module
279 */
280 oid interfaces_variables_oid[] = { SNMP_OID_MIB2, 2 };
281 oid interfaces_module_oid[] = { SNMP_OID_MIB2, 31 };
282
283 void
init_interfaces(void)284 init_interfaces(void)
285 {
286 /*
287 * register ourselves with the agent to handle our mib tree
288 */
289 REGISTER_MIB("mibII/interfaces", interfaces_variables, variable3,
290 interfaces_variables_oid);
291 REGISTER_SYSOR_ENTRY(interfaces_module_oid,
292 "The MIB module to describe generic objects for network interface sub-layers");
293
294 #ifndef USE_SYSCTL_IFLIST
295 #if HAVE_NET_IF_MIB_H
296 init_interfaces_setup();
297 #endif
298 #endif
299 #ifdef solaris2
300 init_kernel_sunos5();
301 #endif
302 }
303
304 #ifdef linux
305 /*
306 * if_type_from_name
307 * Return interface type using the interface name as a clue.
308 * Returns 1 to imply "other" type if name not recognized.
309 */
310 static int
if_type_from_name(const char * pcch)311 if_type_from_name(const char *pcch)
312 {
313 typedef struct _match_if {
314 int mi_type;
315 const char *mi_name;
316 } *pmatch_if, match_if;
317
318 static match_if lmatch_if[] = {
319 {24, "lo"},
320 {6, "eth"},
321 {9, "tr"},
322 {23, "ppp"},
323 {28, "sl"},
324 {0, 0} /* end of list */
325 };
326
327 int len;
328 register pmatch_if pm;
329
330 for (pm = lmatch_if; pm->mi_name; pm++) {
331 len = strlen(pm->mi_name);
332 if (0 == strncmp(pcch, pm->mi_name, len)) {
333 return (pm->mi_type);
334 }
335 }
336 return (1); /* in case search fails */
337 }
338 #endif
339
340
341 #ifdef linux
342 static struct ifnet *ifnetaddr_list;
343 #endif
344
345
346 /*
347 * header_ifEntry(...
348 * Arguments:
349 * vp IN - pointer to variable entry that points here
350 * name IN/OUT - IN/name requested, OUT/name found
351 * length IN/OUT - length of IN/OUT oid's
352 * exact IN - TRUE if an exact match was requested
353 * var_len OUT - length of variable or 0 if function returned
354 * write_method
355 *
356 */
357 #if !defined (WIN32) && !defined (cygwin)
358 static int
header_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)359 header_ifEntry(struct variable *vp,
360 oid * name,
361 size_t * length,
362 int exact, size_t * var_len, WriteMethod ** write_method)
363 {
364 #define IFENTRY_NAME_LENGTH 10
365 oid newname[MAX_OID_LEN];
366 register int interface;
367 int result, count;
368
369 DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
370 DEBUGMSGOID(("mibII/interfaces", name, *length));
371 DEBUGMSG(("mibII/interfaces", " %d\n", exact));
372
373 memcpy((char *) newname, (char *) vp->name,
374 (int) vp->namelen * sizeof(oid));
375 /*
376 * find "next" interface
377 */
378 count = Interface_Scan_Get_Count();
379 for (interface = 1; interface <= count; interface++) {
380 newname[IFENTRY_NAME_LENGTH] = (oid) interface;
381 result =
382 snmp_oid_compare(name, *length, newname,
383 (int) vp->namelen + 1);
384 if ((exact && (result == 0)) || (!exact && (result < 0)))
385 break;
386 }
387 if (interface > count) {
388 DEBUGMSGTL(("mibII/interfaces", "... index out of range\n"));
389 return MATCH_FAILED;
390 }
391
392
393 memcpy((char *) name, (char *) newname,
394 ((int) vp->namelen + 1) * sizeof(oid));
395 *length = vp->namelen + 1;
396 *write_method = 0;
397 *var_len = sizeof(long); /* default to 'long' results */
398
399 DEBUGMSGTL(("mibII/interfaces", "... get I/F stats "));
400 DEBUGMSGOID(("mibII/interfaces", name, *length));
401 DEBUGMSG(("mibII/interfaces", "\n"));
402
403 return interface;
404 }
405
406
407
408 u_char *
var_interfaces(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)409 var_interfaces(struct variable * vp,
410 oid * name,
411 size_t * length,
412 int exact, size_t * var_len, WriteMethod ** write_method)
413 {
414 if (header_generic(vp, name, length, exact, var_len, write_method) ==
415 MATCH_FAILED)
416 return NULL;
417
418 switch (vp->magic) {
419 case NETSNMP_IFNUMBER:
420 long_return = Interface_Scan_Get_Count();
421 return (u_char *) & long_return;
422 default:
423 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_interfaces\n",
424 vp->magic));
425 }
426 return NULL;
427 }
428
429 #ifdef USE_SYSCTL_IFLIST
430
431 static u_char *if_list = 0;
432 static const u_char *if_list_end;
433 static size_t if_list_size = 0;
434
435 struct small_ifaddr {
436 struct in_addr sifa_addr;
437 struct in_addr sifa_netmask;
438 struct in_addr sifa_broadcast;
439 };
440
441 static int Interface_Scan_By_Index(int, struct if_msghdr *, char *,
442 struct small_ifaddr *);
443 static int Interface_Get_Ether_By_Index(int, u_char *);
444
445 static int
Interface_Scan_By_Index(int iindex,struct if_msghdr * if_msg,char * if_name,struct small_ifaddr * sifa)446 Interface_Scan_By_Index(int iindex,
447 struct if_msghdr *if_msg,
448 char *if_name, struct small_ifaddr *sifa)
449 {
450 u_char *cp;
451 struct if_msghdr *ifp;
452 int have_ifinfo = 0, have_addr = 0;
453
454 if (NULL != sifa)
455 memset(sifa, 0, sizeof(*sifa));
456 for (cp = if_list; cp < if_list_end; cp += ifp->ifm_msglen) {
457 ifp = (struct if_msghdr *) cp;
458 DEBUGMSGTL(("mibII/interfaces", "ifm_type = %d, ifm_index = %d\n",
459 ifp->ifm_type, ifp->ifm_index));
460
461 switch (ifp->ifm_type) {
462 case RTM_IFINFO:
463 {
464 const struct sockaddr *a;
465
466 if (ifp->ifm_index == iindex) {
467 a = get_address(ifp + 1, ifp->ifm_addrs, RTA_IFP);
468 if (a == NULL)
469 return 0;
470 sprintf(if_name, "%.*s", ((const u_char *) a)[5],
471 ((const struct sockaddr_in *) a)->sin_zero);
472 *if_msg = *ifp;
473 ++have_ifinfo;
474 }
475 }
476 break;
477 case RTM_NEWADDR:
478 {
479 struct ifa_msghdr *ifap = (struct ifa_msghdr *) cp;
480
481 if ((NULL != sifa) && (ifap->ifam_index == iindex)) {
482 const struct in_addr *ia;
483
484 /*
485 * I don't know why the normal get_address() doesn't
486 * work on IRIX 6.2. Maybe this has to do with the
487 * existence of struct sockaddr_new. Hopefully, on
488 * other systems we can simply use get_in_address
489 * three times, with (ifap+1) as the starting
490 * address.
491 */
492
493 sifa->sifa_netmask =
494 *((struct in_addr *) ((char *) (ifap + 1) + 4));
495 ia = get_in_address((char *) (ifap + 1) + 8,
496 ifap->ifam_addrs &=
497 ~RTA_NETMASK, RTA_IFA);
498 if (ia == NULL)
499 return 0;
500
501 sifa->sifa_addr = *ia;
502 ia = get_in_address((char *) (ifap + 1) + 8,
503 ifap->ifam_addrs &= ~RTA_NETMASK,
504 RTA_BRD);
505 if (ia == NULL)
506 return 0;
507
508 sifa->sifa_broadcast = *ia;
509 ++have_addr;
510 }
511 }
512 break;
513 default:
514 DEBUGMSGTL(("mibII/interfaces",
515 "routing socket: unknown message type %d\n",
516 ifp->ifm_type));
517 }
518 }
519 if (have_ifinfo && (NULL == sifa) || (have_addr)) {
520 return 0;
521 } else if (have_ifinfo && !(if_msg->ifm_flags & IFF_UP))
522 return 0;
523 else {
524 return -1;
525 }
526 }
527
528 int
Interface_Scan_Get_Count(void)529 Interface_Scan_Get_Count(void)
530 {
531 u_char *cp;
532 struct if_msghdr *ifp;
533 long n = 0;
534
535 Interface_Scan_Init();
536
537 if (if_list_size) {
538 for (cp = if_list, n = 0; cp < if_list_end; cp += ifp->ifm_msglen) {
539 ifp = (struct if_msghdr *) cp;
540
541 if (ifp->ifm_type == RTM_IFINFO) {
542 ++n;
543 }
544 }
545 }
546 return n;
547 }
548
549 void
Interface_Scan_Init(void)550 Interface_Scan_Init(void)
551 {
552 int name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
553 size_t size;
554
555 if (sysctl(name, sizeof(name) / sizeof(int), 0, &size, 0, 0) == -1) {
556 snmp_log(LOG_ERR, "sysctl size fail\n");
557 } else {
558 if (if_list == 0 || if_list_size < size) {
559 if (if_list != 0) {
560 free(if_list);
561 }
562 if_list = NULL;
563 if_list_size = 0;
564 if_list_end = 0;
565 if ((if_list = malloc(size)) == NULL) {
566 snmp_log(LOG_ERR,
567 "out of memory allocating route table (size = %d)\n", size);
568 return;
569 }
570 if_list_size = size;
571 } else {
572 size = if_list_size;
573 }
574 if (sysctl(name, sizeof(name) / sizeof(int),
575 if_list, &size, 0, 0) == -1) {
576 snmp_log(LOG_ERR, "sysctl get fail\n");
577 }
578 if_list_end = if_list + size;
579 }
580 }
581
582 u_char *
var_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)583 var_ifEntry(struct variable *vp,
584 oid * name,
585 size_t * length,
586 int exact, size_t * var_len, WriteMethod ** write_method)
587 {
588 int interface;
589 struct if_msghdr if_msg;
590 static char if_name[100];
591 conf_if_list *if_ptr;
592 char *cp;
593
594 interface =
595 header_ifEntry(vp, name, length, exact, var_len, write_method);
596 if (interface == MATCH_FAILED)
597 return NULL;
598
599 if (Interface_Scan_By_Index(interface, &if_msg, if_name, NULL) != 0)
600 return NULL;
601 if_ptr = netsnmp_access_interface_entry_overrides_get(if_name);
602
603 switch (vp->magic) {
604 case NETSNMP_IFINDEX:
605 long_return = interface;
606 return (u_char *) & long_return;
607 case NETSNMP_IFDESCR:
608 cp = if_name;
609 *var_len = strlen(if_name);
610 return (u_char *) cp;
611 case NETSNMP_IFTYPE:
612 if (if_ptr)
613 long_return = if_ptr->type;
614 else
615 long_return = (long) if_msg.ifm_data.ifi_type;
616 return (u_char *) & long_return;
617 case NETSNMP_IFMTU:
618 long_return = (long) if_msg.ifm_data.ifi_mtu;
619 return (u_char *) & long_return;
620 case NETSNMP_IFSPEED:
621 if (if_ptr)
622 long_return = if_ptr->speed;
623 else {
624 #if HAVE_STRUCT_IFNET_IF_BAUDRATE_IFS_VALUE
625 long_return = (u_long) if_msg.ifm_data.ifi_baudrate.ifs_value <<
626 if_msg.ifm_data.ifi_baudrate.ifs_log2;
627 #else
628 long_return = (u_long) if_msg.ifm_data.ifi_baudrate;
629 #endif
630 }
631 return (u_char *) & long_return;
632 case NETSNMP_IFPHYSADDRESS:
633 /*
634 * XXX
635 */
636 return NULL;
637 case NETSNMP_IFADMINSTATUS:
638 long_return = if_msg.ifm_flags & IFF_UP ? 1 : 2;
639 return (u_char *) & long_return;
640 case NETSNMP_IFOPERSTATUS:
641 long_return = if_msg.ifm_flags & IFF_RUNNING ? 1 : 2;
642 return (u_char *) & long_return;
643 /*
644 * ifLastChange
645 */
646 case NETSNMP_IFINOCTETS:
647 long_return = (u_long) if_msg.ifm_data.ifi_ibytes;
648 return (u_char *) & long_return;
649 case NETSNMP_IFINUCASTPKTS:
650 long_return =
651 (u_long) if_msg.ifm_data.ifi_ipackets -
652 if_msg.ifm_data.ifi_imcasts;
653 return (u_char *) & long_return;
654 case NETSNMP_IFINNUCASTPKTS:
655 long_return = (u_long) if_msg.ifm_data.ifi_imcasts;
656 return (u_char *) & long_return;
657 case NETSNMP_IFINDISCARDS:
658 long_return = (u_long) if_msg.ifm_data.ifi_iqdrops;
659 return (u_char *) & long_return;
660 case NETSNMP_IFINERRORS:
661 long_return = (u_long) if_msg.ifm_data.ifi_ierrors;
662 return (u_char *) & long_return;
663 case NETSNMP_IFINUNKNOWNPROTOS:
664 long_return = (u_long) if_msg.ifm_data.ifi_noproto;
665 return (u_char *) & long_return;
666 case NETSNMP_IFOUTOCTETS:
667 long_return = (u_long) if_msg.ifm_data.ifi_obytes;
668 return (u_char *) & long_return;
669 case NETSNMP_IFOUTUCASTPKTS:
670 long_return =
671 (u_long) if_msg.ifm_data.ifi_opackets -
672 if_msg.ifm_data.ifi_omcasts;
673 return (u_char *) & long_return;
674 case NETSNMP_IFOUTNUCASTPKTS:
675 long_return = (u_long) if_msg.ifm_data.ifi_omcasts;
676 return (u_char *) & long_return;
677 case NETSNMP_IFOUTDISCARDS:
678 #ifdef if_odrops
679 long_return = (u_long) if_msg.ifm_data.ifi_odrops;
680 #else
681 #if NETSNMP_NO_DUMMY_VALUES
682 return NULL;
683 #endif
684 long_return = 0;
685 #endif
686 return (u_char *) & long_return;
687 case NETSNMP_IFOUTERRORS:
688 long_return = (u_long) if_msg.ifm_data.ifi_oerrors;
689 return (u_char *) & long_return;
690 case NETSNMP_IFLASTCHANGE:
691 #ifdef irix6
692 long_return = 0;
693 #else
694 if (if_msg.ifm_data.ifi_lastchange.tv_sec == 0 &&
695 #if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_NSEC
696 if_msg.ifm_data.ifi_lastchange.tv_nsec == 0
697 #else
698 if_msg.ifm_data.ifi_lastchange.tv_usec == 0
699 #endif
700 )
701 long_return = 0;
702 else if (if_msg.ifm_data.ifi_lastchange.tv_sec < starttime.tv_sec)
703 long_return = 0;
704 else {
705 long_return = (u_long)
706 ((if_msg.ifm_data.ifi_lastchange.tv_sec -
707 starttime.tv_sec) * 100 +
708 (
709 #if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_NSEC
710 if_msg.ifm_data.ifi_lastchange.tv_nsec / 1000
711 #else
712 if_msg.ifm_data.ifi_lastchange.tv_usec
713 #endif
714 - starttime.tv_usec) / 10000);
715 }
716 #endif
717 return (u_char *) & long_return;
718 default:
719 return 0;
720 }
721 }
722
723 int
Interface_Scan_Next(short * Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * Retin_ifaddr)724 Interface_Scan_Next(short *Index,
725 char *Name,
726 struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
727 {
728 return 0;
729 }
730
731 int
Interface_Scan_NextInt(int * Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * Retin_ifaddr)732 Interface_Scan_NextInt(int *Index,
733 char *Name,
734 struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
735 {
736 return 0;
737 }
738
739 #else /* not USE_SYSCTL_IFLIST */
740
741 /*********************
742 *
743 * Kernel & interface information,
744 * and internal forward declarations
745 *
746 *********************/
747
748 #ifndef HAVE_NET_IF_MIB_H
749
750 #ifndef solaris2
751 #ifndef hpux11
752 static int Interface_Scan_By_Index(int, char *, struct ifnet *,
753 struct in_ifaddr *);
754 static int Interface_Get_Ether_By_Index(int, u_char *);
755 #else
756 static int Interface_Scan_By_Index(int, char *, nmapi_phystat *);
757 #endif
758 #endif
759
760
761
762 /*********************
763 *
764 * System specific implementation functions
765 *
766 *********************/
767
768
769 #ifndef solaris2
770 #ifndef hpux
771
772 u_char *
var_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)773 var_ifEntry(struct variable *vp,
774 oid * name,
775 size_t * length,
776 int exact, size_t * var_len, WriteMethod ** write_method)
777 {
778 static struct ifnet ifnet;
779 int interface;
780 static struct in_ifaddr in_ifaddr;
781 static char Name[16];
782 char *cp;
783 conf_if_list *if_ptr;
784
785 interface =
786 header_ifEntry(vp, name, length, exact, var_len, write_method);
787 if (interface == MATCH_FAILED)
788 return NULL;
789
790 Interface_Scan_By_Index(interface, Name, &ifnet, &in_ifaddr);
791 if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
792
793 switch (vp->magic) {
794 case NETSNMP_IFINDEX:
795 long_return = interface;
796 return (u_char *) & long_return;
797 case NETSNMP_IFDESCR:
798 cp = Name;
799 *var_len = strlen(cp);
800 return (u_char *) cp;
801 case NETSNMP_IFTYPE:
802 if (if_ptr)
803 long_return = if_ptr->type;
804 else {
805 #if HAVE_STRUCT_IFNET_IF_TYPE
806 long_return = ifnet.if_type;
807 #else
808 long_return = 1; /* OTHER */
809 #endif
810 }
811 return (u_char *) & long_return;
812 case NETSNMP_IFMTU:{
813 long_return = (long) ifnet.if_mtu;
814 return (u_char *) & long_return;
815 }
816 case NETSNMP_IFSPEED:
817 if (if_ptr)
818 long_return = if_ptr->speed;
819 else {
820 #if HAVE_STRUCT_IFNET_IF_BAUDRATE
821 long_return = ifnet.if_baudrate;
822 #elif HAVE_STRUCT_IFNET_IF_SPEED
823 long_return = ifnet.if_speed;
824 #elif HAVE_STRUCT_IFNET_IF_TYPE && defined(IFT_ETHER)
825 if (ifnet.if_type == IFT_ETHER)
826 long_return = 10000000;
827 if (ifnet.if_type == IFT_P10)
828 long_return = 10000000;
829 if (ifnet.if_type == IFT_P80)
830 long_return = 80000000;
831 if (ifnet.if_type == IFT_ISDNBASIC)
832 long_return = 64000; /* EDSS1 only */
833 if (ifnet.if_type == IFT_ISDNPRIMARY)
834 long_return = 64000 * 30;
835 #else
836 #if NETSNMP_NO_DUMMY_VALUES
837 return NULL;
838 #endif
839 long_return = (u_long) 10000000;
840 #endif
841 }
842 return (u_char *) & long_return;
843 case NETSNMP_IFPHYSADDRESS:
844 Interface_Get_Ether_By_Index(interface, return_buf);
845 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
846 *var_len = 0;
847 #else
848 if ((return_buf[0] == 0) && (return_buf[1] == 0) &&
849 (return_buf[2] == 0) && (return_buf[3] == 0) &&
850 (return_buf[4] == 0) && (return_buf[5] == 0))
851 *var_len = 0;
852 else
853 *var_len = 6;
854 #endif
855 return (u_char *) return_buf;
856 case NETSNMP_IFADMINSTATUS:
857 long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
858 return (u_char *) & long_return;
859 case NETSNMP_IFOPERSTATUS:
860 long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
861 return (u_char *) & long_return;
862 case NETSNMP_IFLASTCHANGE:
863 #if defined(HAVE_STRUCT_IFNET_IF_LASTCHANGE_TV_SEC) && !(defined(freebsd2) && __FreeBSD_version < 199607)
864 /*
865 * XXX - SNMP's ifLastchange is time when op. status changed
866 * * FreeBSD's if_lastchange is time when packet was input or output
867 * * (at least in 2.1.0-RELEASE. Changed in later versions of the kernel?)
868 */
869 /*
870 * FreeBSD's if_lastchange before the 2.1.5 release is the time when
871 * * a packet was last input or output. In the 2.1.5 and later releases,
872 * * this is fixed, thus the 199607 comparison.
873 */
874 if (ifnet.if_lastchange.tv_sec == 0 &&
875 ifnet.if_lastchange.tv_usec == 0)
876 long_return = 0;
877 else if (ifnet.if_lastchange.tv_sec < starttime.tv_sec)
878 long_return = 0;
879 else {
880 long_return = (u_long)
881 ((ifnet.if_lastchange.tv_sec - starttime.tv_sec) * 100
882 + (ifnet.if_lastchange.tv_usec -
883 starttime.tv_usec) / 10000);
884 }
885 #else
886 #if NETSNMP_NO_DUMMY_VALUES
887 return NULL;
888 #endif
889 long_return = 0; /* XXX */
890 #endif
891 return (u_char *) & long_return;
892 case NETSNMP_IFINOCTETS:
893 #ifdef HAVE_STRUCT_IFNET_IF_IBYTES
894 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
895 long_return = (u_long) ifnet.if_ibytes & 0xffffffff;
896 #else
897 long_return = (u_long) ifnet.if_ibytes;
898 #endif
899 #else
900 #if NETSNMP_NO_DUMMY_VALUES
901 return NULL;
902 #endif
903 long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
904 #endif
905 return (u_char *) & long_return;
906 case NETSNMP_IFINUCASTPKTS:
907 {
908 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
909 long_return = (u_long) ifnet.if_ipackets & 0xffffffff;
910 #else
911 long_return = (u_long) ifnet.if_ipackets;
912 #endif
913 #if HAVE_STRUCT_IFNET_IF_IMCASTS
914 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
915 long_return -= (u_long) ifnet.if_imcasts & 0xffffffff;
916 #else
917 long_return -= (u_long) ifnet.if_imcasts;
918 #endif
919 #endif
920 }
921 return (u_char *) & long_return;
922 case NETSNMP_IFINNUCASTPKTS:
923 #if HAVE_STRUCT_IFNET_IF_IMCASTS
924 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
925 long_return = (u_long) ifnet.if_imcasts & 0xffffffff;
926 #else
927 long_return = (u_long) ifnet.if_imcasts;
928 #endif
929 #else
930 #if NETSNMP_NO_DUMMY_VALUES
931 return NULL;
932 #endif
933 long_return = (u_long) 0; /* XXX */
934 #endif
935 return (u_char *) & long_return;
936 case NETSNMP_IFINDISCARDS:
937 #if HAVE_STRUCT_IFNET_IF_IQDROPS
938 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
939 long_return = (u_long) ifnet.if_iqdrops & 0xffffffff;
940 #else
941 long_return = (u_long) ifnet.if_iqdrops;
942 #endif
943 #else
944 #if NETSNMP_NO_DUMMY_VALUES
945 return NULL;
946 #endif
947 long_return = (u_long) 0; /* XXX */
948 #endif
949 return (u_char *) & long_return;
950 case NETSNMP_IFINERRORS:
951 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
952 long_return = (u_long) ifnet.if_ierrors & 0xffffffff;
953 #else
954 long_return = (u_long) ifnet.if_ierrors;
955 #endif
956 return (u_char *) & long_return;
957 case NETSNMP_IFINUNKNOWNPROTOS:
958 #if HAVE_STRUCT_IFNET_IF_NOPROTO
959 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
960 long_return = (u_long) ifnet.if_noproto & 0xffffffff;
961 #else
962 long_return = (u_long) ifnet.if_noproto;
963 #endif
964 #else
965 #if NETSNMP_NO_DUMMY_VALUES
966 return NULL;
967 #endif
968 long_return = (u_long) 0; /* XXX */
969 #endif
970 return (u_char *) & long_return;
971 case NETSNMP_IFOUTOCTETS:
972 #ifdef HAVE_STRUCT_IFNET_IF_OBYTES
973 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
974 long_return = (u_long) ifnet.if_obytes & 0xffffffff;
975 #else
976 long_return = (u_long) ifnet.if_obytes;
977 #endif
978 #else
979 #if NETSNMP_NO_DUMMY_VALUES
980 return NULL;
981 #endif
982 long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
983 #endif
984 return (u_char *) & long_return;
985 case NETSNMP_IFOUTUCASTPKTS:
986 {
987 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
988 long_return = (u_long) ifnet.if_opackets & 0xffffffff;
989 #else
990 long_return = (u_long) ifnet.if_opackets;
991 #endif
992 #if HAVE_STRUCT_IFNET_IF_OMCASTS
993 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
994 long_return -= (u_long) ifnet.if_omcasts & 0xffffffff;
995 #else
996 long_return -= (u_long) ifnet.if_omcasts;
997 #endif
998 #endif
999 }
1000 return (u_char *) & long_return;
1001 case NETSNMP_IFOUTNUCASTPKTS:
1002 #if HAVE_STRUCT_IFNET_IF_OMCASTS
1003 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
1004 long_return = (u_long) ifnet.if_omcasts & 0xffffffff;
1005 #else
1006 long_return = (u_long) ifnet.if_omcasts;
1007 #endif
1008 #else
1009 #if NETSNMP_NO_DUMMY_VALUES
1010 return NULL;
1011 #endif
1012 long_return = (u_long) 0; /* XXX */
1013 #endif
1014 return (u_char *) & long_return;
1015 case NETSNMP_IFOUTDISCARDS:
1016 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
1017 long_return = ifnet.if_snd.ifq_drops & 0xffffffff;
1018 #else
1019 long_return = ifnet.if_snd.ifq_drops;
1020 #endif
1021 return (u_char *) & long_return;
1022 case NETSNMP_IFOUTERRORS:
1023 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
1024 long_return = ifnet.if_oerrors & 0xffffffff;
1025 #else
1026 long_return = ifnet.if_oerrors;
1027 #endif
1028 return (u_char *) & long_return;
1029 case NETSNMP_IFOUTQLEN:
1030 #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7)
1031 long_return = ifnet.if_snd.ifq_len & 0xffffffff;
1032 #else
1033 long_return = ifnet.if_snd.ifq_len;
1034 #endif
1035 return (u_char *) & long_return;
1036 case NETSNMP_IFSPECIFIC:
1037 *var_len = nullOidLen;
1038 return (u_char *) nullOid;
1039 default:
1040 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
1041 vp->magic));
1042 }
1043 return NULL;
1044 }
1045
1046 #else /* hpux */
1047
1048 u_char *
var_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)1049 var_ifEntry(struct variable *vp,
1050 oid * name,
1051 size_t * length,
1052 int exact, size_t * var_len, WriteMethod ** write_method)
1053 {
1054 #if defined(hpux11)
1055 static nmapi_phystat ifnet;
1056 #else
1057 static struct ifnet ifnet;
1058 #endif
1059 register int interface;
1060 #if !defined(hpux11)
1061 static struct in_ifaddr in_ifaddrVar;
1062 #endif
1063 #if defined(hpux11)
1064 static char Name[MAX_PHYSADDR_LEN];
1065 #else
1066 static char Name[16];
1067 #endif
1068 register char *cp;
1069 #if HAVE_STRUCT_IFNET_IF_LASTCHANGE_TV_SEC
1070 struct timeval now;
1071 #endif
1072 #if !defined(hpux11)
1073 struct nmparms hp_nmparms;
1074 static mib_ifEntry hp_ifEntry;
1075 int hp_fd;
1076 int hp_len = sizeof(hp_ifEntry);
1077 #endif
1078 conf_if_list *if_ptr;
1079
1080 interface =
1081 header_ifEntry(vp, name, length, exact, var_len, write_method);
1082 if (interface == MATCH_FAILED)
1083 return NULL;
1084
1085 #if defined(hpux11)
1086 Interface_Scan_By_Index(interface, Name, &ifnet);
1087 #else
1088 Interface_Scan_By_Index(interface, Name, &ifnet, &in_ifaddrVar);
1089 #endif
1090
1091 #if !defined(hpux11)
1092 /*
1093 * Additional information about the interfaces is available under
1094 * HP-UX through the network management interface '/dev/netman'
1095 */
1096 hp_ifEntry.ifIndex = interface;
1097 hp_nmparms.objid = ID_ifEntry;
1098 hp_nmparms.buffer = (char *) &hp_ifEntry;
1099 hp_nmparms.len = &hp_len;
1100 if ((hp_fd = open("/dev/netman", O_RDONLY)) != -1) {
1101 if (ioctl(hp_fd, NMIOGET, &hp_nmparms) != -1) {
1102 close(hp_fd);
1103 } else {
1104 close(hp_fd);
1105 hp_fd = -1; /* failed */
1106 }
1107 }
1108 #endif
1109 if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
1110
1111 switch (vp->magic) {
1112 case NETSNMP_IFINDEX:
1113 long_return = interface;
1114 return (u_char *) & long_return;
1115 case NETSNMP_IFDESCR:
1116 #if defined(hpux11)
1117 cp = ifnet.if_entry.ifDescr;
1118 #else
1119 if (hp_fd != -1)
1120 cp = hp_ifEntry.ifDescr;
1121 else
1122 cp = Name;
1123 #endif
1124 *var_len = strlen(cp);
1125 return (u_char *) cp;
1126 case NETSNMP_IFTYPE:
1127 if (if_ptr)
1128 long_return = if_ptr->type;
1129 else {
1130 #if defined(hpux11)
1131 long_return = ifnet.if_entry.ifType;
1132 #else
1133 if (hp_fd != -1)
1134 long_return = hp_ifEntry.ifType;
1135 else
1136 long_return = 1; /* OTHER */
1137 #endif
1138 }
1139 return (u_char *) & long_return;
1140 case NETSNMP_IFMTU:{
1141 #if defined(hpux11)
1142 long_return = (long) ifnet.if_entry.ifMtu;
1143 #else
1144 long_return = (long) ifnet.if_mtu;
1145 #endif
1146 return (u_char *) & long_return;
1147 }
1148 case NETSNMP_IFSPEED:
1149 if (if_ptr)
1150 long_return = if_ptr->speed;
1151 else {
1152 #if defined(hpux11)
1153 long_return = ifnet.if_entry.ifSpeed;
1154 #else
1155 if (hp_fd != -1)
1156 long_return = hp_ifEntry.ifSpeed;
1157 else
1158 long_return = (u_long) 1; /* OTHER */
1159 #endif
1160 }
1161 return (u_char *) & long_return;
1162 case NETSNMP_IFPHYSADDRESS:
1163 #if defined(hpux11)
1164 *var_len = ifnet.if_entry.ifPhysAddress.o_length;
1165 return (u_char *) ifnet.if_entry.ifPhysAddress.o_bytes;
1166 #else
1167 Interface_Get_Ether_By_Index(interface, return_buf);
1168 if ((return_buf[0] == 0) && (return_buf[1] == 0) &&
1169 (return_buf[2] == 0) && (return_buf[3] == 0) &&
1170 (return_buf[4] == 0) && (return_buf[5] == 0))
1171 *var_len = 0;
1172 else
1173 *var_len = 6;
1174 return (u_char *) return_buf;
1175 #endif
1176 case NETSNMP_IFADMINSTATUS:
1177 #if defined(hpux11)
1178 long_return = ifnet.if_entry.ifAdmin;
1179 #else
1180 long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
1181 #endif
1182 return (u_char *) & long_return;
1183 case NETSNMP_IFOPERSTATUS:
1184 #if defined(hpux11)
1185 long_return = ifnet.if_entry.ifOper;
1186 #else
1187 long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
1188 #endif
1189 return (u_char *) & long_return;
1190 case NETSNMP_IFLASTCHANGE:
1191 #if defined(hpux11)
1192 long_return = ifnet.if_entry.ifLastChange;
1193 #else
1194 if (hp_fd != -1)
1195 long_return = hp_ifEntry.ifLastChange;
1196 else
1197 long_return = 0; /* XXX */
1198 #endif
1199 return (u_char *) & long_return;
1200 case NETSNMP_IFINOCTETS:
1201 #if defined(hpux11)
1202 long_return = ifnet.if_entry.ifInOctets;
1203 #else
1204 if (hp_fd != -1)
1205 long_return = hp_ifEntry.ifInOctets;
1206 else
1207 long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
1208 #endif
1209 return (u_char *) & long_return;
1210 case NETSNMP_IFINUCASTPKTS:
1211 #if defined(hpux11)
1212 long_return = ifnet.if_entry.ifInUcastPkts;
1213 #else
1214 if (hp_fd != -1)
1215 long_return = hp_ifEntry.ifInUcastPkts;
1216 else
1217 long_return = (u_long) ifnet.if_ipackets;
1218 #endif
1219 return (u_char *) & long_return;
1220 case NETSNMP_IFINNUCASTPKTS:
1221 #if defined(hpux11)
1222 long_return = ifnet.if_entry.ifInNUcastPkts;
1223 #else
1224 if (hp_fd != -1)
1225 long_return = hp_ifEntry.ifInNUcastPkts;
1226 else
1227 long_return = (u_long) 0; /* XXX */
1228 #endif
1229 return (u_char *) & long_return;
1230 case NETSNMP_IFINDISCARDS:
1231 #if defined(hpux11)
1232 long_return = ifnet.if_entry.ifInDiscards;
1233 #else
1234 if (hp_fd != -1)
1235 long_return = hp_ifEntry.ifInDiscards;
1236 else
1237 long_return = (u_long) 0; /* XXX */
1238 #endif
1239 return (u_char *) & long_return;
1240 case NETSNMP_IFINERRORS:
1241 #if defined(hpux11)
1242 long_return = ifnet.if_entry.ifInErrors;
1243 #else
1244 long_return = ifnet.if_ierrors;
1245 #endif
1246 return (u_char *) & long_return;
1247 case NETSNMP_IFINUNKNOWNPROTOS:
1248 #if defined(hpux11)
1249 long_return = ifnet.if_entry.ifInUnknownProtos;
1250 #else
1251 if (hp_fd != -1)
1252 long_return = hp_ifEntry.ifInUnknownProtos;
1253 else
1254 long_return = (u_long) 0; /* XXX */
1255 #endif
1256 return (u_char *) & long_return;
1257 case NETSNMP_IFOUTOCTETS:
1258 #if defined(hpux11)
1259 long_return = ifnet.if_entry.ifOutOctets;
1260 #else
1261 if (hp_fd != -1)
1262 long_return = hp_ifEntry.ifOutOctets;
1263 else
1264 long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
1265 #endif
1266 return (u_char *) & long_return;
1267 case NETSNMP_IFOUTUCASTPKTS:
1268 #if defined(hpux11)
1269 long_return = ifnet.if_entry.ifOutUcastPkts;
1270 #else
1271 if (hp_fd != -1)
1272 long_return = hp_ifEntry.ifOutUcastPkts;
1273 else
1274 long_return = (u_long) ifnet.if_opackets;
1275 #endif
1276 return (u_char *) & long_return;
1277 case NETSNMP_IFOUTNUCASTPKTS:
1278 #if defined(hpux11)
1279 long_return = ifnet.if_entry.ifOutNUcastPkts;
1280 #else
1281 if (hp_fd != -1)
1282 long_return = hp_ifEntry.ifOutNUcastPkts;
1283 else
1284 long_return = (u_long) 0; /* XXX */
1285 #endif
1286 return (u_char *) & long_return;
1287 case NETSNMP_IFOUTDISCARDS:
1288 #if defined(hpux11)
1289 long_return = ifnet.if_entry.ifOutDiscards;
1290 #else
1291 long_return = ifnet.if_snd.ifq_drops;
1292 #endif
1293 return (u_char *) & long_return;
1294 case NETSNMP_IFOUTERRORS:
1295 #if defined(hpux11)
1296 long_return = ifnet.if_entry.ifOutErrors;
1297 #else
1298 long_return = ifnet.if_oerrors;
1299 #endif
1300 return (u_char *) & long_return;
1301 case NETSNMP_IFOUTQLEN:
1302 #if defined(hpux11)
1303 long_return = ifnet.if_entry.ifOutQlen;
1304 #else
1305 long_return = ifnet.if_snd.ifq_len;
1306 #endif
1307 return (u_char *) & long_return;
1308 case NETSNMP_IFSPECIFIC:
1309 *var_len = nullOidLen;
1310 return (u_char *) nullOid;
1311 default:
1312 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
1313 vp->magic));
1314 }
1315 return NULL;
1316 }
1317
1318 #endif /* hpux */
1319 #else /* solaris2 */
1320
1321 static int
IF_cmp(void * addr,void * ep)1322 IF_cmp(void *addr, void *ep)
1323 {
1324 DEBUGMSGTL(("mibII/interfaces", "... IF_cmp %d %d\n",
1325 ((mib2_ifEntry_t *) ep)->ifIndex,
1326 ((mib2_ifEntry_t *) addr)->ifIndex));
1327 if (((mib2_ifEntry_t *) ep)->ifIndex ==
1328 ((mib2_ifEntry_t *) addr)->ifIndex)
1329 return (0);
1330 else
1331 return (1);
1332 }
1333
1334 u_char *
var_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)1335 var_ifEntry(struct variable * vp,
1336 oid * name,
1337 size_t * length,
1338 int exact, size_t * var_len, WriteMethod ** write_method)
1339 {
1340 int interface;
1341 mib2_ifEntry_t ifstat;
1342 conf_if_list *if_ptr = NULL;
1343
1344 interface =
1345 header_ifEntry(vp, name, length, exact, var_len, write_method);
1346 if (interface == MATCH_FAILED)
1347 return NULL;
1348
1349 if (getMibstat(MIB_INTERFACES, &ifstat, sizeof(mib2_ifEntry_t),
1350 GET_EXACT, &IF_cmp, &interface) != 0) {
1351 DEBUGMSGTL(("mibII/interfaces", "... no mib stats\n"));
1352 return NULL;
1353 }
1354 /*
1355 * hmmm.. where to get the interface name to check overrides?
1356 *
1357 * if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
1358 */
1359 switch (vp->magic) {
1360 case NETSNMP_IFINDEX:
1361 long_return = ifstat.ifIndex;
1362 return (u_char *) & long_return;
1363 case NETSNMP_IFDESCR:
1364 *var_len = ifstat.ifDescr.o_length;
1365 (void) memcpy(return_buf, ifstat.ifDescr.o_bytes, *var_len);
1366 return (u_char *) return_buf;
1367 case NETSNMP_IFTYPE:
1368 if (if_ptr)
1369 long_return = if_ptr->type;
1370 else
1371 long_return = (u_long) ifstat.ifType;
1372 return (u_char *) & long_return;
1373 case NETSNMP_IFMTU:
1374 long_return = (u_long) ifstat.ifMtu;
1375 return (u_char *) & long_return;
1376 case NETSNMP_IFSPEED:
1377 if (if_ptr)
1378 long_return = if_ptr->speed;
1379 else
1380 long_return = (u_long) ifstat.ifSpeed;
1381 return (u_char *) & long_return;
1382 case NETSNMP_IFPHYSADDRESS:
1383 *var_len = ifstat.ifPhysAddress.o_length;
1384 (void) memcpy(return_buf, ifstat.ifPhysAddress.o_bytes, *var_len);
1385 return (u_char *) return_buf;
1386 case NETSNMP_IFADMINSTATUS:
1387 long_return = (u_long) ifstat.ifAdminStatus;
1388 return (u_char *) & long_return;
1389 case NETSNMP_IFOPERSTATUS:
1390 long_return = (u_long) ifstat.ifOperStatus;
1391 return (u_char *) & long_return;
1392 case NETSNMP_IFLASTCHANGE:
1393 long_return = (u_long) ifstat.ifLastChange;
1394 return (u_char *) & long_return;
1395 case NETSNMP_IFINOCTETS:
1396 long_return = (u_long) ifstat.ifInOctets;
1397 return (u_char *) & long_return;
1398 case NETSNMP_IFINUCASTPKTS:
1399 long_return = (u_long) ifstat.ifInUcastPkts;
1400 return (u_char *) & long_return;
1401 case NETSNMP_IFINNUCASTPKTS:
1402 long_return = (u_long) ifstat.ifInNUcastPkts;
1403 return (u_char *) & long_return;
1404 case NETSNMP_IFINDISCARDS:
1405 long_return = (u_long) ifstat.ifInDiscards;
1406 return (u_char *) & long_return;
1407 case NETSNMP_IFINERRORS:
1408 long_return = (u_long) ifstat.ifInErrors;
1409 return (u_char *) & long_return;
1410 case NETSNMP_IFINUNKNOWNPROTOS:
1411 long_return = (u_long) ifstat.ifInUnknownProtos;
1412 return (u_char *) & long_return;
1413 case NETSNMP_IFOUTOCTETS:
1414 long_return = (u_long) ifstat.ifOutOctets;
1415 return (u_char *) & long_return;
1416 case NETSNMP_IFOUTUCASTPKTS:
1417 long_return = (u_long) ifstat.ifOutUcastPkts;
1418 return (u_char *) & long_return;
1419 case NETSNMP_IFOUTNUCASTPKTS:
1420 long_return = (u_long) ifstat.ifOutNUcastPkts;
1421 return (u_char *) & long_return;
1422 case NETSNMP_IFOUTDISCARDS:
1423 long_return = (u_long) ifstat.ifOutDiscards;
1424 return (u_char *) & long_return;
1425 case NETSNMP_IFOUTERRORS:
1426 long_return = (u_long) ifstat.ifOutErrors;
1427 return (u_char *) & long_return;
1428 case NETSNMP_IFOUTQLEN:
1429 long_return = (u_long) ifstat.ifOutQLen;
1430 return (u_char *) & long_return;
1431 case NETSNMP_IFSPECIFIC:
1432 long_return = (u_long) ifstat.ifSpecific;
1433 return (u_char *) & long_return;
1434 default:
1435 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
1436 vp->magic));
1437 }
1438 return NULL;
1439 }
1440
1441 #endif /* solaris2 */
1442
1443
1444
1445 /*********************
1446 *
1447 * Internal implementation functions
1448 *
1449 *********************/
1450
1451
1452 #ifndef solaris2
1453
1454 #if !defined(sunV3) && !defined(linux) && !defined(hpux11)
1455 static struct in_ifaddr savein_ifaddr;
1456 #endif
1457 #if !defined(hpux11)
1458 static struct ifnet *ifnetaddr, saveifnet, *saveifnetaddr;
1459 static char saveName[16];
1460 #endif
1461 static int saveIndex = 0;
1462
1463 /**
1464 * Determines network interface speed. It is system specific. Only linux
1465 * realization is made.
1466 */
getIfSpeed(int fd,struct ifreq ifr,unsigned int defaultspeed)1467 unsigned int getIfSpeed(int fd, struct ifreq ifr, unsigned int defaultspeed)
1468 {
1469 #ifdef linux
1470 return netsnmp_linux_interface_get_if_speed(fd, ifr.ifr_name, defaultspeed);
1471 #else /*!linux*/
1472 return defaultspeed;
1473 #endif
1474 }
1475
1476 void
Interface_Scan_Init(void)1477 Interface_Scan_Init(void)
1478 {
1479 #ifdef linux
1480 char line[256], ifname_buf[64], *ifname, *ptr;
1481 struct ifreq ifrq;
1482 struct ifnet **ifnetaddr_ptr;
1483 FILE *devin;
1484 int i, fd;
1485 conf_if_list *if_ptr;
1486 /*
1487 * scanline_2_2:
1488 * [ IN ]
1489 * byte pkts errs drop fifo frame cmprs mcst |
1490 * [ OUT ]
1491 * byte pkts errs drop fifo colls carrier compressed
1492 */
1493 uintmax_t rec_pkt, rec_oct, rec_err, rec_drop;
1494 uintmax_t snd_pkt, snd_oct, snd_err, snd_drop, coll;
1495 const char *scan_line_2_2 =
1496 "%" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX
1497 " %*" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX
1498 " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX
1499 " %*" SCNuMAX " %" SCNuMAX;
1500 const char *scan_line_2_0 =
1501 "%" SCNuMAX " %" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX
1502 " %*" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %*" SCNuMAX
1503 " %*" SCNuMAX " %" SCNuMAX;
1504 const char *scan_line_to_use;
1505 struct timeval et; /* elapsed time */
1506
1507 #endif
1508
1509 #if !defined(hpux11) && defined(IFNET_SYMBOL)
1510 auto_nlist(IFNET_SYMBOL, (char *) &ifnetaddr, sizeof(ifnetaddr));
1511 #endif
1512 saveIndex = 0;
1513
1514
1515 #ifdef linux
1516 /* disallow reloading of structures too often */
1517 netsnmp_get_monotonic_clock(&et);
1518 if ( et.tv_sec < LastLoad + MINLOADFREQ ) { /* only reload so often */
1519 ifnetaddr = ifnetaddr_list; /* initialize pointer */
1520 return;
1521 }
1522 LastLoad = et.tv_sec;
1523
1524 /*
1525 * free old list:
1526 */
1527 while (ifnetaddr_list) {
1528 struct ifnet *old = ifnetaddr_list;
1529 ifnetaddr_list = ifnetaddr_list->if_next;
1530 free(old->if_name);
1531 free(old->if_unit);
1532 free(old);
1533 }
1534
1535 ifnetaddr = 0;
1536 ifnetaddr_ptr = &ifnetaddr_list;
1537
1538 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1539 DEBUGMSGTL(("snmpd",
1540 "socket open failure in Interface_Scan_Init\n"));
1541 return; /** exit (1); **/
1542 }
1543
1544 /*
1545 * build up ifnetaddr list by hand:
1546 */
1547
1548 /*
1549 * at least linux v1.3.53 says EMFILE without reason...
1550 */
1551 if (!(devin = fopen("/proc/net/dev", "r"))) {
1552 close(fd);
1553 NETSNMP_LOGONCE((LOG_ERR, "cannot open /proc/net/dev.\n"));
1554 return; /** exit (1); **/
1555 }
1556
1557 i = 0;
1558
1559 /*
1560 * read the second line (a header) and determine the fields we
1561 * should read from. This should be done in a better way by
1562 * actually looking for the field names we want. But thats too
1563 * much work for today. -- Wes
1564 */
1565 fgets(line, sizeof(line), devin);
1566 fgets(line, sizeof(line), devin);
1567 if (strstr(line, "compressed")) {
1568 scan_line_to_use = scan_line_2_2;
1569 DEBUGMSGTL(("mibII/interfaces",
1570 "using linux 2.2 kernel /proc/net/dev\n"));
1571 } else {
1572 scan_line_to_use = scan_line_2_0;
1573 DEBUGMSGTL(("mibII/interfaces",
1574 "using linux 2.0 kernel /proc/net/dev\n"));
1575 }
1576
1577
1578 while (fgets(line, sizeof(line), devin)) {
1579 struct ifnet *nnew;
1580 char *stats, *ifstart = line;
1581
1582 if (line[strlen(line) - 1] == '\n')
1583 line[strlen(line) - 1] = '\0';
1584
1585 while (*ifstart && *ifstart == ' ')
1586 ifstart++;
1587
1588 if (!*ifstart || ((stats = strrchr(ifstart, ':')) == NULL)) {
1589 snmp_log(LOG_ERR,
1590 "/proc/net/dev data format error, line ==|%s|", line);
1591 continue;
1592 }
1593 if ((scan_line_to_use == scan_line_2_2) && ((stats - line) < 6)) {
1594 snmp_log(LOG_ERR,
1595 "/proc/net/dev data format error, line ==|%s|", line);
1596 }
1597
1598 *stats = 0;
1599 strlcpy(ifname_buf, ifstart, sizeof(ifname_buf));
1600 *stats++ = ':';
1601 while (*stats == ' ')
1602 stats++;
1603
1604 if ((scan_line_to_use == scan_line_2_2 &&
1605 sscanf(stats, scan_line_to_use, &rec_oct, &rec_pkt, &rec_err,
1606 &rec_drop, &snd_oct, &snd_pkt, &snd_err, &snd_drop,
1607 &coll) != 9) || (scan_line_to_use == scan_line_2_0
1608 && sscanf(stats, scan_line_to_use,
1609 &rec_pkt, &rec_err,
1610 &snd_pkt, &snd_err,
1611 &coll) != 5)) {
1612 if ((scan_line_to_use == scan_line_2_2)
1613 && !strstr(line, "No statistics available"))
1614 snmp_log(LOG_ERR,
1615 "/proc/net/dev data format error, line ==|%s|",
1616 line);
1617 continue;
1618 }
1619
1620 nnew = (struct ifnet *) calloc(1, sizeof(struct ifnet));
1621 if (nnew == NULL)
1622 break; /* alloc error */
1623
1624 /*
1625 * chain in:
1626 */
1627 *ifnetaddr_ptr = nnew;
1628 ifnetaddr_ptr = &nnew->if_next;
1629 i++;
1630
1631 /*
1632 * linux previous to 1.3.~13 may miss transmitted loopback pkts:
1633 */
1634 if (!strcmp(ifname_buf, "lo") && rec_pkt > 0 && !snd_pkt)
1635 snd_pkt = rec_pkt;
1636
1637 nnew->if_ipackets = rec_pkt & 0xffffffff;
1638 nnew->if_ierrors = rec_err;
1639 nnew->if_opackets = snd_pkt & 0xffffffff;
1640 nnew->if_oerrors = snd_err;
1641 nnew->if_collisions = coll;
1642 if (scan_line_to_use == scan_line_2_2) {
1643 nnew->if_ibytes = rec_oct & 0xffffffff;
1644 nnew->if_obytes = snd_oct & 0xffffffff;
1645 nnew->if_iqdrops = rec_drop;
1646 nnew->if_snd.ifq_drops = snd_drop;
1647 } else {
1648 nnew->if_ibytes = (rec_pkt * 308) & 0xffffffff;
1649 nnew->if_obytes = (snd_pkt * 308) & 0xffffffff;
1650 }
1651
1652 /*
1653 * ifnames are given as `` eth0'': split in ``eth'' and ``0'':
1654 */
1655 for (ifname = ifname_buf; *ifname && *ifname == ' '; ifname++);
1656
1657 /*
1658 * set name and interface# :
1659 */
1660 nnew->if_name = (char *) strdup(ifname);
1661 for (ptr = nnew->if_name; *ptr && (*ptr < '0' || *ptr > '9');
1662 ptr++);
1663 nnew->if_unit = strdup(*ptr ? ptr : "");
1664 *ptr = 0;
1665
1666 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1667 if (ioctl(fd, SIOCGIFADDR, &ifrq) < 0)
1668 memset((char *) &nnew->if_addr, 0, sizeof(nnew->if_addr));
1669 else
1670 nnew->if_addr = ifrq.ifr_addr;
1671
1672 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1673 if (ioctl(fd, SIOCGIFBRDADDR, &ifrq) < 0)
1674 memset((char *) &nnew->ifu_broadaddr, 0,
1675 sizeof(nnew->ifu_broadaddr));
1676 else
1677 nnew->ifu_broadaddr = ifrq.ifr_broadaddr;
1678
1679 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1680 if (ioctl(fd, SIOCGIFNETMASK, &ifrq) < 0)
1681 memset((char *) &nnew->ia_subnetmask, 0,
1682 sizeof(nnew->ia_subnetmask));
1683 else
1684 nnew->ia_subnetmask = ifrq.ifr_netmask;
1685
1686 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1687 nnew->if_flags = ioctl(fd, SIOCGIFFLAGS, &ifrq) < 0
1688 ? 0 : ifrq.ifr_flags;
1689
1690 nnew->if_type = 0;
1691
1692 /*
1693 * NOTE: this ioctl does not guarantee 6 bytes of a physaddr.
1694 * In particular, a 'sit0' interface only appears to get back
1695 * 4 bytes of sa_data.
1696 */
1697 memset(ifrq.ifr_hwaddr.sa_data, (0), IFHWADDRLEN);
1698 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1699 if (ioctl(fd, SIOCGIFHWADDR, &ifrq) < 0)
1700 memset(nnew->if_hwaddr, (0), IFHWADDRLEN);
1701 else {
1702 memcpy(nnew->if_hwaddr, ifrq.ifr_hwaddr.sa_data, IFHWADDRLEN);
1703
1704 #ifdef ARPHRD_LOOPBACK
1705 switch (ifrq.ifr_hwaddr.sa_family) {
1706 case ARPHRD_ETHER:
1707 nnew->if_type = 6;
1708 break;
1709 case ARPHRD_TUNNEL:
1710 case ARPHRD_TUNNEL6:
1711 #ifdef ARPHRD_IPGRE
1712 case ARPHRD_IPGRE:
1713 #endif
1714 case ARPHRD_SIT:
1715 nnew->if_type = 131;
1716 break; /* tunnel */
1717 case ARPHRD_SLIP:
1718 case ARPHRD_CSLIP:
1719 case ARPHRD_SLIP6:
1720 case ARPHRD_CSLIP6:
1721 nnew->if_type = 28;
1722 break; /* slip */
1723 case ARPHRD_PPP:
1724 nnew->if_type = 23;
1725 break; /* ppp */
1726 case ARPHRD_LOOPBACK:
1727 nnew->if_type = 24;
1728 break; /* softwareLoopback */
1729 case ARPHRD_FDDI:
1730 nnew->if_type = 15;
1731 break;
1732 case ARPHRD_ARCNET:
1733 nnew->if_type = 35;
1734 break;
1735 case ARPHRD_LOCALTLK:
1736 nnew->if_type = 42;
1737 break;
1738 #ifdef ARPHRD_HIPPI
1739 case ARPHRD_HIPPI:
1740 nnew->if_type = 47;
1741 break;
1742 #endif
1743 #ifdef ARPHRD_ATM
1744 case ARPHRD_ATM:
1745 nnew->if_type = 37;
1746 break;
1747 #endif
1748 /*
1749 * XXX: more if_arp.h:ARPHDR_xxx to IANAifType mappings...
1750 */
1751 }
1752 #endif
1753 }
1754
1755 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1756 nnew->if_metric = ioctl(fd, SIOCGIFMETRIC, &ifrq) < 0
1757 ? 0 : ifrq.ifr_metric;
1758
1759 #ifdef SIOCGIFMTU
1760 strlcpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1761 nnew->if_mtu = (ioctl(fd, SIOCGIFMTU, &ifrq) < 0)
1762 ? 0 : ifrq.ifr_mtu;
1763 #else
1764 nnew->if_mtu = 0;
1765 #endif
1766
1767 if_ptr = netsnmp_access_interface_entry_overrides_get(ifname);
1768 if (if_ptr) {
1769 nnew->if_type = if_ptr->type;
1770 nnew->if_speed = if_ptr->speed;
1771 } else {
1772 /*
1773 * do only guess if_type from name, if we could not read
1774 * * it before from SIOCGIFHWADDR
1775 */
1776 unsigned int defaultspeed = NOMINAL_LINK_SPEED;
1777 if (!(nnew->if_flags & IFF_RUNNING)) {
1778 /*
1779 * use speed 0 if the if speed cannot be determined *and* the
1780 * interface is down
1781 */
1782 defaultspeed = 0;
1783 }
1784
1785 if (!nnew->if_type)
1786 nnew->if_type = if_type_from_name(nnew->if_name);
1787 switch(nnew->if_type) {
1788 case 6:
1789 nnew->if_speed = getIfSpeed(fd, ifrq, defaultspeed);
1790 break;
1791 case 24:
1792 nnew->if_speed = 10000000;
1793 break;
1794 case 9:
1795 nnew->if_speed = 4000000;
1796 break;
1797 default:
1798 nnew->if_speed = 0;
1799 }
1800 /*Zero speed means link problem*/
1801 if(nnew->if_speed == 0 && nnew->if_flags & IFF_UP){
1802 nnew->if_flags &= ~IFF_RUNNING;
1803 }
1804 }
1805
1806 } /* while (fgets ... */
1807
1808 ifnetaddr = ifnetaddr_list;
1809
1810 if (snmp_get_do_debugging()) {
1811 {
1812 struct ifnet *x = ifnetaddr;
1813 DEBUGMSGTL(("mibII/interfaces", "* see: known interfaces:"));
1814 while (x) {
1815 DEBUGMSG(("mibII/interfaces", " %s", x->if_name));
1816 x = x->if_next;
1817 }
1818 DEBUGMSG(("mibII/interfaces", "\n"));
1819 } /* XXX */
1820 }
1821
1822 fclose(devin);
1823 close(fd);
1824 #endif /* linux */
1825 }
1826
1827
1828
1829 #if defined(sunV3) || defined(linux)
1830 /*
1831 * ** 4.2 BSD doesn't have ifaddr
1832 * **
1833 */
1834 int
Interface_Scan_Next(short * Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * dummy)1835 Interface_Scan_Next(short *Index,
1836 char *Name,
1837 struct ifnet *Retifnet, struct in_ifaddr *dummy)
1838 {
1839 int returnIndex = 0;
1840 int ret;
1841 if (Index)
1842 returnIndex = *Index;
1843
1844 ret = Interface_Scan_NextInt( &returnIndex, Name, Retifnet, dummy );
1845 if (Index)
1846 *Index = (returnIndex & 0x8fff);
1847 return ret;
1848 }
1849
1850 int
Interface_Scan_NextInt(int * Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * dummy)1851 Interface_Scan_NextInt(int *Index,
1852 char *Name,
1853 struct ifnet *Retifnet, struct in_ifaddr *dummy)
1854 {
1855 struct ifnet ifnet;
1856 #if !defined(linux)
1857 register char *cp;
1858 #endif
1859
1860 while (ifnetaddr) {
1861 /*
1862 * Get the "ifnet" structure and extract the device name
1863 */
1864 #ifndef linux
1865 if (!NETSNMP_KLOOKUP(ifnetaddr, (char *) &ifnet, sizeof ifnet)) {
1866 DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
1867 break;
1868 }
1869
1870 if (!NETSNMP_KLOOKUP(ifnet.if_name, (char *) saveName, sizeof saveName)) {
1871 DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
1872 break;
1873 }
1874
1875 /*
1876 * The purpose of this comparison is lost in the mists of time.
1877 * It's been around at least cmu-snmp 2.1.2 for SUNv3 systems and
1878 * was applied to linux systems during the cmu-snmp-linux project.
1879 * No-one now knows what it was intended for, and it breaks IPv6
1880 * tunnel interfaces, so it's been moved out of the Linux code block.
1881 */
1882 if (strcmp(saveName, "ip") == 0) {
1883 ifnetaddr = ifnet.if_next;
1884 continue;
1885 }
1886 #else
1887 ifnet = *ifnetaddr;
1888 strlcpy(saveName, ifnet.if_name, sizeof(saveName));
1889 #endif
1890
1891 saveName[sizeof(saveName) - 1] = '\0';
1892 #ifdef linux
1893 strlcat(saveName, ifnet.if_unit, sizeof(saveName));
1894 #else
1895 #ifdef NETSNMP_FEATURE_CHECKIN
1896 /* this exists here just so we don't copy ifdef logic elsewhere */
1897 netsnmp_feature_require(string_append_int);
1898 #endif
1899 cp = (char *) strchr(saveName, '\0');
1900 string_append_int(cp, ifnet.if_unit);
1901 #endif
1902 if (1 || strcmp(saveName, "lo0") != 0) { /* XXX */
1903
1904 if (Index)
1905 *Index = ++saveIndex;
1906 if (Retifnet)
1907 *Retifnet = ifnet;
1908 if (Name)
1909 strcpy(Name, saveName);
1910 saveifnet = ifnet;
1911 saveifnetaddr = ifnetaddr;
1912 ifnetaddr = ifnet.if_next;
1913
1914 return (1); /* DONE */
1915 }
1916 ifnetaddr = ifnet.if_next;
1917 }
1918 return (0); /* EOF */
1919 }
1920
1921 #ifdef linux
1922 int
Interface_Index_By_Name(char * Name,int Len)1923 Interface_Index_By_Name(char *Name, int Len)
1924 {
1925 int ifIndex = 0;
1926 char ifName[20];
1927
1928 Interface_Scan_Init();
1929 while (Interface_Scan_NextInt(&ifIndex, ifName, NULL, NULL)
1930 && strcmp(Name, ifName));
1931 return ifIndex;
1932 }
1933 #endif
1934
1935
1936 #else /* sunV3 || linux */
1937
1938 #if defined(netbsd1) || defined(openbsd2)
1939 #define ia_next ia_list.tqe_next
1940 #define if_next if_list.tqe_next
1941 #endif
1942
1943 #if defined(hpux11)
1944 int
Interface_Scan_Next(short * Index,char * Name,nmapi_phystat * Retifnet)1945 Interface_Scan_Next(short *Index, char *Name, nmapi_phystat * Retifnet)
1946 {
1947 int returnIndex = 0;
1948 int ret;
1949 if (Index)
1950 returnIndex = *Index;
1951
1952 ret = Interface_Scan_NextInt( &returnIndex, Name, Retifnet );
1953 if (Index)
1954 *Index = (returnIndex & 0x8fff);
1955 return ret;
1956 }
1957
1958
1959 int
Interface_Scan_NextInt(int * Index,char * Name,nmapi_phystat * Retifnet)1960 Interface_Scan_NextInt(int *Index, char *Name, nmapi_phystat * Retifnet)
1961 {
1962 static nmapi_phystat *if_ptr = (nmapi_phystat *) 0;
1963 int count = Interface_Scan_Get_Count();
1964 unsigned int ulen;
1965 int ret;
1966
1967 if (!if_ptr) {
1968 if (count) {
1969 if_ptr =
1970 (nmapi_phystat *) malloc(sizeof(nmapi_phystat) * count);
1971 if (if_ptr == NULL)
1972 return (0);
1973
1974 } else
1975 return (0); /* EOF */
1976 }
1977
1978 if (saveIndex >= count)
1979 return (0); /* EOF */
1980
1981 ulen = (unsigned int) count *sizeof(nmapi_phystat);
1982 if ((ret = get_physical_stat(if_ptr, &ulen)) < 0)
1983 return (0); /* EOF */
1984
1985 if (Retifnet)
1986 *Retifnet = if_ptr[saveIndex];
1987 if (Name)
1988 strcpy(Name, if_ptr[saveIndex].nm_device);
1989 saveIndex++;
1990 if (Index)
1991 *Index = saveIndex;
1992 return (1); /* DONE */
1993 }
1994
1995 #else /* hpux11 */
1996 int
Interface_Scan_Next(short * Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * Retin_ifaddr)1997 Interface_Scan_Next(short *Index,
1998 char *Name,
1999 struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
2000 {
2001 int returnIndex = 0;
2002 int ret;
2003 if (Index)
2004 returnIndex = *Index;
2005
2006 ret = Interface_Scan_NextInt( &returnIndex, Name, Retifnet, Retin_ifaddr );
2007 if (Index)
2008 *Index = (returnIndex & 0x8fff);
2009 return ret;
2010 }
2011
2012
2013 int
Interface_Scan_NextInt(int * Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * Retin_ifaddr)2014 Interface_Scan_NextInt(int *Index,
2015 char *Name,
2016 struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
2017 {
2018 struct ifnet ifnet;
2019 struct in_ifaddr *ia, in_ifaddr;
2020 short has_ipaddr = 0;
2021 #if !HAVE_STRUCT_IFNET_IF_XNAME
2022 register char *cp;
2023 #endif
2024
2025 while (ifnetaddr) {
2026 /*
2027 * Get the "ifnet" structure and extract the device name
2028 */
2029 if (!NETSNMP_KLOOKUP(ifnetaddr, (char *) &ifnet, sizeof ifnet)) {
2030 DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
2031 break;
2032 }
2033 #if HAVE_STRUCT_IFNET_IF_XNAME
2034 #if defined(netbsd1) || defined(openbsd2)
2035 strlcpy(saveName, ifnet.if_xname, sizeof(saveName));
2036 #else
2037 if (!NETSNMP_KLOOKUP(ifnet.if_xname, (char *) saveName, sizeof saveName)) {
2038 DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
2039 break;
2040 }
2041 #endif
2042 saveName[sizeof(saveName) - 1] = '\0';
2043 #else
2044 if (!NETSNMP_KLOOKUP(ifnet.if_name, (char *) saveName, sizeof saveName)) {
2045 DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
2046 break;
2047 }
2048
2049 saveName[sizeof(saveName) - 1] = '\0';
2050 cp = strchr(saveName, '\0');
2051 #ifdef NETSNMP_FEATURE_CHECKIN
2052 /* this exists here just so we don't copy ifdef logic elsewhere */
2053 netsnmp_feature_require(string_append_int);
2054 #endif
2055 string_append_int(cp, ifnet.if_unit);
2056 #endif
2057 if (1 || strcmp(saveName, "lo0") != 0) { /* XXX */
2058 /*
2059 * Try to find an address for this interface
2060 */
2061
2062 #ifdef netbsd1
2063 ia = (struct in_ifaddr *) ifnet.if_addrlist.tqh_first;
2064 #elif defined(IFADDR_SYMBOL)
2065 auto_nlist(IFADDR_SYMBOL, (char *) &ia, sizeof(ia));
2066 #endif
2067 while (ia) {
2068 if (!NETSNMP_KLOOKUP(ia, (char *) &in_ifaddr, sizeof(in_ifaddr))) {
2069 DEBUGMSGTL(("mibII/interfaces:Interface_Scan_Next", "klookup failed\n"));
2070 break;
2071 }
2072 {
2073 #ifdef netbsd1
2074 #define CP(x) ((char *)(x))
2075 char *cp;
2076 struct sockaddr *sa;
2077 cp = (CP(in_ifaddr.ia_ifa.ifa_addr) - CP(ia)) +
2078 CP(&in_ifaddr);
2079 sa = (struct sockaddr *) cp;
2080
2081 if (sa->sa_family == AF_INET)
2082 #endif
2083 if (in_ifaddr.ia_ifp == ifnetaddr) {
2084 has_ipaddr = 1; /* this IF has IP-address */
2085 break;
2086 }
2087 }
2088 #ifdef netbsd1
2089 ia = (struct in_ifaddr *) in_ifaddr.ia_ifa.ifa_list.
2090 tqe_next;
2091 #else
2092 ia = in_ifaddr.ia_next;
2093 #endif
2094 }
2095
2096 #if !defined(netbsd1) && !defined(freebsd2) && !defined(openbsd2) && !defined(HAVE_STRUCT_IFNET_IF_ADDRLIST)
2097 ifnet.if_addrlist = (struct ifaddr *) ia; /* WRONG DATA TYPE; ONLY A FLAG */
2098 #endif
2099 /*
2100 * ifnet.if_addrlist = (struct ifaddr *)&ia->ia_ifa;
2101 *
2102 * WRONG DATA TYPE; ONLY A FLAG
2103 */
2104
2105 if (Index)
2106 *Index = ++saveIndex;
2107 if (Retifnet)
2108 *Retifnet = ifnet;
2109 if (Retin_ifaddr && has_ipaddr) /* assign the in_ifaddr only
2110 * if the IF has IP-address */
2111 *Retin_ifaddr = in_ifaddr;
2112 if (Name)
2113 strcpy(Name, saveName);
2114 saveifnet = ifnet;
2115 saveifnetaddr = ifnetaddr;
2116 savein_ifaddr = in_ifaddr;
2117 ifnetaddr = ifnet.if_next;
2118
2119 return (1); /* DONE */
2120 }
2121 ifnetaddr = ifnet.if_next;
2122 }
2123 return (0); /* EOF */
2124 }
2125
2126 #endif /* hpux11 */
2127
2128 #endif /* sunV3 || linux */
2129
2130 #if defined(hpux11)
2131
2132 static int
Interface_Scan_By_Index(int Index,char * Name,nmapi_phystat * Retifnet)2133 Interface_Scan_By_Index(int Index, char *Name, nmapi_phystat * Retifnet)
2134 {
2135 int i;
2136
2137 Interface_Scan_Init();
2138 while (Interface_Scan_NextInt(&i, Name, Retifnet)) {
2139 if (i == Index)
2140 break;
2141 }
2142 if (i != Index)
2143 return (-1); /* Error, doesn't exist */
2144 return (0); /* DONE */
2145 }
2146
2147 #else /* hpux11 */
2148
2149 static int
Interface_Scan_By_Index(int Index,char * Name,struct ifnet * Retifnet,struct in_ifaddr * Retin_ifaddr)2150 Interface_Scan_By_Index(int Index,
2151 char *Name,
2152 struct ifnet *Retifnet,
2153 struct in_ifaddr *Retin_ifaddr)
2154 {
2155 int i;
2156
2157 Interface_Scan_Init();
2158 while (Interface_Scan_NextInt(&i, Name, Retifnet, Retin_ifaddr)) {
2159 if (i == Index)
2160 break;
2161 }
2162 if (i != Index)
2163 return (-1); /* Error, doesn't exist */
2164 return (0); /* DONE */
2165 }
2166
2167 #endif /* hpux11 */
2168
2169 static int Interface_Count = 0;
2170
2171 #if defined(hpux11)
2172
2173 int
Interface_Scan_Get_Count(void)2174 Interface_Scan_Get_Count(void)
2175 {
2176 if (!Interface_Count) {
2177 int fd;
2178 struct nmparms p;
2179 int val;
2180 unsigned int ulen;
2181 int ret;
2182
2183 if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
2184 p.objid = ID_ifNumber;
2185 p.buffer = (void *) &val;
2186 ulen = sizeof(int);
2187 p.len = &ulen;
2188 if ((ret = get_mib_info(fd, &p)) == 0)
2189 Interface_Count = val;
2190 close_mib(fd);
2191 }
2192 }
2193 return (Interface_Count);
2194 }
2195
2196 #else /* hpux11 */
2197
2198 int
Interface_Scan_Get_Count(void)2199 Interface_Scan_Get_Count(void)
2200 {
2201 static time_t scan_time = 0;
2202 time_t time_now = time(NULL);
2203
2204 if (!Interface_Count || (time_now > scan_time + 60)) {
2205 scan_time = time_now;
2206 Interface_Scan_Init();
2207 Interface_Count = 0;
2208 while (Interface_Scan_NextInt(NULL, NULL, NULL, NULL) != 0) {
2209 Interface_Count++;
2210 }
2211 }
2212 return (Interface_Count);
2213 }
2214
2215
2216 static int
Interface_Get_Ether_By_Index(int Index,u_char * EtherAddr)2217 Interface_Get_Ether_By_Index(int Index, u_char * EtherAddr)
2218 {
2219 int i;
2220 #if !(defined(linux) || defined(netbsd1) || defined(bsdi2) || defined(openbsd2))
2221 struct arpcom arpcom;
2222 #else /* is linux or netbsd1 */
2223 struct arpcom {
2224 char ac_enaddr[6];
2225 } arpcom;
2226 #if defined(netbsd1) || defined(bsdi2) || defined(openbsd2)
2227 struct sockaddr_dl sadl;
2228 struct ifaddr ifaddr;
2229 u_long ifaddraddr;
2230 #endif
2231 #endif
2232
2233 #if defined(mips) || defined(hpux) || defined(osf4) || defined(osf3) || defined(osf5)
2234 memset(arpcom.ac_enaddr, 0, sizeof(arpcom.ac_enaddr));
2235 #else
2236 memset(&arpcom.ac_enaddr, 0, sizeof(arpcom.ac_enaddr));
2237 #endif
2238 memset(EtherAddr, 0, sizeof(arpcom.ac_enaddr));
2239
2240 if (saveIndex != Index) { /* Optimization! */
2241
2242 Interface_Scan_Init();
2243
2244 while (Interface_Scan_NextInt(&i, NULL, NULL, NULL) != 0) {
2245 if (i == Index)
2246 break;
2247 }
2248 if (i != Index)
2249 return (-1); /* Error, doesn't exist */
2250 }
2251 #ifdef freebsd2
2252 if (saveifnet.if_type != IFT_ETHER) {
2253 return (0); /* Not an ethernet if */
2254 }
2255 #endif
2256 /*
2257 * the arpcom structure is an extended ifnet structure which
2258 * contains the ethernet address.
2259 */
2260 #ifndef linux
2261 #if !(defined(netbsd1) || defined(bsdi2) || defined(openbsd2))
2262 if (!NETSNMP_KLOOKUP(saveifnetaddr, (char *) &arpcom, sizeof arpcom)) {
2263 DEBUGMSGTL(("mibII/interfaces:Interface_Get_Ether_By_Index", "klookup failed\n"));
2264 return 0;
2265 }
2266 #else /* netbsd1 or bsdi2 or openbsd2 */
2267
2268 #if defined(netbsd1) || defined(openbsd2)
2269 #define if_addrlist if_addrlist.tqh_first
2270 #define ifa_next ifa_list.tqe_next
2271 #endif
2272
2273 ifaddraddr = (unsigned long) saveifnet.if_addrlist;
2274 while (ifaddraddr) {
2275 if (!NETSNMP_KLOOKUP(ifaddraddr, (char *) &ifaddr, sizeof ifaddr)) {
2276 DEBUGMSGTL(("mibII/interfaces:Interface_Get_Ether_By_Index", "klookup failed\n"));
2277 break;
2278 }
2279 if (!NETSNMP_KLOOKUP(ifaddr.ifa_addr, (char *) &sadl, sizeof sadl)) {
2280 DEBUGMSGTL(("mibII/interfaces:Interface_Get_Ether_By_Index", "klookup failed\n"));
2281 break;
2282 }
2283 if (sadl.sdl_family == AF_LINK
2284 && (saveifnet.if_type == IFT_ETHER
2285 || saveifnet.if_type == IFT_ISO88025
2286 || saveifnet.if_type == IFT_FDDI)) {
2287 memcpy(arpcom.ac_enaddr, sadl.sdl_data + sadl.sdl_nlen,
2288 sizeof(arpcom.ac_enaddr));
2289 break;
2290 }
2291 ifaddraddr = (unsigned long) ifaddr.ifa_next;
2292 }
2293 #endif /* netbsd1 or bsdi2 or openbsd2 */
2294
2295 #else /* linux */
2296 memcpy(arpcom.ac_enaddr, saveifnetaddr->if_hwaddr, 6);
2297 #endif
2298 if (strncmp("lo", saveName, 2) == 0) {
2299 /*
2300 * Loopback doesn't have a HW addr, so return 00:00:00:00:00:00
2301 */
2302 memset(EtherAddr, 0, sizeof(arpcom.ac_enaddr));
2303
2304 } else {
2305
2306 #if defined(mips) || defined(hpux) || defined(osf4) || defined(osf3)
2307 memcpy(EtherAddr, (char *) arpcom.ac_enaddr,
2308 sizeof(arpcom.ac_enaddr));
2309 #else
2310 memcpy(EtherAddr, (char *) &arpcom.ac_enaddr,
2311 sizeof(arpcom.ac_enaddr));
2312 #endif
2313
2314
2315 }
2316 return (0); /* DONE */
2317 }
2318
2319 #endif /* hpux11 */
2320
2321 #else /* solaris2 */
2322
2323 int
Interface_Scan_Get_Count(void)2324 Interface_Scan_Get_Count(void)
2325 {
2326 int i, sd;
2327
2328 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
2329 return (0);
2330 if (ioctl(sd, SIOCGIFNUM, &i) == -1) {
2331 close(sd);
2332 return (0);
2333 } else {
2334 close(sd);
2335 return (i);
2336 }
2337 }
2338
2339 int
Interface_Index_By_Name(char * Name,int Len)2340 Interface_Index_By_Name(char *Name, int Len)
2341 {
2342 return (solaris2_if_nametoindex(Name, Len));
2343 }
2344
2345 #endif /* solaris2 */
2346
2347 #else /* HAVE_NET_IF_MIB_H */
2348
2349 /*
2350 * This code attempts to do the right thing for FreeBSD. Note that
2351 * the statistics could be gathered through use of of the
2352 * net.route.0.link.iflist.0 sysctl (which we already use to get the
2353 * hardware address of the interfaces), rather than using the ifmib
2354 * code, but eventually I will implement dot3Stats and we will have to
2355 * use the ifmib interface. ifmib is also a much more natural way of
2356 * mapping the SNMP MIB onto sysctl(3).
2357 */
2358
2359 #include <net/if.h>
2360 #include <net/if_dl.h>
2361 #include <net/if_mib.h>
2362 #include <net/route.h>
2363
2364 static int header_interfaces(struct variable *, oid *, size_t *, int,
2365 size_t *, WriteMethod ** write);
2366 static int header_ifEntry(struct variable *, oid *, size_t *, int,
2367 size_t *, WriteMethod ** write);
2368
2369 static char *physaddrbuf;
2370 static int nphysaddrs;
2371 struct sockaddr_dl **physaddrs;
2372
2373 void
init_interfaces_setup(void)2374 init_interfaces_setup(void)
2375 {
2376 int naddrs, ilen, bit;
2377 static int mib[6]
2378 = { CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
2379 char *cp;
2380 size_t len;
2381 struct rt_msghdr *rtm;
2382 struct if_msghdr *ifm;
2383 struct ifa_msghdr *ifam;
2384 struct sockaddr *sa;
2385
2386 DEBUGMSGTL(("mibII:freebsd", "init_interfaces_setup\n"));
2387
2388 naddrs = 0;
2389 if (physaddrs)
2390 free(physaddrs);
2391 if (physaddrbuf)
2392 free(physaddrbuf);
2393 physaddrbuf = 0;
2394 physaddrs = 0;
2395 nphysaddrs = 0;
2396 len = 0;
2397 if (sysctl(mib, 6, 0, &len, 0, 0) < 0) {
2398 DEBUGMSGTL(("mibII:freebsd", "sysctl 1 < 0\n"));
2399 return;
2400 }
2401
2402 cp = physaddrbuf = malloc(len);
2403 if (physaddrbuf == 0)
2404 return;
2405 if (sysctl(mib, 6, physaddrbuf, &len, 0, 0) < 0) {
2406 free(physaddrbuf);
2407 physaddrbuf = 0;
2408 DEBUGMSGTL(("mibII:freebsd", "sysctl 2 < 0\n"));
2409 return;
2410 }
2411
2412 loop:
2413 ilen = len;
2414 cp = physaddrbuf;
2415 while (ilen > 0) {
2416 rtm = (struct rt_msghdr *) cp;
2417 if (rtm->rtm_version != RTM_VERSION || rtm->rtm_type != RTM_IFINFO) {
2418 DEBUGMSGTL(("mibII:freebsd", "version:%d/%d type:%d/%d\n",
2419 rtm->rtm_version, RTM_VERSION, rtm->rtm_type, RTM_IFINFO));
2420 free(physaddrs);
2421 physaddrs = 0;
2422 free(physaddrbuf);
2423 physaddrbuf = 0;
2424 }
2425 ifm = (struct if_msghdr *) rtm;
2426 #if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
2427 if (physaddrs != 0)
2428 physaddrs[naddrs] = (void *) (ifm + 1);
2429 naddrs++;
2430 #endif
2431 ilen -= ifm->ifm_msglen;
2432 cp += ifm->ifm_msglen;
2433 rtm = (struct rt_msghdr *) cp;
2434 while (ilen > 0 && rtm->rtm_type == RTM_NEWADDR) {
2435 #if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
2436 ilen -= rtm->rtm_msglen;
2437 cp += rtm->rtm_msglen;
2438 #else
2439 int is_alias = 0;
2440 ifam = (struct ifa_msghdr *) rtm;
2441 ilen -= sizeof(*ifam);
2442 cp += sizeof(*ifam);
2443 sa = (struct sockaddr *) cp;
2444 #define ROUND(x) (((x) + sizeof(long) - 1) & ~sizeof(long))
2445 for (bit = 1; bit && ilen > 0; bit <<= 1) {
2446 if (!(ifam->ifam_addrs & bit))
2447 continue;
2448 ilen -= ROUND(sa->sa_len);
2449 cp += ROUND(sa->sa_len);
2450
2451 if (bit == RTA_IFA) {
2452 if (physaddrs)
2453 #define satosdl(sa) ((struct sockaddr_dl *)(sa))
2454 physaddrs[naddrs++]
2455 = satosdl(sa);
2456 else
2457 naddrs++;
2458 }
2459 sa = (struct sockaddr *) cp;
2460 }
2461 #endif
2462 rtm = (struct rt_msghdr *) cp;
2463 }
2464 }
2465 DEBUGMSGTL(("mibII:freebsd", "found %d addrs\n", naddrs));
2466 if (physaddrs) {
2467 nphysaddrs = naddrs;
2468 return;
2469 }
2470 physaddrs = malloc(naddrs * sizeof(*physaddrs));
2471 if (physaddrs == 0)
2472 return;
2473 naddrs = 0;
2474 goto loop;
2475
2476 }
2477
2478 static int
get_phys_address(int iindex,char ** ap,int * len)2479 get_phys_address(int iindex, char **ap, int *len)
2480 {
2481 int i;
2482 int once = 1;
2483
2484 do {
2485 for (i = 0; i < nphysaddrs; i++) {
2486 if (physaddrs[i]->sdl_index == iindex)
2487 break;
2488 }
2489 if (i < nphysaddrs)
2490 break;
2491 init_interfaces_setup();
2492 } while (once--);
2493
2494 DEBUGMSGTL(("mibII:freebsd", "get_phys_address %d/%d\n", i, nphysaddrs));
2495 if (i < nphysaddrs) {
2496 *ap = LLADDR(physaddrs[i]);
2497 *len = physaddrs[i]->sdl_alen;
2498 return 0;
2499 }
2500 return -1;
2501 }
2502
2503 int
Interface_Scan_Get_Count(void)2504 Interface_Scan_Get_Count(void)
2505 {
2506 static int count_oid[5] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
2507 IFMIB_SYSTEM, IFMIB_IFCOUNT
2508 };
2509 size_t len;
2510 int count;
2511
2512 len = sizeof count;
2513 if (sysctl(count_oid, 5, &count, &len, (void *) 0, (size_t) 0) < 0) {
2514 DEBUGMSGTL(("mibII:freebsd", "Interface_Scan_Get_Count err\n"));
2515 return -1;
2516 }
2517 DEBUGMSGTL(("mibII:freebsd", "Interface_Scan_Get_Count %d\n", count));
2518 return count;
2519 }
2520
2521
2522 u_char *
var_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)2523 var_ifEntry(struct variable * vp,
2524 oid * name,
2525 size_t * length,
2526 int exact, size_t * var_len, WriteMethod ** write_method)
2527 {
2528 int interface;
2529 static int sname[6] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
2530 IFMIB_IFDATA, 0, IFDATA_GENERAL
2531 };
2532 static struct ifmibdata ifmd;
2533 size_t len;
2534 char *cp;
2535 conf_if_list *if_ptr = NULL;
2536
2537 interface = header_ifEntry(vp, name, length, exact, var_len,
2538 write_method);
2539 if (interface == MATCH_FAILED)
2540 return NULL;
2541
2542 sname[4] = interface;
2543 len = sizeof ifmd;
2544 if (sysctl(sname, 6, &ifmd, &len, 0, 0) < 0) {
2545 DEBUGMSGTL(("mibII:freebsd", "var_ifEntry sysctl err\n"));
2546 return NULL;
2547 }
2548 /*
2549 * hmmm.. where to get the interface name to check overrides?
2550 *
2551 * if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
2552 */
2553
2554 switch (vp->magic) {
2555 case NETSNMP_IFINDEX:
2556 long_return = interface;
2557 return (u_char *) & long_return;
2558 case NETSNMP_IFDESCR:
2559 cp = ifmd.ifmd_name;
2560 *var_len = strlen(cp);
2561 return (u_char *) cp;
2562 case NETSNMP_IFTYPE:
2563 if (if_ptr)
2564 long_return = if_ptr->type;
2565 else
2566 long_return = ifmd.ifmd_data.ifi_type;
2567 return (u_char *) & long_return;
2568 case NETSNMP_IFMTU:
2569 long_return = (long) ifmd.ifmd_data.ifi_mtu;
2570 return (u_char *) & long_return;
2571 case NETSNMP_IFSPEED:
2572 if (if_ptr)
2573 long_return = if_ptr->speed;
2574 else
2575 long_return = ifmd.ifmd_data.ifi_baudrate;
2576 return (u_char *) & long_return;
2577 case NETSNMP_IFPHYSADDRESS:
2578 {
2579 char *cp;
2580 if (get_phys_address(interface, &cp, var_len))
2581 return NULL;
2582 else
2583 return cp;
2584 }
2585 case NETSNMP_IFADMINSTATUS:
2586 long_return = ifmd.ifmd_flags & IFF_UP ? 1 : 2;
2587 return (u_char *) & long_return;
2588 case NETSNMP_IFOPERSTATUS:
2589 long_return = ifmd.ifmd_flags & IFF_RUNNING ? 1 : 2;
2590 return (u_char *) & long_return;
2591 case NETSNMP_IFLASTCHANGE:
2592 if (ifmd.ifmd_data.ifi_lastchange.tv_sec == 0 &&
2593 ifmd.ifmd_data.ifi_lastchange.tv_usec == 0) {
2594 long_return = 0;
2595 } else if (ifmd.ifmd_data.ifi_lastchange.tv_sec < starttime.tv_sec) {
2596 long_return = 0;
2597 } else {
2598 long_return = (u_long)
2599 ((ifmd.ifmd_data.ifi_lastchange.tv_sec -
2600 starttime.tv_sec) * 100 +
2601 ((ifmd.ifmd_data.ifi_lastchange.tv_usec -
2602 starttime.tv_usec) / 10000));
2603 }
2604 return (u_char *) & long_return;
2605 case NETSNMP_IFINOCTETS:
2606 long_return = (u_long) ifmd.ifmd_data.ifi_ibytes;
2607 return (u_char *) & long_return;
2608 case NETSNMP_IFINUCASTPKTS:
2609 long_return = (u_long) ifmd.ifmd_data.ifi_ipackets;
2610 long_return -= (u_long) ifmd.ifmd_data.ifi_imcasts;
2611 return (u_char *) & long_return;
2612 case NETSNMP_IFINNUCASTPKTS:
2613 long_return = (u_long) ifmd.ifmd_data.ifi_imcasts;
2614 return (u_char *) & long_return;
2615 case NETSNMP_IFINDISCARDS:
2616 long_return = (u_long) ifmd.ifmd_data.ifi_iqdrops;
2617 return (u_char *) & long_return;
2618 case NETSNMP_IFINERRORS:
2619 long_return = ifmd.ifmd_data.ifi_ierrors;
2620 return (u_char *) & long_return;
2621 case NETSNMP_IFINUNKNOWNPROTOS:
2622 long_return = (u_long) ifmd.ifmd_data.ifi_noproto;
2623 return (u_char *) & long_return;
2624 case NETSNMP_IFOUTOCTETS:
2625 long_return = (u_long) ifmd.ifmd_data.ifi_obytes;
2626 return (u_char *) & long_return;
2627 case NETSNMP_IFOUTUCASTPKTS:
2628 long_return = (u_long) ifmd.ifmd_data.ifi_opackets;
2629 long_return -= (u_long) ifmd.ifmd_data.ifi_omcasts;
2630 return (u_char *) & long_return;
2631 case NETSNMP_IFOUTNUCASTPKTS:
2632 long_return = (u_long) ifmd.ifmd_data.ifi_omcasts;
2633 return (u_char *) & long_return;
2634 case NETSNMP_IFOUTDISCARDS:
2635 long_return = ifmd.ifmd_snd_drops;
2636 return (u_char *) & long_return;
2637 case NETSNMP_IFOUTERRORS:
2638 long_return = ifmd.ifmd_data.ifi_oerrors;
2639 return (u_char *) & long_return;
2640 case NETSNMP_IFOUTQLEN:
2641 long_return = ifmd.ifmd_snd_len;
2642 return (u_char *) & long_return;
2643 case NETSNMP_IFSPECIFIC:
2644 *var_len = nullOidLen;
2645 return (u_char *) nullOid;
2646 default:
2647 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
2648 vp->magic));
2649 }
2650 return NULL;
2651 }
2652
2653 #endif /* HAVE_NET_IF_MIB_H */
2654 #endif /* !USE_SYSCTL_IFLIST */
2655
2656 #elif defined(HAVE_IPHLPAPI_H) /* WIN32 cygwin */
2657 #include <iphlpapi.h>
2658
2659 #ifndef NETSNMP_NO_WRITE_SUPPORT
2660 WriteMethod writeIfEntry;
2661 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
2662 long admin_status = 0;
2663 long oldadmin_status = 0;
2664
2665 void
Interface_Scan_Init(void)2666 Interface_Scan_Init(void)
2667 {
2668 }
2669
2670 static int
header_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)2671 header_ifEntry(struct variable *vp,
2672 oid * name,
2673 size_t * length,
2674 int exact, size_t * var_len, WriteMethod ** write_method)
2675 {
2676 #define IFENTRY_NAME_LENGTH 10
2677 oid newname[MAX_OID_LEN];
2678 register int ifIndex;
2679 int result, count;
2680 DWORD status = NO_ERROR;
2681 DWORD dwActualSize = 0;
2682 PMIB_IFTABLE pIfTable = NULL;
2683
2684 DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
2685 DEBUGMSGOID(("mibII/interfaces", name, *length));
2686 DEBUGMSG(("mibII/interfaces", " %d\n", exact));
2687
2688 memcpy((char *) newname, (char *) vp->name,
2689 (int) vp->namelen * sizeof(oid));
2690 /*
2691 * find "next" ifIndex
2692 */
2693
2694 status = GetIfTable(pIfTable, &dwActualSize, TRUE);
2695 if (status == ERROR_INSUFFICIENT_BUFFER) {
2696 pIfTable = malloc(dwActualSize);
2697 if (pIfTable)
2698 GetIfTable(pIfTable, &dwActualSize, TRUE);
2699 }
2700 count = pIfTable->dwNumEntries;
2701 for (ifIndex = 0; ifIndex < count; ifIndex++) {
2702 newname[IFENTRY_NAME_LENGTH] =
2703 (oid) pIfTable->table[ifIndex].dwIndex;
2704 result =
2705 snmp_oid_compare(name, *length, newname,
2706 (int) vp->namelen + 1);
2707 if ((exact && (result == 0)) || (!exact && (result < 0)))
2708 break;
2709 }
2710 if (ifIndex >= count) {
2711 DEBUGMSGTL(("mibII/interfaces", "... index out of range\n"));
2712 count = MATCH_FAILED;
2713 goto out;
2714 }
2715
2716 memcpy((char *) name, (char *) newname,
2717 ((int) vp->namelen + 1) * sizeof(oid));
2718 *length = vp->namelen + 1;
2719 *write_method = 0;
2720 *var_len = sizeof(long); /* default to 'long' results */
2721
2722 DEBUGMSGTL(("mibII/interfaces", "... get I/F stats "));
2723 DEBUGMSGOID(("mibII/interfaces", name, *length));
2724 DEBUGMSG(("mibII/interfaces", "\n"));
2725
2726 count = pIfTable->table[ifIndex].dwIndex;
2727 out:
2728 free(pIfTable);
2729 return count;
2730 }
2731
2732
2733
2734 u_char *
var_interfaces(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)2735 var_interfaces(struct variable * vp,
2736 oid * name,
2737 size_t * length,
2738 int exact, size_t * var_len, WriteMethod ** write_method)
2739 {
2740 if (header_generic(vp, name, length, exact, var_len, write_method) ==
2741 MATCH_FAILED)
2742 return NULL;
2743
2744 switch (vp->magic) {
2745 case NETSNMP_IFNUMBER:
2746 netsnmp_assert(sizeof(DWORD) == sizeof(long_return));
2747 GetNumberOfInterfaces((DWORD *) &long_return);
2748 return (u_char *) & long_return;
2749 default:
2750 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_interfaces\n",
2751 vp->magic));
2752 }
2753 return NULL;
2754 }
2755
2756 u_char *
var_ifEntry(struct variable * vp,oid * name,size_t * length,int exact,size_t * var_len,WriteMethod ** write_method)2757 var_ifEntry(struct variable * vp,
2758 oid * name,
2759 size_t * length,
2760 int exact, size_t * var_len, WriteMethod ** write_method)
2761 {
2762 int ifIndex;
2763 static MIB_IFROW ifRow;
2764 conf_if_list *if_ptr = NULL;
2765
2766 ifIndex =
2767 header_ifEntry(vp, name, length, exact, var_len, write_method);
2768 if (ifIndex == MATCH_FAILED)
2769 return NULL;
2770 /*
2771 * hmmm.. where to get the interface name to check overrides?
2772 *
2773 * if_ptr = netsnmp_access_interface_entry_overrides_get(Name);
2774 */
2775
2776 /*
2777 * Get the If Table Row by passing index as argument
2778 */
2779 ifRow.dwIndex = ifIndex;
2780 if (GetIfEntry(&ifRow) != NO_ERROR)
2781 return NULL;
2782 switch (vp->magic) {
2783 case NETSNMP_IFINDEX:
2784 long_return = ifIndex;
2785 return (u_char *) & long_return;
2786 case NETSNMP_IFDESCR:
2787 *var_len = ifRow.dwDescrLen;
2788 return (u_char *) ifRow.bDescr;
2789 case NETSNMP_IFTYPE:
2790 if (if_ptr)
2791 long_return = if_ptr->type;
2792 else
2793 long_return = ifRow.dwType;
2794 return (u_char *) & long_return;
2795 case NETSNMP_IFMTU:
2796 long_return = (long) ifRow.dwMtu;
2797 return (u_char *) & long_return;
2798 case NETSNMP_IFSPEED:
2799 if (if_ptr)
2800 long_return = (long) if_ptr->speed;
2801 else
2802 long_return = (long) ifRow.dwSpeed;
2803 return (u_char *) & long_return;
2804 case NETSNMP_IFPHYSADDRESS:
2805 *var_len = ifRow.dwPhysAddrLen;
2806 memcpy(return_buf, ifRow.bPhysAddr, *var_len);
2807 return (u_char *) return_buf;
2808 case NETSNMP_IFADMINSTATUS:
2809 long_return = ifRow.dwAdminStatus;
2810 admin_status = long_return;
2811 #ifndef NETSNMP_NO_WRITE_SUPPORT
2812 *write_method = writeIfEntry;
2813 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
2814 return (u_char *) & long_return;
2815 case NETSNMP_IFOPERSTATUS:
2816 long_return =
2817 (MIB_IF_OPER_STATUS_OPERATIONAL == ifRow.dwOperStatus) ? 1 : 2;
2818 return (u_char *) & long_return;
2819 case NETSNMP_IFLASTCHANGE:
2820 long_return = 0 /* XXX not a UNIX epochal time ifRow.dwLastChange */ ;
2821 return (u_char *) & long_return;
2822 case NETSNMP_IFINOCTETS:
2823 long_return = ifRow.dwInOctets;
2824 return (u_char *) & long_return;
2825 case NETSNMP_IFINUCASTPKTS:
2826 long_return = ifRow.dwInUcastPkts;
2827 return (u_char *) & long_return;
2828 case NETSNMP_IFINNUCASTPKTS:
2829 long_return = ifRow.dwInNUcastPkts;
2830 return (u_char *) & long_return;
2831 case NETSNMP_IFINDISCARDS:
2832 long_return = ifRow.dwInDiscards;
2833 return (u_char *) & long_return;
2834 case NETSNMP_IFINERRORS:
2835 long_return = ifRow.dwInErrors;
2836 return (u_char *) & long_return;
2837 case NETSNMP_IFINUNKNOWNPROTOS:
2838 long_return = ifRow.dwInUnknownProtos;
2839 return (u_char *) & long_return;
2840 case NETSNMP_IFOUTOCTETS:
2841 long_return = ifRow.dwOutOctets;
2842 return (u_char *) & long_return;
2843 case NETSNMP_IFOUTUCASTPKTS:
2844 long_return = ifRow.dwOutUcastPkts;
2845 return (u_char *) & long_return;
2846 case NETSNMP_IFOUTNUCASTPKTS:
2847 long_return = ifRow.dwOutNUcastPkts;
2848 return (u_char *) & long_return;
2849 case NETSNMP_IFOUTDISCARDS:
2850 long_return = ifRow.dwOutDiscards;
2851 return (u_char *) & long_return;
2852 case NETSNMP_IFOUTERRORS:
2853 long_return = ifRow.dwOutErrors;
2854 return (u_char *) & long_return;
2855 case NETSNMP_IFOUTQLEN:
2856 long_return = ifRow.dwOutQLen;
2857 return (u_char *) & long_return;
2858 case NETSNMP_IFSPECIFIC:
2859 *var_len = nullOidLen;
2860 return (u_char *) nullOid;
2861 default:
2862 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
2863 vp->magic));
2864 }
2865 return NULL;
2866 }
2867
2868
2869 #ifndef NETSNMP_NO_WRITE_SUPPORT
2870 int
writeIfEntry(int action,u_char * var_val,u_char var_val_type,size_t var_val_len,u_char * statP,oid * name,size_t name_len)2871 writeIfEntry(int action,
2872 u_char * var_val,
2873 u_char var_val_type,
2874 size_t var_val_len,
2875 u_char * statP, oid * name, size_t name_len)
2876 {
2877 MIB_IFROW ifEntryRow;
2878 if ((char) name[9] != NETSNMP_IFADMINSTATUS) {
2879 return SNMP_ERR_NOTWRITABLE;
2880 }
2881
2882 switch (action) {
2883 case RESERVE1: /* Check values for acceptability */
2884 if (var_val_type != ASN_INTEGER) {
2885 snmp_log(LOG_ERR, "not integer\n");
2886 return SNMP_ERR_WRONGTYPE;
2887 }
2888 if (var_val_len > sizeof(int)) {
2889 snmp_log(LOG_ERR, "bad length\n");
2890 return SNMP_ERR_WRONGLENGTH;
2891 }
2892
2893 /*
2894 * The dwAdminStatus member can be MIB_IF_ADMIN_STATUS_UP or MIB_IF_ADMIN_STATUS_DOWN
2895 */
2896 if (!(((int) (*var_val) == MIB_IF_ADMIN_STATUS_UP) ||
2897 ((int) (*var_val) == MIB_IF_ADMIN_STATUS_DOWN))) {
2898 snmp_log(LOG_ERR, "not supported admin state\n");
2899 return SNMP_ERR_WRONGVALUE;
2900 }
2901 break;
2902
2903 case RESERVE2: /* Allocate memory and similar resources */
2904 break;
2905
2906 case ACTION:
2907 /*
2908 * Save the old value, in case of UNDO
2909 */
2910
2911 oldadmin_status = admin_status;
2912 admin_status = (int) *var_val;
2913 break;
2914
2915 case UNDO: /* Reverse the SET action and free resources */
2916 admin_status = oldadmin_status;
2917 break;
2918
2919 case COMMIT: /* Confirm the SET, performing any irreversible actions,
2920 * and free resources */
2921 ifEntryRow.dwIndex = (int) name[10];
2922 ifEntryRow.dwAdminStatus = admin_status;
2923 /*
2924 * Only UP and DOWN status are supported. Thats why done in COMMIT
2925 */
2926 if (SetIfEntry(&ifEntryRow) != NO_ERROR) {
2927 snmp_log(LOG_ERR,
2928 "Error in writeIfEntry case COMMIT with index: %lu & adminStatus %lu\n",
2929 ifEntryRow.dwIndex, ifEntryRow.dwAdminStatus);
2930 return SNMP_ERR_COMMITFAILED;
2931 }
2932
2933 case FREE: /* Free any resources allocated */
2934 /*
2935 * No resources have been allocated
2936 */
2937 break;
2938 }
2939 return SNMP_ERR_NOERROR;
2940 } /* end of writeIfEntry */
2941 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
2942 #endif /* WIN32 cygwin */
2943