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