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