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