2 * Interfaces MIB group implementation - interfaces.c
6 #include <net-snmp/net-snmp-config.h>
8 #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && !defined(IFNET_NEEDS_KERNEL_LATE)
10 #define _I_DEFINED_KERNEL
26 #include <sys/param.h>
28 #include <sys/types.h>
32 #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL) && defined(IFNET_NEEDS_KERNEL_LATE)
34 #define _I_DEFINED_KERNEL
37 #include <sys/socket.h>
39 #ifndef STREAM_NEEDS_KERNEL_ISLANDS
41 #include <sys/stream.h>
44 #if HAVE_SYS_SOCKETVAR_H
45 #include <sys/socketvar.h>
48 #if TIME_WITH_SYS_TIME
50 # include <sys/timeb.h>
52 # include <sys/time.h>
57 # include <sys/time.h>
63 #include <sys/sockio.h>
69 #include <sys/ioctl.h>
72 #include <netinet/in.h>
78 #include <net/if_var.h>
80 #ifdef _I_DEFINED_KERNEL
83 #ifdef STREAM_NEEDS_KERNEL_ISLANDS
85 #include <sys/stream.h>
89 #include <net/route.h>
91 #if HAVE_NETINET_IN_SYSTM_H
92 #include <netinet/in_systm.h>
94 #if HAVE_SYS_HASHING_H
95 #include <sys/hashing.h>
97 #if HAVE_NETINET_IN_VAR_H
98 #include <netinet/in_var.h>
100 #if HAVE_NETINET_IP_H
101 #include <netinet/ip.h>
104 #if HAVE_NETINET_IP6_H
105 #include <netinet/ip6.h>
109 #include <sys/queue.h>
111 #if HAVE_NETINET_IP_VAR_H
112 #include <netinet/ip_var.h>
115 #if HAVE_NETINET6_IP6_VAR_H
116 #include <netinet6/ip6_var.h>
119 #if HAVE_NETINET_IN_PCB_H
120 #include <netinet/in_pcb.h>
122 #if HAVE_NETINET_IF_ETHER_H
123 #include <netinet/if_ether.h>
125 #if HAVE_NET_IF_TYPES_H
126 #include <net/if_types.h>
130 #include <net/if_dl.h>
132 #include <sys/net/if_dl.h>
136 #include <inet/mib2.h>
148 #include "kernel_sunos5.h"
155 #include <netinet/mib_kern.h>
163 #if HAVE_SYS_SYSCTL_H
164 #include <sys/sysctl.h>
166 #if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
167 # define USE_SYSCTL_IFLIST
169 # if defined(CTL_NET) && !defined(freebsd2) && !defined(netbsd1)
171 # ifdef NET_RT_IFLIST
173 # define USE_SYSCTL_IFLIST
178 #endif /* defined(freebsd3) */
179 #endif /* HAVE_SYS_SYSCTL_H */
182 #include <osreldate.h>
184 #ifdef CAN_USE_SYSCTL
185 #include <sys/sysctl.h>
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>
192 #include "interfaces.h"
194 #include "util_funcs.h"
196 #ifdef BUILD_SNMP_SYSOR_MIB
197 #include "sysORTable.h"
200 #include <bcmtypes.h>
201 #include <bcmatmapi.h>
204 #define BRCM_IFLASTCHANGE_SUPPORT
206 extern struct timeval starttime;
208 static void parse_interface_config(const char *, char *);
209 static void free_interface_config(void);
211 struct variable3 interfaces_variables[] = {
212 {IFNUMBER, ASN_INTEGER, RONLY, var_interfaces, 1, {1}},
213 {IFINDEX, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 1}},
214 {IFDESCR, ASN_OCTET_STR, RONLY, var_ifEntry, 3, {2, 1, 2}},
215 {IFTYPE, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 3}},
216 {IFMTU, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 4}},
217 {IFSPEED, ASN_GAUGE, RONLY, var_ifEntry, 3, {2, 1, 5}},
218 {IFPHYSADDRESS, ASN_OCTET_STR, RONLY, var_ifEntry, 3, {2, 1, 6}},
219 #ifdef BUILD_SNMP_SET
220 {IFADMINSTATUS, ASN_INTEGER, RWRITE, var_ifEntry, 3, {2, 1, 7}}, /* brcm, linux can write */
222 {IFADMINSTATUS, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 7}},
223 #endif /* BUILD_SNMP_SET */
224 {IFOPERSTATUS, ASN_INTEGER, RONLY, var_ifEntry, 3, {2, 1, 8}},
225 {IFLASTCHANGE, ASN_TIMETICKS, RONLY, var_ifEntry, 3, {2, 1, 9}},
226 {IFINOCTETS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 10}},
227 {IFINUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 11}},
228 {IFINNUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 12}},
229 {IFINDISCARDS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 13}},
230 {IFINERRORS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 14}},
231 {IFINUNKNOWNPROTOS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 15}},
232 {IFOUTOCTETS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 16}},
233 {IFOUTUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 17}},
234 {IFOUTNUCASTPKTS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 18}},
235 {IFOUTDISCARDS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 19}},
236 {IFOUTERRORS, ASN_COUNTER, RONLY, var_ifEntry, 3, {2, 1, 20}},
237 {IFOUTQLEN, ASN_GAUGE, RONLY, var_ifEntry, 3, {2, 1, 21}},
238 {IFSPECIFIC, ASN_OBJECT_ID, RONLY, var_ifEntry, 3, {2, 1, 22}}
242 #define ARPHRD_CPCS 28 /* CPCS */
243 #define ARPHRD_DSL 29 /* ADSL */
246 * Define the OID pointer to the top of the mib tree that we're
247 * registering underneath, and the OID of the MIB module
249 oid interfaces_variables_oid[] = { SNMP_OID_MIB2, 2 };
250 oid interfaces_module_oid[] = { SNMP_OID_MIB2, 31 };
253 init_interfaces(void)
256 * register ourselves with the agent to handle our mib tree
258 REGISTER_MIB("mibII/interfaces", interfaces_variables, variable3,
259 interfaces_variables_oid);
260 #ifdef BUILD_SNMP_SYSOR_MIB
261 REGISTER_SYSOR_ENTRY(interfaces_module_oid,
262 "The MIB module to describe generic objects for network interface sub-layers");
263 #endif /* BUILD_SNMP_SYSOR_MIB */
265 snmpd_register_config_handler("interface", parse_interface_config,
266 free_interface_config,
269 #ifndef USE_SYSCTL_IFLIST
270 #if HAVE_NET_IF_MIB_H
271 init_interfaces_setup();
275 init_kernel_sunos5();
282 * Return interface type using the interface name as a clue.
283 * Returns 1 to imply "other" type if name not recognized.
286 if_type_from_name(const char *pcch)
288 typedef struct _match_if {
291 } *pmatch_if, match_if;
293 static match_if lmatch_if[] = {
299 {0, 0} /* end of list */
303 register pmatch_if pm;
305 for (ii = 0, pm = lmatch_if; pm->mi_name; pm++) {
306 len = strlen(pm->mi_name);
307 if (0 == strncmp(pcch, pm->mi_name, len)) {
308 return (pm->mi_type);
311 return (1); /* in case search fails */
316 typedef struct _conf_if_list {
320 struct _conf_if_list *next;
323 static conf_if_list *conf_list;
325 static struct ifnet *ifnetaddr_list;
329 parse_interface_config(const char *token, char *cptr)
331 conf_if_list *if_ptr, *if_new;
332 char *name, *type, *speed, *ecp;
334 name = strtok(cptr, " \t");
336 config_perror("Missing NAME parameter");
339 type = strtok(NULL, " \t");
341 config_perror("Missing TYPE parameter");
344 speed = strtok(NULL, " \t");
346 config_perror("Missing SPEED parameter");
351 if (strcmp(if_ptr->name, name))
352 if_ptr = if_ptr->next;
356 config_pwarn("Duplicate interface specification");
357 if_new = (conf_if_list *) malloc(sizeof(conf_if_list));
359 config_perror("Out of memory");
362 if_new->speed = strtoul(speed, &ecp, 0);
364 config_perror("Bad SPEED value");
368 if_new->type = strtol(type, &ecp, 0);
369 if (*ecp || if_new->type < 0) {
370 config_perror("Bad TYPE");
374 if_new->name = strdup(name);
376 config_perror("Out of memory");
380 if_new->next = conf_list;
385 free_interface_config(void)
387 conf_if_list *if_ptr = conf_list, *if_next;
389 if_next = if_ptr->next;
402 * vp IN - pointer to variable entry that points here
403 * name IN/OUT - IN/name requested, OUT/name found
404 * length IN/OUT - length of IN/OUT oid's
405 * exact IN - TRUE if an exact match was requested
406 * var_len OUT - length of variable or 0 if function returned
411 WriteMethod writeIfEntry;
413 header_ifEntry(struct variable *vp,
416 int exact, size_t * var_len, WriteMethod ** write_method)
418 #define IFENTRY_NAME_LENGTH 10
419 oid newname[MAX_OID_LEN];
420 register int interface;
423 DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
424 DEBUGMSGOID(("mibII/interfaces", name, *length));
425 DEBUGMSG(("mibII/interfaces", " %d\n", exact));
427 memcpy((char *) newname, (char *) vp->name,
428 (int) vp->namelen * sizeof(oid));
430 * find "next" interface
432 count = Interface_Scan_Get_Count();
433 for (interface = 1; interface <= count; interface++) {
434 newname[IFENTRY_NAME_LENGTH] = (oid) interface;
436 snmp_oid_compare(name, *length, newname,
437 (int) vp->namelen + 1);
438 if ((exact && (result == 0)) || (!exact && (result < 0)))
441 if (interface > count) {
442 DEBUGMSGTL(("mibII/interfaces", "... index out of range\n"));
447 memcpy((char *) name, (char *) newname,
448 ((int) vp->namelen + 1) * sizeof(oid));
449 *length = vp->namelen + 1;
450 #ifdef BUILD_SNMP_SET
451 /* brcm: write is now supported on linux as well */
452 *write_method = writeIfEntry;
454 *write_method = NULL;
455 #endif /* BUILD_SNMP_SET */
456 *var_len = sizeof(long); /* default to 'long' results */
458 DEBUGMSGTL(("mibII/interfaces", "... get I/F stats "));
459 DEBUGMSGOID(("mibII/interfaces", name, *length));
460 DEBUGMSG(("mibII/interfaces", "\n"));
468 var_interfaces(struct variable * vp,
471 int exact, size_t * var_len, WriteMethod ** write_method)
473 if (header_generic(vp, name, length, exact, var_len, write_method) ==
479 long_return = Interface_Scan_Get_Count();
480 return (u_char *) & long_return;
482 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_interfaces\n",
488 #ifdef USE_SYSCTL_IFLIST
490 static u_char *if_list = 0;
491 static const u_char *if_list_end;
492 static size_t if_list_size = 0;
494 struct small_ifaddr {
495 struct in_addr sifa_addr;
496 struct in_addr sifa_netmask;
497 struct in_addr sifa_broadcast;
500 extern const struct sockaddr *get_address(const void *, int, int);
501 extern const struct in_addr *get_in_address(const void *, int, int);
502 static int Interface_Scan_By_Index(int, struct if_msghdr *, char *,
503 struct small_ifaddr *);
504 static int Interface_Get_Ether_By_Index(int, u_char *);
507 Interface_Scan_By_Index(int iindex,
508 struct if_msghdr *if_msg,
509 char *if_name, struct small_ifaddr *sifa)
512 struct if_msghdr *ifp;
513 int have_ifinfo = 0, have_addr = 0;
515 memset(sifa, 0, sizeof(*sifa));
516 for (cp = if_list; cp < if_list_end; cp += ifp->ifm_msglen) {
517 ifp = (struct if_msghdr *) cp;
518 DEBUGMSGTL(("mibII/interfaces", "ifm_type = %d, ifm_index = %d\n",
519 ifp->ifm_type, ifp->ifm_index));
521 switch (ifp->ifm_type) {
524 const struct sockaddr *a;
526 if (ifp->ifm_index == iindex) {
527 a = get_address(ifp + 1, ifp->ifm_addrs, RTA_IFP);
531 ((const struct sockaddr_in *) a)->sin_zero,
532 ((const u_char *) a)[5]);
533 if_name[((const u_char *) a)[5]] = 0;
541 struct ifa_msghdr *ifap = (struct ifa_msghdr *) cp;
543 if (ifap->ifam_index == iindex) {
544 const struct in_addr *ia;
547 * I don't know why the normal get_address() doesn't
548 * work on IRIX 6.2. Maybe this has to do with the
549 * existence of struct sockaddr_new. Hopefully, on
550 * other systems we can simply use get_in_address
551 * three times, with (ifap+1) as the starting
556 *((struct in_addr *) ((char *) (ifap + 1) + 4));
557 ia = get_in_address((char *) (ifap + 1) + 8,
559 ~RTA_NETMASK, RTA_IFA);
563 sifa->sifa_addr = *ia;
564 ia = get_in_address((char *) (ifap + 1) + 8,
565 ifap->ifam_addrs &= ~RTA_NETMASK,
570 sifa->sifa_broadcast = *ia;
576 DEBUGMSGTL(("mibII/interfaces",
577 "routing socket: unknown message type %d\n",
581 if (have_ifinfo && have_addr) {
583 } else if (have_ifinfo && !(if_msg->ifm_flags & IFF_UP))
591 Interface_Scan_Get_Count(void)
594 struct if_msghdr *ifp;
597 Interface_Scan_Init();
600 for (cp = if_list, n = 0; cp < if_list_end; cp += ifp->ifm_msglen) {
601 ifp = (struct if_msghdr *) cp;
603 if (ifp->ifm_type == RTM_IFINFO) {
612 Interface_Scan_Init(void)
614 int name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
617 if (sysctl(name, sizeof(name) / sizeof(int), 0, &size, 0, 0) == -1) {
618 snmp_log(LOG_ERR, "sysctl size fail\n");
620 if (if_list == 0 || if_list_size < size) {
627 if ((if_list = malloc(size)) == NULL) {
629 "out of memory allocating route table (size = %d)\n", size);
636 if (sysctl(name, sizeof(name) / sizeof(int),
637 if_list, &size, 0, 0) == -1) {
638 snmp_log(LOG_ERR, "sysctl get fail\n");
640 if_list_end = if_list + size;
645 var_ifEntry(struct variable *vp,
648 int exact, size_t * var_len, WriteMethod ** write_method)
651 struct if_msghdr if_msg;
652 static char if_name[100];
653 struct small_ifaddr sifa;
657 header_ifEntry(vp, name, length, exact, var_len, write_method);
658 if (interface == MATCH_FAILED)
661 if (Interface_Scan_By_Index(interface, &if_msg, if_name, &sifa) != 0)
666 long_return = interface;
667 return (u_char *) & long_return;
670 *var_len = strlen(if_name);
671 return (u_char *) cp;
673 long_return = (long) if_msg.ifm_data.ifi_type;
674 return (u_char *) & long_return;
676 long_return = (long) if_msg.ifm_data.ifi_mtu;
677 return (u_char *) & long_return;
679 #if STRUCT_IFNET_HAS_IF_BAUDRATE_IFS_VALUE
680 long_return = (u_long) if_msg.ifm_data.ifi_baudrate.ifs_value <<
681 if_msg.ifm_data.ifi_baudrate.ifs_log2;
683 long_return = (u_long) if_msg.ifm_data.ifi_baudrate;
685 return (u_char *) & long_return;
692 long_return = if_msg.ifm_flags & IFF_UP ? 1 : 2;
693 return (u_char *) & long_return;
695 long_return = if_msg.ifm_flags & IFF_RUNNING ? 1 : 2;
696 return (u_char *) & long_return;
701 long_return = (u_long) if_msg.ifm_data.ifi_ibytes;
702 return (u_char *) & long_return;
705 (u_long) if_msg.ifm_data.ifi_ipackets -
706 if_msg.ifm_data.ifi_imcasts;
707 return (u_char *) & long_return;
709 long_return = (u_long) if_msg.ifm_data.ifi_imcasts;
710 return (u_char *) & long_return;
712 long_return = (u_long) if_msg.ifm_data.ifi_iqdrops;
713 return (u_char *) & long_return;
715 long_return = (u_long) if_msg.ifm_data.ifi_ierrors;
716 return (u_char *) & long_return;
717 case IFINUNKNOWNPROTOS:
718 long_return = (u_long) if_msg.ifm_data.ifi_noproto;
719 return (u_char *) & long_return;
721 long_return = (u_long) if_msg.ifm_data.ifi_obytes;
722 return (u_char *) & long_return;
725 (u_long) if_msg.ifm_data.ifi_opackets -
726 if_msg.ifm_data.ifi_omcasts;
727 return (u_char *) & long_return;
728 case IFOUTNUCASTPKTS:
729 long_return = (u_long) if_msg.ifm_data.ifi_omcasts;
730 return (u_char *) & long_return;
733 long_return = (u_long) if_msg.ifm_data.ifi_odrops;
740 return (u_char *) & long_return;
742 long_return = (u_long) if_msg.ifm_data.ifi_oerrors;
743 return (u_char *) & long_return;
748 if (if_msg.ifm_data.ifi_lastchange.tv_sec == 0 &&
749 if_msg.ifm_data.ifi_lastchange.tv_usec == 0)
751 else if (if_msg.ifm_data.ifi_lastchange.tv_sec < starttime.tv_sec)
754 long_return = (u_long)
755 ((if_msg.ifm_data.ifi_lastchange.tv_sec -
756 starttime.tv_sec) * 100 +
757 (if_msg.ifm_data.ifi_lastchange.tv_usec -
758 starttime.tv_usec) / 10000);
761 return (u_char *) & long_return;
768 Interface_Scan_Next(short *Index,
770 struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
775 #else /* not USE_SYSCTL_IFLIST */
777 /*********************
779 * Kernel & interface information,
780 * and internal forward declarations
782 *********************/
784 #ifndef HAVE_NET_IF_MIB_H
788 static int Interface_Scan_By_Index(int, char *, struct ifnet *,
790 static int Interface_Get_Ether_By_Index(int, u_char *);
792 static int Interface_Scan_By_Index(int, char *, nmapi_phystat *);
798 /*********************
800 * System specific implementation functions
802 *********************/
809 var_ifEntry(struct variable *vp,
812 int exact, size_t * var_len, WriteMethod ** write_method)
814 static struct ifnet ifnet;
816 static struct in_ifaddr in_ifaddr;
817 static char Name[16];
819 conf_if_list *if_ptr = conf_list;
820 #if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC
825 header_ifEntry(vp, name, length, exact, var_len, write_method);
826 if (interface == MATCH_FAILED)
829 Interface_Scan_By_Index(interface, Name, &ifnet, &in_ifaddr);
830 while (if_ptr && strcmp(Name, if_ptr->name))
831 if_ptr = if_ptr->next;
835 long_return = interface;
836 return (u_char *) & long_return;
839 *var_len = strlen(cp);
840 return (u_char *) cp;
843 long_return = if_ptr->type;
845 #if STRUCT_IFNET_HAS_IF_TYPE
846 long_return = ifnet.if_type;
848 long_return = 1; /* OTHER */
851 return (u_char *) & long_return;
853 long_return = (long) ifnet.if_mtu;
854 return (u_char *) & long_return;
858 long_return = if_ptr->speed;
860 #if STRUCT_IFNET_HAS_IF_BAUDRATE
861 long_return = ifnet.if_baudrate;
862 #elif STRUCT_IFNET_HAS_IF_SPEED
863 long_return = ifnet.if_speed;
864 #elif STRUCT_IFNET_HAS_IF_TYPE && defined(IFT_ETHER)
865 if (ifnet.if_type == IFT_ETHER)
866 long_return = 10000000;
867 if (ifnet.if_type == IFT_P10)
868 long_return = 10000000;
869 if (ifnet.if_type == IFT_P80)
870 long_return = 80000000;
871 if (ifnet.if_type == IFT_ISDNBASIC)
872 long_return = 64000; /* EDSS1 only */
873 if (ifnet.if_type == IFT_ISDNPRIMARY)
874 long_return = 64000 * 30;
879 long_return = (u_long) 10000000;
882 return (u_char *) & long_return;
884 Interface_Get_Ether_By_Index(interface, return_buf);
886 if ((return_buf[0] == 0) && (return_buf[1] == 0) &&
887 (return_buf[2] == 0) && (return_buf[3] == 0) &&
888 (return_buf[4] == 0) && (return_buf[5] == 0))
890 return (u_char *) return_buf;
892 long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
893 return (u_char *) & long_return;
895 long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
896 return (u_char *) & long_return;
898 #if defined(STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC) && !(defined(freebsd2) && __FreeBSD_version < 199607)
900 * XXX - SNMP's ifLastchange is time when op. status changed
901 * * FreeBSD's if_lastchange is time when packet was input or output
902 * * (at least in 2.1.0-RELEASE. Changed in later versions of the kernel?)
905 * FreeBSD's if_lastchange before the 2.1.5 release is the time when
906 * * a packet was last input or output. In the 2.1.5 and later releases,
907 * * this is fixed, thus the 199607 comparison.
909 if (ifnet.if_lastchange.tv_sec == 0 &&
910 ifnet.if_lastchange.tv_usec == 0)
912 else if (ifnet.if_lastchange.tv_sec < starttime.tv_sec)
915 long_return = (u_long)
916 ((ifnet.if_lastchange.tv_sec - starttime.tv_sec) * 100
917 + (ifnet.if_lastchange.tv_usec -
918 starttime.tv_usec) / 10000);
921 #ifdef BRCM_IFLASTCHANGE_SUPPORT
922 /* brcm - if_lastchange now supported */
923 long_return = ifnet.if_lastchange;
930 return (u_char *) & long_return;
932 #ifdef STRUCT_IFNET_HAS_IF_IBYTES
933 long_return = (u_long) ifnet.if_ibytes;
938 long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
940 return (u_char *) & long_return;
943 long_return = (u_long) ifnet.if_ipackets;
944 #if STRUCT_IFNET_HAS_IF_IMCASTS
945 long_return -= (u_long) ifnet.if_imcasts;
948 return (u_char *) & long_return;
950 #if STRUCT_IFNET_HAS_IF_IMCASTS
951 long_return = (u_long) ifnet.if_imcasts;
956 long_return = (u_long) 0; /* XXX */
958 return (u_char *) & long_return;
960 #if STRUCT_IFNET_HAS_IF_IQDROPS
961 long_return = (u_long) ifnet.if_iqdrops;
966 long_return = (u_long) 0; /* XXX */
968 return (u_char *) & long_return;
970 long_return = (u_long) ifnet.if_ierrors;
971 return (u_char *) & long_return;
972 case IFINUNKNOWNPROTOS:
973 #if STRUCT_IFNET_HAS_IF_NOPROTO
974 long_return = (u_long) ifnet.if_noproto;
979 long_return = (u_long) 0; /* XXX */
981 return (u_char *) & long_return;
983 #ifdef STRUCT_IFNET_HAS_IF_OBYTES
984 long_return = (u_long) ifnet.if_obytes;
989 long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
991 return (u_char *) & long_return;
994 long_return = (u_long) ifnet.if_opackets;
995 #if STRUCT_IFNET_HAS_IF_OMCASTS
996 long_return -= (u_long) ifnet.if_omcasts;
999 return (u_char *) & long_return;
1000 case IFOUTNUCASTPKTS:
1001 #if STRUCT_IFNET_HAS_IF_OMCASTS
1002 long_return = (u_long) ifnet.if_omcasts;
1007 long_return = (u_long) 0; /* XXX */
1009 return (u_char *) & long_return;
1011 long_return = ifnet.if_snd.ifq_drops;
1012 return (u_char *) & long_return;
1014 long_return = ifnet.if_oerrors;
1015 return (u_char *) & long_return;
1017 long_return = ifnet.if_snd.ifq_len;
1018 return (u_char *) & long_return;
1020 *var_len = nullOidLen;
1021 return (u_char *) nullOid;
1023 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
1032 var_ifEntry(struct variable *vp,
1035 int exact, size_t * var_len, WriteMethod ** write_method)
1038 static nmapi_phystat ifnet;
1040 static struct ifnet ifnet;
1042 register int interface;
1043 #if !defined(hpux11)
1044 static struct in_ifaddr in_ifaddrVar;
1047 static char Name[MAX_PHYSADDR_LEN];
1049 static char Name[16];
1052 #if STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC
1055 #if !defined(hpux11)
1056 struct nmparms hp_nmparms;
1057 static mib_ifEntry hp_ifEntry;
1059 int hp_len = sizeof(hp_ifEntry);
1064 header_ifEntry(vp, name, length, exact, var_len, write_method);
1065 if (interface == MATCH_FAILED)
1069 Interface_Scan_By_Index(interface, Name, &ifnet);
1071 Interface_Scan_By_Index(interface, Name, &ifnet, &in_ifaddrVar);
1074 #if !defined(hpux11)
1076 * Additional information about the interfaces is available under
1077 * HP-UX through the network management interface '/dev/netman'
1079 hp_ifEntry.ifIndex = interface;
1080 hp_nmparms.objid = ID_ifEntry;
1081 hp_nmparms.buffer = (char *) &hp_ifEntry;
1082 hp_nmparms.len = &hp_len;
1083 if ((hp_fd = open("/dev/netman", O_RDONLY)) != -1) {
1084 if (ioctl(hp_fd, NMIOGET, &hp_nmparms) != -1) {
1088 hp_fd = -1; /* failed */
1093 switch (vp->magic) {
1095 long_return = interface;
1096 return (u_char *) & long_return;
1099 cp = ifnet.if_entry.ifDescr;
1102 cp = hp_ifEntry.ifDescr;
1106 *var_len = strlen(cp);
1107 return (u_char *) cp;
1110 long_return = ifnet.if_entry.ifType;
1113 long_return = hp_ifEntry.ifType;
1115 long_return = 1; /* OTHER */
1117 return (u_char *) & long_return;
1120 long_return = (long) ifnet.if_entry.ifMtu;
1122 long_return = (long) ifnet.if_mtu;
1124 return (u_char *) & long_return;
1128 long_return = ifnet.if_entry.ifSpeed;
1131 long_return = hp_ifEntry.ifSpeed;
1133 long_return = (u_long) 1; /* OTHER */
1135 return (u_char *) & long_return;
1138 *var_len = ifnet.if_entry.ifPhysAddress.o_length;
1139 return (u_char *) ifnet.if_entry.ifPhysAddress.o_bytes;
1141 Interface_Get_Ether_By_Index(interface, return_buf);
1143 if ((return_buf[0] == 0) && (return_buf[1] == 0) &&
1144 (return_buf[2] == 0) && (return_buf[3] == 0) &&
1145 (return_buf[4] == 0) && (return_buf[5] == 0))
1147 return (u_char *) return_buf;
1151 long_return = ifnet.if_entry.ifAdmin;
1153 long_return = ifnet.if_flags & IFF_UP ? 1 : 2;
1155 return (u_char *) & long_return;
1158 long_return = ifnet.if_entry.ifOper;
1160 long_return = ifnet.if_flags & IFF_RUNNING ? 1 : 2;
1162 return (u_char *) & long_return;
1165 long_return = ifnet.if_entry.ifLastChange;
1168 long_return = hp_ifEntry.ifLastChange;
1170 long_return = 0; /* XXX */
1172 return (u_char *) & long_return;
1175 long_return = ifnet.if_entry.ifInOctets;
1178 long_return = hp_ifEntry.ifInOctets;
1180 long_return = (u_long) ifnet.if_ipackets * 308; /* XXX */
1182 return (u_char *) & long_return;
1185 long_return = ifnet.if_entry.ifInUcastPkts;
1188 long_return = hp_ifEntry.ifInUcastPkts;
1190 long_return = (u_long) ifnet.if_ipackets;
1192 return (u_char *) & long_return;
1193 case IFINNUCASTPKTS:
1195 long_return = ifnet.if_entry.ifInNUcastPkts;
1198 long_return = hp_ifEntry.ifInNUcastPkts;
1200 long_return = (u_long) 0; /* XXX */
1202 return (u_char *) & long_return;
1205 long_return = ifnet.if_entry.ifInDiscards;
1208 long_return = hp_ifEntry.ifInDiscards;
1210 long_return = (u_long) 0; /* XXX */
1212 return (u_char *) & long_return;
1215 long_return = ifnet.if_entry.ifInErrors;
1217 long_return = ifnet.if_ierrors;
1219 return (u_char *) & long_return;
1220 case IFINUNKNOWNPROTOS:
1222 long_return = ifnet.if_entry.ifInUnknownProtos;
1225 long_return = hp_ifEntry.ifInUnknownProtos;
1227 long_return = (u_long) 0; /* XXX */
1229 return (u_char *) & long_return;
1232 long_return = ifnet.if_entry.ifOutOctets;
1235 long_return = hp_ifEntry.ifOutOctets;
1237 long_return = (u_long) ifnet.if_opackets * 308; /* XXX */
1239 return (u_char *) & long_return;
1240 case IFOUTUCASTPKTS:
1242 long_return = ifnet.if_entry.ifOutUcastPkts;
1245 long_return = hp_ifEntry.ifOutUcastPkts;
1247 long_return = (u_long) ifnet.if_opackets;
1249 return (u_char *) & long_return;
1250 case IFOUTNUCASTPKTS:
1252 long_return = ifnet.if_entry.ifOutNUcastPkts;
1255 long_return = hp_ifEntry.ifOutNUcastPkts;
1257 long_return = (u_long) 0; /* XXX */
1259 return (u_char *) & long_return;
1262 long_return = ifnet.if_entry.ifOutDiscards;
1264 long_return = ifnet.if_snd.ifq_drops;
1266 return (u_char *) & long_return;
1269 long_return = ifnet.if_entry.ifOutErrors;
1271 long_return = ifnet.if_oerrors;
1273 return (u_char *) & long_return;
1276 long_return = ifnet.if_entry.ifOutQlen;
1278 long_return = ifnet.if_snd.ifq_len;
1280 return (u_char *) & long_return;
1282 *var_len = nullOidLen;
1283 return (u_char *) nullOid;
1285 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
1292 #else /* solaris2 */
1295 IF_cmp(void *addr, void *ep)
1297 DEBUGMSGTL(("mibII/interfaces", "... IF_cmp %d %d\n",
1298 ((mib2_ifEntry_t *) ep)->ifIndex,
1299 ((mib2_ifEntry_t *) addr)->ifIndex));
1300 if (((mib2_ifEntry_t *) ep)->ifIndex ==
1301 ((mib2_ifEntry_t *) addr)->ifIndex)
1308 var_ifEntry(struct variable * vp,
1311 int exact, size_t * var_len, WriteMethod ** write_method)
1314 mib2_ifEntry_t ifstat;
1318 header_ifEntry(vp, name, length, exact, var_len, write_method);
1319 if (interface == MATCH_FAILED)
1322 if (getMibstat(MIB_INTERFACES, &ifstat, sizeof(mib2_ifEntry_t),
1323 GET_EXACT, &IF_cmp, &interface) != 0) {
1324 DEBUGMSGTL(("mibII/interfaces", "... no mib stats\n"));
1327 switch (vp->magic) {
1329 long_return = ifstat.ifIndex;
1330 return (u_char *) & long_return;
1332 *var_len = ifstat.ifDescr.o_length;
1333 (void) memcpy(return_buf, ifstat.ifDescr.o_bytes, *var_len);
1334 return (u_char *) return_buf;
1336 long_return = (u_long) ifstat.ifType;
1337 return (u_char *) & long_return;
1339 long_return = (u_long) ifstat.ifMtu;
1340 return (u_char *) & long_return;
1342 long_return = (u_long) ifstat.ifSpeed;
1343 return (u_char *) & long_return;
1345 *var_len = ifstat.ifPhysAddress.o_length;
1346 (void) memcpy(return_buf, ifstat.ifPhysAddress.o_bytes, *var_len);
1347 return (u_char *) return_buf;
1349 long_return = (u_long) ifstat.ifAdminStatus;
1350 return (u_char *) & long_return;
1352 long_return = (u_long) ifstat.ifOperStatus;
1353 return (u_char *) & long_return;
1355 long_return = (u_long) ifstat.ifLastChange;
1356 return (u_char *) & long_return;
1358 long_return = (u_long) ifstat.ifInOctets;
1359 return (u_char *) & long_return;
1361 long_return = (u_long) ifstat.ifInUcastPkts;
1362 return (u_char *) & long_return;
1363 case IFINNUCASTPKTS:
1364 long_return = (u_long) ifstat.ifInNUcastPkts;
1365 return (u_char *) & long_return;
1367 long_return = (u_long) ifstat.ifInDiscards;
1368 return (u_char *) & long_return;
1370 long_return = (u_long) ifstat.ifInErrors;
1371 return (u_char *) & long_return;
1372 case IFINUNKNOWNPROTOS:
1373 long_return = (u_long) ifstat.ifInUnknownProtos;
1374 return (u_char *) & long_return;
1376 long_return = (u_long) ifstat.ifOutOctets;
1377 return (u_char *) & long_return;
1378 case IFOUTUCASTPKTS:
1379 long_return = (u_long) ifstat.ifOutUcastPkts;
1380 return (u_char *) & long_return;
1381 case IFOUTNUCASTPKTS:
1382 long_return = (u_long) ifstat.ifOutNUcastPkts;
1383 return (u_char *) & long_return;
1385 long_return = (u_long) ifstat.ifOutDiscards;
1386 return (u_char *) & long_return;
1388 long_return = (u_long) ifstat.ifOutErrors;
1389 return (u_char *) & long_return;
1391 long_return = (u_long) ifstat.ifOutQLen;
1392 return (u_char *) & long_return;
1394 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
1400 #endif /* solaris2 */
1404 /*********************
1406 * Internal implementation functions
1408 *********************/
1413 #if !defined(sunV3) && !defined(linux) && !defined(hpux11)
1414 static struct in_ifaddr savein_ifaddr;
1416 #if !defined(hpux11)
1417 static struct ifnet *ifnetaddr, saveifnet, *saveifnetaddr;
1418 static char saveName[16];
1420 static int saveIndex = 0;
1423 * Determines network interface speed. It is system specific. Only linux
1424 * realization is made.
1426 unsigned int getIfSpeed(int fd, struct ifreq ifr){
1427 unsigned int retspeed = 10000000;
1429 /* the code is based on mii-diag utility by Donald Becker
1430 * see ftp://ftp.scyld.com/pub/diag/mii-diag.c
1432 ushort *data = (ushort *)(&ifr.ifr_data);
1433 /* brcm: not used, remove warning */
1434 /* unsigned int *data32 = (unsigned int *)(&ifr.ifr_data); */
1436 unsigned char new_ioctl_nums = 0;
1439 ushort bmcr, bmsr, nway_advert, lkpar;
1440 const unsigned int media_speeds[] = {10000000, 10000000, 100000000, 100000000, 10000000, 0};
1441 /* It corresponds to "10baseT", "10baseT-FD", "100baseTx", "100baseTx-FD", "100baseT4", "Flow-control", 0, */
1446 if (ioctl(fd, 0x8947, &ifr) >= 0) {
1448 } else if (ioctl(fd, SIOCDEVPRIVATE, &ifr) >= 0) {
1451 DEBUGMSGTL(("mibII/interfaces", "SIOCGMIIPHY on %s failed\n", ifr.ifr_name));
1454 /* Begin getting mii register values */
1456 for (mii_reg = 0; mii_reg < 8; mii_reg++){
1459 if(ioctl(fd, new_ioctl_nums ? 0x8948 : SIOCDEVPRIVATE+1, &ifr) <0){
1460 DEBUGMSGTL(("mibII/interfaces", "SIOCGMIIREG on %s failed\n", ifr.ifr_name));
1462 mii_val[mii_reg] = data[3];
1464 /*Parsing of mii values*/
1465 /*Invalid basic mode control register*/
1466 if (mii_val[0] == 0xffff || mii_val[1] == 0x0000) {
1467 DEBUGMSGTL(("mibII/interfaces", "No MII transceiver present!.\n"));
1470 /* Descriptive rename. */
1471 bmcr = mii_val[0]; /*basic mode control register*/
1472 bmsr = mii_val[1]; /* basic mode status register*/
1473 nway_advert = mii_val[4]; /* autonegotiation advertisement*/
1474 lkpar = mii_val[5]; /*link partner ability*/
1476 /*Check for link existence, returns 0 if link is absent*/
1477 if ((bmsr & 0x0016) != 0x0004){
1478 DEBUGMSGTL(("mibII/interfaces", "No link...\n"));
1483 if(!(bmcr & 0x1000) ){
1484 DEBUGMSGTL(("mibII/interfaces", "Auto-negotiation disabled.\n"));
1485 retspeed = bmcr & 0x2000 ? 100000000 : 10000000;
1488 /* Link partner got our advertised abilities */
1489 if (lkpar & 0x4000) {
1490 int negotiated = nway_advert & lkpar & 0x3e0;
1491 int max_capability = 0;
1492 /* Scan for the highest negotiated capability, highest priority
1493 (100baseTx-FDX) to lowest (10baseT-HDX). */
1494 int media_priority[] = {8, 9, 7, 6, 5}; /* media_names[i-5] */
1495 for (i = 0; media_priority[i]; i++){
1496 if (negotiated & (1 << media_priority[i])) {
1497 max_capability = media_priority[i];
1502 retspeed = media_speeds[max_capability - 5];
1504 DEBUGMSGTL(("mibII/interfaces", "No common media type was autonegotiated!\n"));
1514 Interface_Scan_Init(void)
1517 char line[256], ifname_buf[64], *ifname, *ptr;
1519 struct ifnet **ifnetaddr_ptr;
1521 unsigned long rec_pkt, rec_oct, rec_err, rec_drop;
1522 unsigned long snd_pkt, snd_oct, snd_err, snd_drop, coll;
1524 conf_if_list *if_ptr;
1525 const char *scan_line_2_2 =
1526 "%lu %lu %lu %lu %*lu %*lu %*lu %*lu %lu %lu %lu %lu %*lu %lu";
1527 const char *scan_line_2_0 =
1528 "%lu %lu %*lu %*lu %*lu %lu %lu %*lu %*lu %lu";
1529 const char *scan_line_to_use;
1531 PIOCTL_MIB_INFO pNetDevMibInfo;
1532 IOCTL_MIB_INFO netDevMibInfo;
1535 #if !defined(hpux11)
1536 auto_nlist(IFNET_SYMBOL, (char *) &ifnetaddr, sizeof(ifnetaddr));
1544 while (ifnetaddr_list) {
1545 struct ifnet *old = ifnetaddr_list;
1546 ifnetaddr_list = ifnetaddr_list->if_next;
1553 ifnetaddr_ptr = &ifnetaddr_list;
1555 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1556 DEBUGMSGTL(("snmpd",
1557 "socket open failure in Interface_Scan_Init\n"));
1558 return; /** exit (1); **/
1562 * build up ifnetaddr list by hand:
1566 * at least linux v1.3.53 says EMFILE without reason...
1568 if (!(devin = fopen("/proc/net/dev", "r"))) {
1570 snmp_log(LOG_ERR, "cannot open /proc/net/dev - continuing...\n");
1571 return; /** exit (1); **/
1577 * read the second line (a header) and determine the fields we
1578 * should read from. This should be done in a better way by
1579 * actually looking for the field names we want. But thats too
1580 * much work for today. -- Wes
1582 fgets(line, sizeof(line), devin);
1583 fgets(line, sizeof(line), devin);
1584 if (strstr(line, "compressed")) {
1585 scan_line_to_use = scan_line_2_2;
1586 DEBUGMSGTL(("mibII/interfaces",
1587 "using linux 2.2 kernel /proc/net/dev\n"));
1589 scan_line_to_use = scan_line_2_0;
1590 DEBUGMSGTL(("mibII/interfaces",
1591 "using linux 2.0 kernel /proc/net/dev\n"));
1595 while (fgets(line, sizeof(line), devin)) {
1597 char *stats, *ifstart = line;
1599 if (line[strlen(line) - 1] == '\n')
1600 line[strlen(line) - 1] = '\0';
1602 while (*ifstart && *ifstart == ' ')
1605 if (!*ifstart || ((stats = strrchr(ifstart, ':')) == NULL)) {
1607 "/proc/net/dev data format error, line ==|%s|", line);
1610 if ((scan_line_to_use == scan_line_2_2) && ((stats - line) < 6)) {
1612 "/proc/net/dev data format error, line ==|%s|", line);
1616 strncpy(ifname_buf, ifstart, sizeof(ifname_buf));
1617 ifname_buf[ sizeof(ifname_buf)-1 ] = 0;
1619 while (*stats == ' ')
1622 if ((scan_line_to_use == scan_line_2_2 &&
1623 sscanf(stats, scan_line_to_use, &rec_oct, &rec_pkt, &rec_err,
1624 &rec_drop, &snd_oct, &snd_pkt, &snd_err, &snd_drop,
1625 &coll) != 9) || (scan_line_to_use == scan_line_2_0
1626 && sscanf(stats, scan_line_to_use,
1630 if ((scan_line_to_use == scan_line_2_2)
1631 && !strstr(line, "No statistics available"))
1633 "/proc/net/dev data format error, line ==|%s|",
1638 nnew = (struct ifnet *) calloc(1, sizeof(struct ifnet));
1640 break; /* alloc error */
1645 *ifnetaddr_ptr = nnew;
1646 ifnetaddr_ptr = &nnew->if_next;
1650 * linux previous to 1.3.~13 may miss transmitted loopback pkts:
1652 if (!strcmp(ifname_buf, "lo") && rec_pkt > 0 && !snd_pkt)
1655 nnew->if_ipackets = rec_pkt;
1656 nnew->if_ierrors = rec_err;
1657 nnew->if_opackets = snd_pkt;
1658 nnew->if_oerrors = snd_err;
1659 nnew->if_collisions = coll;
1660 if (scan_line_to_use == scan_line_2_2) {
1661 nnew->if_ibytes = rec_oct;
1662 nnew->if_obytes = snd_oct;
1663 nnew->if_iqdrops = rec_drop;
1664 nnew->if_snd.ifq_drops = snd_drop;
1666 nnew->if_ibytes = rec_pkt * 308;
1667 nnew->if_obytes = snd_pkt * 308;
1671 * ifnames are given as `` eth0'': split in ``eth'' and ``0'':
1673 for (ifname = ifname_buf; *ifname && *ifname == ' '; ifname++);
1676 * set name and interface# :
1678 nnew->if_name = (char *) strdup(ifname);
1679 for (ptr = nnew->if_name; *ptr && (*ptr < '0' || *ptr > '9');
1681 nnew->if_unit = strdup(*ptr ? ptr : "");
1684 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1685 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1686 if (ioctl(fd, SIOCGIFADDR, &ifrq) < 0)
1687 memset((char *) &nnew->if_addr, 0, sizeof(nnew->if_addr));
1689 nnew->if_addr = ifrq.ifr_addr;
1691 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1692 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1693 if (ioctl(fd, SIOCGIFBRDADDR, &ifrq) < 0)
1694 memset((char *) &nnew->ifu_broadaddr, 0,
1695 sizeof(nnew->ifu_broadaddr));
1697 nnew->ifu_broadaddr = ifrq.ifr_broadaddr;
1699 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1700 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1701 if (ioctl(fd, SIOCGIFNETMASK, &ifrq) < 0)
1702 memset((char *) &nnew->ia_subnetmask, 0,
1703 sizeof(nnew->ia_subnetmask));
1705 nnew->ia_subnetmask = ifrq.ifr_netmask;
1707 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1708 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1709 nnew->if_flags = ioctl(fd, SIOCGIFFLAGS, &ifrq) < 0
1710 ? 0 : ifrq.ifr_flags;
1714 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1715 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1716 if (ioctl(fd, SIOCGIFHWADDR, &ifrq) < 0)
1717 memset(nnew->if_hwaddr, (0), 6);
1719 memcpy(nnew->if_hwaddr, ifrq.ifr_hwaddr.sa_data, 6);
1721 #ifdef ARPHRD_LOOPBACK
1722 switch (ifrq.ifr_hwaddr.sa_family) {
1724 nnew->if_type = IF_IANAIFTYPE_ETHERNETCSMACD;
1727 case ARPHRD_TUNNEL6:
1732 nnew->if_type = IF_IANAIFTYPE_TUNNEL;
1738 nnew->if_type = IF_IANAIFTYPE_SLIP;
1741 nnew->if_type = IF_IANAIFTYPE_PPP;
1743 case ARPHRD_LOOPBACK:
1744 nnew->if_type = IF_IANAIFTYPE_SOFTWARELOOPBACK;
1745 break; /* softwareLoopback */
1747 nnew->if_type = IF_IANAIFTYPE_FDDI;
1750 nnew->if_type = IF_IANAIFTYPE_ARCNETPLUS;
1752 case ARPHRD_LOCALTLK:
1753 nnew->if_type = IF_IANAIFTYPE_LOCALTALK;
1757 nnew->if_type = IF_IANAIFTYPE_HIPPI;
1762 nnew->if_type = IF_IANAIFTYPE_ATM;
1767 nnew->if_type = IF_IANAIFTYPE_AAL5;
1770 nnew->if_type = IF_IANAIFTYPE_ADSL;
1774 * XXX: more if_arp.h:ARPHDR_xxx to IANAifType mappings...
1780 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1781 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1782 nnew->if_metric = ioctl(fd, SIOCGIFMETRIC, &ifrq) < 0
1783 ? 0 : ifrq.ifr_metric;
1786 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1787 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1788 nnew->if_mtu = (ioctl(fd, SIOCGIFMTU, &ifrq) < 0)
1794 #ifdef BRCM_IFLASTCHANGE_SUPPORT
1795 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1796 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1797 nnew->if_lastchange = (ioctl(fd, SIOCGIFTRANSSTART, &ifrq) < 0)
1798 ? 0 : ifrq.ifr_ifru.ifru_ivalue;
1800 nnew->if_lastchange = 0;
1802 for (if_ptr = conf_list; if_ptr; if_ptr = if_ptr->next)
1803 if (!strcmp(if_ptr->name, ifname))
1807 nnew->if_type = if_ptr->type;
1808 nnew->if_speed = if_ptr->speed;
1811 * do only guess if_type from name, if we could not read
1812 * * it before from SIOCGIFHWADDR
1815 nnew->if_type = if_type_from_name(nnew->if_name);
1816 switch (nnew->if_type)
1818 case IF_IANAIFTYPE_ETHERNETCSMACD:
1819 case IF_IANAIFTYPE_SOFTWARELOOPBACK:
1820 strncpy(ifrq.ifr_name, ifname, sizeof(ifrq.ifr_name));
1821 ifrq.ifr_name[ sizeof(ifrq.ifr_name)-1 ] = 0;
1822 ifrq.ifr_data = (char*)&netDevMibInfo;
1824 if (ioctl(fd, SIOCMIBINFO, &ifrq) < 0) {
1828 pNetDevMibInfo = (IOCTL_MIB_INFO *)(ifrq.ifr_data);
1829 nnew->if_speed = pNetDevMibInfo->ulIfSpeed;
1832 case IF_IANAIFTYPE_TOKENRING:
1833 nnew->if_speed = 4000000;
1835 case IF_IANAIFTYPE_ADSL:
1836 nnew->if_speed = getAdslIfSpeed();
1837 if (getAdslOperStatus() == IF_OPER_STATUS_UP)
1838 nnew->if_flags |= IFF_RUNNING;
1840 nnew->if_flags &= ~IFF_RUNNING;
1841 if (getAdslAdminStatus() == IF_ADMIN_STATUS_UP)
1842 nnew->if_flags |= IFF_UP;
1844 nnew->if_flags &= ~IFF_UP;
1846 case IF_IANAIFTYPE_ATM:
1847 case IF_IANAIFTYPE_AAL5:
1848 nnew->if_speed = getAdslIfSpeed();
1849 if (getAtmIntfOperStatus() == IF_OPER_STATUS_UP)
1850 nnew->if_flags |= IFF_RUNNING;
1852 nnew->if_flags &= ~IFF_RUNNING;
1853 if (getAtmIntfAdminStatus() == IF_ADMIN_STATUS_UP)
1854 nnew->if_flags |= IFF_UP;
1856 nnew->if_flags &= ~IFF_UP;
1863 } /* while (fgets ... */
1865 ifnetaddr = ifnetaddr_list;
1867 if (snmp_get_do_debugging()) {
1869 struct ifnet *x = ifnetaddr;
1870 DEBUGMSGTL(("mibII/interfaces", "* see: known interfaces:"));
1872 DEBUGMSG(("mibII/interfaces", " %s", x->if_name));
1875 DEBUGMSG(("mibII/interfaces", "\n"));
1886 #if defined(sunV3) || defined(linux)
1888 * ** 4.2 BSD doesn't have ifaddr
1892 Interface_Scan_Next(short *Index,
1894 struct ifnet *Retifnet, struct in_ifaddr *dummy)
1901 * Get the "ifnet" structure and extract the device name
1904 klookup((unsigned long) ifnetaddr, (char *) &ifnet, sizeof ifnet);
1905 klookup((unsigned long) ifnet.if_name, (char *) saveName,
1909 strncpy(saveName, ifnet.if_name, sizeof(saveName));
1911 if (strcmp(saveName, "ip") == 0) {
1912 ifnetaddr = ifnet.if_next;
1918 saveName[sizeof(saveName) - 1] = '\0';
1919 cp = (char *) strchr(saveName, '\0');
1921 strncat(cp, ifnet.if_unit, sizeof(saveName)-strlen(saveName)-1);
1922 saveName[sizeof(saveName) - 1] = '\0';
1924 string_append_int(cp, ifnet.if_unit);
1926 if (1 || strcmp(saveName, "lo0") != 0) { /* XXX */
1929 *Index = ++saveIndex;
1933 strcpy(Name, saveName);
1935 saveifnetaddr = ifnetaddr;
1936 ifnetaddr = ifnet.if_next;
1938 return (1); /* DONE */
1940 ifnetaddr = ifnet.if_next;
1942 return (0); /* EOF */
1947 Interface_Index_By_Name(char *Name, int Len)
1952 Interface_Scan_Init();
1954 while (Interface_Scan_Next(&ifIndex, ifName, NULL, NULL)
1955 && strcmp(Name, ifName));
1958 /*brcm: if an interface is not found, we should return 0 rather than the
1959 last index in the interface list */
1960 while ((Interface_Scan_Next(&ifIndex, ifName, NULL, NULL)) != 0)
1962 if (strcmp(Name, ifName) == 0)
1966 #endif /* brcm bug fix */
1971 #else /* sunV3 || linux */
1973 #if defined(netbsd1) || defined(openbsd2)
1974 #define ia_next ia_list.tqe_next
1975 #define if_next if_list.tqe_next
1981 Interface_Scan_Next(short *Index, char *Name, nmapi_phystat * Retifnet)
1983 static nmapi_phystat *if_ptr = (nmapi_phystat *) 0;
1984 int count = Interface_Scan_Get_Count();
1991 (nmapi_phystat *) malloc(sizeof(nmapi_phystat) * count);
1993 return (0); /* EOF */
1996 if (saveIndex >= count)
1997 return (0); /* EOF */
1999 ulen = (unsigned int) count *sizeof(nmapi_phystat);
2000 if ((ret = get_physical_stat(if_ptr, &ulen)) < 0)
2001 return (0); /* EOF */
2004 *Retifnet = if_ptr[saveIndex];
2006 strcpy(Name, if_ptr[saveIndex].nm_device);
2010 return (1); /* DONE */
2016 Interface_Scan_Next(short *Index,
2018 struct ifnet *Retifnet, struct in_ifaddr *Retin_ifaddr)
2021 struct in_ifaddr *ia, in_ifaddr;
2022 short has_ipaddr = 0;
2023 #if !STRUCT_IFNET_HAS_IF_XNAME
2029 * Get the "ifnet" structure and extract the device name
2031 klookup((unsigned long) ifnetaddr, (char *) &ifnet, sizeof ifnet);
2032 #if STRUCT_IFNET_HAS_IF_XNAME
2033 #if defined(netbsd1) || defined(openbsd2)
2034 strncpy(saveName, ifnet.if_xname, sizeof saveName);
2036 klookup((unsigned long) ifnet.if_xname, (char *) saveName,
2039 saveName[sizeof(saveName) - 1] = '\0';
2041 klookup((unsigned long) ifnet.if_name, (char *) saveName,
2044 saveName[sizeof(saveName) - 1] = '\0';
2045 cp = strchr(saveName, '\0');
2046 string_append_int(cp, ifnet.if_unit);
2048 if (1 || strcmp(saveName, "lo0") != 0) { /* XXX */
2050 * Try to find an address for this interface
2053 auto_nlist(IFADDR_SYMBOL, (char *) &ia, sizeof(ia));
2055 ia = (struct in_ifaddr *) ifnet.if_addrlist.tqh_first;
2058 klookup((unsigned long) ia, (char *) &in_ifaddr,
2062 #define CP(x) ((char *)(x))
2064 struct sockaddr *sa;
2065 cp = (CP(in_ifaddr.ia_ifa.ifa_addr) - CP(ia)) +
2067 sa = (struct sockaddr *) cp;
2069 if (sa->sa_family == AF_INET)
2071 if (in_ifaddr.ia_ifp == ifnetaddr) {
2072 has_ipaddr = 1; /* this IF has IP-address */
2077 ia = (struct in_ifaddr *) in_ifaddr.ia_ifa.ifa_list.
2080 ia = in_ifaddr.ia_next;
2084 #if !defined(netbsd1) && !defined(freebsd2) && !defined(openbsd2) && !defined(STRUCT_IFNET_HAS_IF_ADDRLIST)
2085 ifnet.if_addrlist = (struct ifaddr *) ia; /* WRONG DATA TYPE; ONLY A FLAG */
2088 * ifnet.if_addrlist = (struct ifaddr *)&ia->ia_ifa;
2090 * WRONG DATA TYPE; ONLY A FLAG
2094 *Index = ++saveIndex;
2097 if (Retin_ifaddr && has_ipaddr) /* assign the in_ifaddr only
2098 * if the IF has IP-address */
2099 *Retin_ifaddr = in_ifaddr;
2101 strcpy(Name, saveName);
2103 saveifnetaddr = ifnetaddr;
2104 savein_ifaddr = in_ifaddr;
2105 ifnetaddr = ifnet.if_next;
2107 return (1); /* DONE */
2109 ifnetaddr = ifnet.if_next;
2111 return (0); /* EOF */
2116 #endif /* sunV3 || linux */
2121 Interface_Scan_By_Index(int Index, char *Name, nmapi_phystat * Retifnet)
2125 Interface_Scan_Init();
2126 while (Interface_Scan_Next(&i, Name, Retifnet)) {
2131 return (-1); /* Error, doesn't exist */
2132 return (0); /* DONE */
2138 Interface_Scan_By_Index(int Index,
2140 struct ifnet *Retifnet,
2141 struct in_ifaddr *Retin_ifaddr)
2145 Interface_Scan_Init();
2146 while (Interface_Scan_Next(&i, Name, Retifnet, Retin_ifaddr)) {
2151 return (-1); /* Error, doesn't exist */
2152 return (0); /* DONE */
2157 static int Interface_Count = 0;
2162 Interface_Scan_Get_Count(void)
2164 if (!Interface_Count) {
2171 if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
2172 p.objid = ID_ifNumber;
2173 p.buffer = (void *) &val;
2176 if ((ret = get_mib_info(fd, &p)) == 0)
2177 Interface_Count = val;
2181 return (Interface_Count);
2186 static time_t scan_time = 0;
2189 Interface_Scan_Get_Count(void)
2191 time_t time_now = time(NULL);
2193 if (!Interface_Count || (time_now > scan_time + 60)) {
2194 scan_time = time_now;
2195 Interface_Scan_Init();
2196 Interface_Count = 0;
2197 while (Interface_Scan_Next(NULL, NULL, NULL, NULL) != 0) {
2201 return (Interface_Count);
2206 Interface_Get_Ether_By_Index(int Index, u_char * EtherAddr)
2209 #if !(defined(linux) || defined(netbsd1) || defined(bsdi2) || defined(openbsd2))
2210 struct arpcom arpcom;
2211 #else /* is linux or netbsd1 */
2215 #if defined(netbsd1) || defined(bsdi2) || defined(openbsd2)
2216 struct sockaddr_dl sadl;
2217 struct ifaddr ifaddr;
2222 #if defined(mips) || defined(hpux) || defined(osf4) || defined(osf3)
2223 memset(arpcom.ac_enaddr, 0, sizeof(arpcom.ac_enaddr));
2225 memset(&arpcom.ac_enaddr, 0, sizeof(arpcom.ac_enaddr));
2227 memset(EtherAddr, 0, sizeof(arpcom.ac_enaddr));
2229 if (saveIndex != Index) { /* Optimization! */
2231 Interface_Scan_Init();
2233 while (Interface_Scan_Next((short *) &i, NULL, NULL, NULL) != 0) {
2238 return (-1); /* Error, doesn't exist */
2241 if (saveifnet.if_type != IFT_ETHER) {
2242 return (0); /* Not an ethernet if */
2246 * the arpcom structure is an extended ifnet structure which
2247 * contains the ethernet address.
2250 #if !(defined(netbsd1) || defined(bsdi2) || defined(openbsd2))
2251 klookup((unsigned long) saveifnetaddr, (char *) &arpcom,
2253 #else /* netbsd1 or bsdi2 or openbsd2 */
2255 #if defined(netbsd1) || defined(openbsd2)
2256 #define if_addrlist if_addrlist.tqh_first
2257 #define ifa_next ifa_list.tqe_next
2260 ifaddraddr = (unsigned long) saveifnet.if_addrlist;
2261 while (ifaddraddr) {
2262 klookup(ifaddraddr, (char *) &ifaddr, sizeof ifaddr);
2263 klookup((unsigned long) ifaddr.ifa_addr, (char *) &sadl,
2265 if (sadl.sdl_family == AF_LINK
2266 && (saveifnet.if_type == IFT_ETHER
2267 || saveifnet.if_type == IFT_ISO88025
2268 || saveifnet.if_type == IFT_FDDI)) {
2269 memcpy(arpcom.ac_enaddr, sadl.sdl_data + sadl.sdl_nlen,
2270 sizeof(arpcom.ac_enaddr));
2273 ifaddraddr = (unsigned long) ifaddr.ifa_next;
2275 #endif /* netbsd1 or bsdi2 or openbsd2 */
2278 memcpy(arpcom.ac_enaddr, saveifnetaddr->if_hwaddr, 6);
2280 if (strncmp("lo", saveName, 2) == 0) {
2282 * Loopback doesn't have a HW addr, so return 00:00:00:00:00:00
2284 memset(EtherAddr, 0, sizeof(arpcom.ac_enaddr));
2288 #if defined(mips) || defined(hpux) || defined(osf4) || defined(osf3)
2289 memcpy(EtherAddr, (char *) arpcom.ac_enaddr,
2290 sizeof(arpcom.ac_enaddr));
2292 memcpy(EtherAddr, (char *) &arpcom.ac_enaddr,
2293 sizeof(arpcom.ac_enaddr));
2298 return (0); /* DONE */
2303 #else /* solaris2 */
2306 Interface_Scan_Get_Count(void)
2310 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
2312 if (ioctl(sd, SIOCGIFNUM, &i) == -1) {
2322 Interface_Index_By_Name(char *Name, int Len)
2324 int i, sd, lastlen = 0, interfaces = 0;
2326 struct ifreq *ifrp = NULL;
2332 if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
2337 * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF
2338 * on some platforms; see W. R. Stevens, ``Unix Network Programming
2339 * Volume I'', p.435.
2342 for (i = 8;; i += 8) {
2343 buf = calloc(i, sizeof(struct ifreq));
2348 ifc.ifc_len = i * sizeof(struct ifreq);
2349 ifc.ifc_buf = (caddr_t) buf;
2351 if (ioctl(sd, SIOCGIFCONF, (char *) &ifc) < 0) {
2352 if (errno != EINVAL || lastlen != 0) {
2354 * Something has gone genuinely wrong.
2361 * Otherwise, it could just be that the buffer is too small.
2364 if (ifc.ifc_len == lastlen) {
2366 * The length is the same as the last time; we're done.
2370 lastlen = ifc.ifc_len;
2376 interfaces = (ifc.ifc_len / sizeof(struct ifreq)) + 1;
2378 for (i = 1; i < interfaces; i++, ifrp++) {
2379 if (strncmp(ifrp->ifr_name, Name, Len) == 0) {
2391 #endif /* solaris2 */
2393 #else /* HAVE_NET_IF_MIB_H */
2396 * This code attempts to do the right thing for FreeBSD. Note that
2397 * the statistics could be gathered through use of of the
2398 * net.route.0.link.iflist.0 sysctl (which we already use to get the
2399 * hardware address of the interfaces), rather than using the ifmib
2400 * code, but eventually I will implement dot3Stats and we will have to
2401 * use the ifmib interface. ifmib is also a much more natural way of
2402 * mapping the SNMP MIB onto sysctl(3).
2406 #include <net/if_dl.h>
2407 #include <net/if_mib.h>
2408 #include <net/route.h>
2410 static int header_interfaces(struct variable *, oid *, size_t *, int,
2411 size_t *, WriteMethod ** write);
2412 static int header_ifEntry(struct variable *, oid *, size_t *, int,
2413 size_t *, WriteMethod ** write);
2414 u_char *var_ifEntry(struct variable *, oid *, size_t *, int,
2415 size_t *, WriteMethod ** write);
2417 static char *physaddrbuf;
2418 static int nphysaddrs;
2419 struct sockaddr_dl **physaddrs;
2422 init_interfaces_setup(void)
2424 int naddrs, ilen, bit;
2426 = { CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
2429 struct rt_msghdr *rtm;
2430 struct if_msghdr *ifm;
2431 struct ifa_msghdr *ifam;
2432 struct sockaddr *sa;
2443 if (sysctl(mib, 6, 0, &len, 0, 0) < 0)
2446 cp = physaddrbuf = malloc(len);
2447 if (physaddrbuf == 0)
2449 if (sysctl(mib, 6, physaddrbuf, &len, 0, 0) < 0) {
2459 rtm = (struct rt_msghdr *) cp;
2460 if (rtm->rtm_version != RTM_VERSION || rtm->rtm_type != RTM_IFINFO) {
2466 ifm = (struct if_msghdr *) rtm;
2467 #if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
2469 physaddrs[naddrs] = (void *) (ifm + 1);
2472 ilen -= ifm->ifm_msglen;
2473 cp += ifm->ifm_msglen;
2474 rtm = (struct rt_msghdr *) cp;
2475 while (ilen > 0 && rtm->rtm_type == RTM_NEWADDR) {
2476 #if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
2477 ilen -= rtm->rtm_msglen;
2478 cp += rtm->rtm_msglen;
2481 ifam = (struct ifa_msghdr *) rtm;
2482 ilen -= sizeof(*ifam);
2483 cp += sizeof(*ifam);
2484 sa = (struct sockaddr *) cp;
2485 #define ROUND(x) (((x) + sizeof(long) - 1) & ~sizeof(long))
2486 for (bit = 1; bit && ilen > 0; bit <<= 1) {
2487 if (!(ifam->ifam_addrs & bit))
2489 ilen -= ROUND(sa->sa_len);
2490 cp += ROUND(sa->sa_len);
2492 if (bit == RTA_IFA) {
2494 #define satosdl(sa) ((struct sockaddr_dl *)(sa))
2500 sa = (struct sockaddr *) cp;
2503 rtm = (struct rt_msghdr *) cp;
2507 nphysaddrs = naddrs;
2510 physaddrs = malloc(naddrs * sizeof(*physaddrs));
2519 get_phys_address(int iindex, char **ap, int *len)
2525 for (i = 0; i < nphysaddrs; i++) {
2526 if (physaddrs[i]->sdl_index == iindex)
2531 init_interfaces_setup();
2534 if (i < nphysaddrs) {
2535 *ap = LLADDR(physaddrs[i]);
2536 *len = physaddrs[i]->sdl_alen;
2543 Interface_Scan_Get_Count(void)
2545 static int count_oid[5] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
2546 IFMIB_SYSTEM, IFMIB_IFCOUNT
2552 if (sysctl(count_oid, 5, &count, &len, (void *) 0, (size_t) 0) < 0)
2559 var_ifEntry(struct variable * vp,
2562 int exact, size_t * var_len, WriteMethod ** write_method)
2565 static int sname[6] = { CTL_NET, PF_LINK, NETLINK_GENERIC,
2566 IFMIB_IFDATA, 0, IFDATA_GENERAL
2568 static struct ifmibdata ifmd;
2572 interface = header_ifEntry(vp, name, length, exact, var_len,
2574 if (interface == MATCH_FAILED)
2577 sname[4] = interface;
2579 if (sysctl(sname, 6, &ifmd, &len, 0, 0) < 0)
2582 switch (vp->magic) {
2584 long_return = interface;
2585 return (u_char *) & long_return;
2587 cp = ifmd.ifmd_name;
2588 *var_len = strlen(cp);
2589 return (u_char *) cp;
2591 long_return = ifmd.ifmd_data.ifi_type;
2592 return (u_char *) & long_return;
2594 long_return = (long) ifmd.ifmd_data.ifi_mtu;
2595 return (u_char *) & long_return;
2597 long_return = ifmd.ifmd_data.ifi_baudrate;
2598 return (u_char *) & long_return;
2602 if (get_phys_address(interface, &cp, var_len))
2608 long_return = ifmd.ifmd_flags & IFF_UP ? 1 : 2;
2609 return (u_char *) & long_return;
2611 long_return = ifmd.ifmd_flags & IFF_RUNNING ? 1 : 2;
2612 return (u_char *) & long_return;
2614 if (ifmd.ifmd_data.ifi_lastchange.tv_sec == 0 &&
2615 ifmd.ifmd_data.ifi_lastchange.tv_usec == 0) {
2617 } else if (ifmd.ifmd_data.ifi_lastchange.tv_sec < starttime.tv_sec) {
2620 long_return = (u_long)
2621 ((ifmd.ifmd_data.ifi_lastchange.tv_sec -
2622 starttime.tv_sec) * 100 +
2623 ((ifmd.ifmd_data.ifi_lastchange.tv_usec -
2624 starttime.tv_usec) / 10000));
2626 return (u_char *) & long_return;
2628 long_return = (u_long) ifmd.ifmd_data.ifi_ibytes;
2629 return (u_char *) & long_return;
2631 long_return = (u_long) ifmd.ifmd_data.ifi_ipackets;
2632 long_return -= (u_long) ifmd.ifmd_data.ifi_imcasts;
2633 return (u_char *) & long_return;
2634 case IFINNUCASTPKTS:
2635 long_return = (u_long) ifmd.ifmd_data.ifi_imcasts;
2636 return (u_char *) & long_return;
2638 long_return = (u_long) ifmd.ifmd_data.ifi_iqdrops;
2639 return (u_char *) & long_return;
2641 long_return = ifmd.ifmd_data.ifi_ierrors;
2642 return (u_char *) & long_return;
2643 case IFINUNKNOWNPROTOS:
2644 long_return = (u_long) ifmd.ifmd_data.ifi_noproto;
2645 return (u_char *) & long_return;
2647 long_return = (u_long) ifmd.ifmd_data.ifi_obytes;
2648 return (u_char *) & long_return;
2649 case IFOUTUCASTPKTS:
2650 long_return = (u_long) ifmd.ifmd_data.ifi_opackets;
2651 long_return -= (u_long) ifmd.ifmd_data.ifi_omcasts;
2652 return (u_char *) & long_return;
2653 case IFOUTNUCASTPKTS:
2654 long_return = (u_long) ifmd.ifmd_data.ifi_omcasts;
2655 return (u_char *) & long_return;
2657 long_return = ifmd.ifmd_snd_drops;
2658 return (u_char *) & long_return;
2660 long_return = ifmd.ifmd_data.ifi_oerrors;
2661 return (u_char *) & long_return;
2663 long_return = ifmd.ifmd_snd_len;
2664 return (u_char *) & long_return;
2666 *var_len = nullOidLen;
2667 return (u_char *) nullOid;
2669 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
2675 #endif /* HAVE_NET_IF_MIB_H */
2676 #endif /* !USE_SYSCTL_IFLIST */
2679 #include <iphlpapi.h>
2681 WriteMethod writeIfEntry;
2682 long admin_status = 0;
2683 long oldadmin_status = 0;
2686 header_ifEntry(struct variable *vp,
2689 int exact, size_t * var_len, WriteMethod ** write_method)
2691 #define IFENTRY_NAME_LENGTH 10
2692 oid newname[MAX_OID_LEN];
2693 register int ifIndex;
2695 DWORD status = NO_ERROR;
2696 DWORD statusRetry = NO_ERROR;
2697 DWORD dwActualSize = 0;
2698 PMIB_IFTABLE pIfTable = NULL;
2700 DEBUGMSGTL(("mibII/interfaces", "var_ifEntry: "));
2701 DEBUGMSGOID(("mibII/interfaces", name, *length));
2702 DEBUGMSG(("mibII/interfaces", " %d\n", exact));
2704 memcpy((char *) newname, (char *) vp->name,
2705 (int) vp->namelen * sizeof(oid));
2707 * find "next" ifIndex
2712 * query for buffer size needed
2714 status = GetIfTable(pIfTable, &dwActualSize, TRUE);
2716 if (status == ERROR_INSUFFICIENT_BUFFER) {
2720 pIfTable = (PMIB_IFTABLE) malloc(dwActualSize);
2721 if (pIfTable != NULL) {
2723 * Get the sorted IF table
2725 GetIfTable(pIfTable, &dwActualSize, TRUE);
2728 count = pIfTable->dwNumEntries;
2729 for (ifIndex = 0; ifIndex < count; ifIndex++) {
2730 newname[IFENTRY_NAME_LENGTH] =
2731 (oid) pIfTable->table[ifIndex].dwIndex;
2733 snmp_oid_compare(name, *length, newname,
2734 (int) vp->namelen + 1);
2735 if ((exact && (result == 0)) || (!exact && (result < 0)))
2738 if (ifIndex > count) {
2739 DEBUGMSGTL(("mibII/interfaces", "... index out of range\n"));
2740 return MATCH_FAILED;
2744 memcpy((char *) name, (char *) newname,
2745 ((int) vp->namelen + 1) * sizeof(oid));
2746 *length = vp->namelen + 1;
2748 *var_len = sizeof(long); /* default to 'long' results */
2750 DEBUGMSGTL(("mibII/interfaces", "... get I/F stats "));
2751 DEBUGMSGOID(("mibII/interfaces", name, *length));
2752 DEBUGMSG(("mibII/interfaces", "\n"));
2754 count = pIfTable->table[ifIndex].dwIndex;
2762 var_interfaces(struct variable * vp,
2765 int exact, size_t * var_len, WriteMethod ** write_method)
2767 if (header_generic(vp, name, length, exact, var_len, write_method) ==
2771 switch (vp->magic) {
2773 GetNumberOfInterfaces(&long_return);
2774 return (u_char *) & long_return;
2776 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_interfaces\n",
2783 var_ifEntry(struct variable * vp,
2786 int exact, size_t * var_len, WriteMethod ** write_method)
2789 static char Name[16];
2790 conf_if_list *if_ptr = conf_list;
2791 static MIB_IFROW ifRow;
2794 header_ifEntry(vp, name, length, exact, var_len, write_method);
2795 if (ifIndex == MATCH_FAILED)
2799 * Get the If Table Row by passing index as argument
2801 ifRow.dwIndex = ifIndex;
2802 if (GetIfEntry(&ifRow) != NO_ERROR)
2804 switch (vp->magic) {
2806 long_return = ifIndex;
2807 return (u_char *) & long_return;
2809 *var_len = ifRow.dwDescrLen;
2810 return (u_char *) ifRow.bDescr;
2812 long_return = ifRow.dwType;
2813 return (u_char *) & long_return;
2815 long_return = (long) ifRow.dwMtu;
2816 return (u_char *) & long_return;
2818 long_return = (long) ifRow.dwSpeed;
2819 return (u_char *) & long_return;
2821 *var_len = ifRow.dwPhysAddrLen;
2822 memcpy(return_buf, ifRow.bPhysAddr, *var_len);
2823 return (u_char *) return_buf;
2825 long_return = ifRow.dwAdminStatus;
2826 admin_status = long_return;
2827 *write_method = writeIfEntry;
2828 return (u_char *) & long_return;
2830 long_return = ifRow.dwOperStatus;
2831 return (u_char *) & long_return;
2833 long_return = ifRow.dwLastChange;
2834 return (u_char *) & long_return;
2836 long_return = ifRow.dwInOctets;
2837 return (u_char *) & long_return;
2839 long_return = ifRow.dwInUcastPkts;
2840 return (u_char *) & long_return;
2841 case IFINNUCASTPKTS:
2842 long_return = ifRow.dwInNUcastPkts;
2843 return (u_char *) & long_return;
2845 long_return = ifRow.dwInDiscards;
2846 return (u_char *) & long_return;
2848 long_return = ifRow.dwInErrors;
2849 return (u_char *) & long_return;
2850 case IFINUNKNOWNPROTOS:
2851 long_return = ifRow.dwInUnknownProtos;
2852 return (u_char *) & long_return;
2854 long_return = ifRow.dwOutOctets;
2855 return (u_char *) & long_return;
2856 case IFOUTUCASTPKTS:
2857 long_return = ifRow.dwOutUcastPkts;
2858 return (u_char *) & long_return;
2859 case IFOUTNUCASTPKTS:
2860 long_return = ifRow.dwOutNUcastPkts;
2861 return (u_char *) & long_return;
2863 long_return = ifRow.dwOutDiscards;
2864 return (u_char *) & long_return;
2866 long_return = ifRow.dwOutErrors;
2867 return (u_char *) & long_return;
2869 long_return = ifRow.dwOutQLen;
2870 return (u_char *) & long_return;
2872 *var_len = nullOidLen;
2873 return (u_char *) nullOid;
2875 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ifEntry\n",
2883 writeIfEntry(int action,
2885 u_char var_val_type,
2887 u_char * statP, oid * name, size_t name_len)
2889 MIB_IFROW ifEntryRow;
2890 if ((char) name[9] != IFADMINSTATUS) {
2891 return SNMP_ERR_NOTWRITABLE;
2895 case RESERVE1: /* Check values for acceptability */
2896 if (var_val_type != ASN_INTEGER) {
2897 snmp_log(LOG_ERR, "not integer\n");
2898 return SNMP_ERR_WRONGTYPE;
2900 if (var_val_len > sizeof(int)) {
2901 snmp_log(LOG_ERR, "bad length\n");
2902 return SNMP_ERR_WRONGLENGTH;
2906 * The dwAdminStatus member can be MIB_IF_ADMIN_STATUS_UP or MIB_IF_ADMIN_STATUS_DOWN
2908 if (!(((int) (*var_val) == MIB_IF_ADMIN_STATUS_UP) ||
2909 ((int) (*var_val) == MIB_IF_ADMIN_STATUS_DOWN))) {
2910 snmp_log(LOG_ERR, "not supported admin state\n");
2911 return SNMP_ERR_WRONGVALUE;
2915 case RESERVE2: /* Allocate memory and similar resources */
2920 * Save the old value, in case of UNDO
2923 oldadmin_status = admin_status;
2924 admin_status = (int) *var_val;
2927 case UNDO: /* Reverse the SET action and free resources */
2928 admin_status = oldadmin_status;
2931 case COMMIT: /* Confirm the SET, performing any irreversible actions,
2932 * and free resources */
2933 ifEntryRow.dwIndex = (int) name[10];
2934 ifEntryRow.dwAdminStatus = admin_status;
2936 * Only UP and DOWN status are supported. Thats why done in COMMIT
2938 if (SetIfEntry(&ifEntryRow) != NO_ERROR) {
2940 "Error in writeIfEntry case COMMIT with index: %d & adminStatus %d\n",
2941 ifEntryRow.dwIndex, ifEntryRow.dwAdminStatus);
2942 return SNMP_ERR_COMMITFAILED;
2945 case FREE: /* Free any resources allocated */
2947 * No resources have been allocated
2951 return SNMP_ERR_NOERROR;
2952 } /* end of writeIfEntry */
2956 #ifdef BUILD_SNMP_SET
2957 static int setPppConnAdminDown(char *devName);
2959 writeIfEntry(int action,
2961 u_char var_val_type,
2963 u_char * statP, oid * name, size_t name_len)
2969 if ((char) name[9] != IFADMINSTATUS)
2970 return SNMP_ERR_NOTWRITABLE;
2973 case RESERVE1: /* Check values for acceptability */
2974 if (var_val_type != ASN_INTEGER) {
2975 snmp_log(LOG_ERR, "not integer\n");
2976 return SNMP_ERR_WRONGTYPE;
2978 if (var_val_len > sizeof(int)) {
2979 snmp_log(LOG_ERR, "bad length\n");
2980 return SNMP_ERR_WRONGLENGTH;
2983 value = *((int*)var_val);
2985 if ((value != IF_ADMIN_STATUS_UP) &&
2986 (value != IF_ADMIN_STATUS_DOWN)) {
2987 snmp_log(LOG_ERR, "not supported admin state %d\n",value);
2988 return SNMP_ERR_WRONGVALUE;
2992 case RESERVE2: /* Allocate memory and similar resources */
2997 * Save the old value, in case of UNDO
3001 case UNDO: /* Reverse the SET action and free resources */
3004 case COMMIT: /* Confirm the SET, performing any irreversible actions,
3005 * and free resources */
3006 index = *((int*)&name[10]);
3007 value = *((int*)var_val);
3008 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
3009 snmp_log(LOG_ERR, "socket open failure in WriteIfEntry\n");
3010 return SNMP_ERR_COMMITFAILED;
3013 /* get ifName first */
3014 ifrq.ifr_ifindex = index;
3015 if (ioctl(fd, SIOCGIFNAME, &ifrq) < 0) {
3016 snmp_log(LOG_ERR, "WriteIfEntry unable to locate device name for ifIndex %d\n",index);
3017 return SNMP_ERR_COMMITFAILED;
3020 if (strcmp(ifrq.ifr_name,IF_BRCM_DSL_DEV_NAME) == 0) {
3021 if (setAdslAdminStatus(value) < 0)
3022 return SNMP_ERR_COMMITFAILED;
3024 else if ((strcmp(ifrq.ifr_name,"atm0") == 0) ||
3025 (strcmp(ifrq.ifr_name,"cpcs0") == 0)) {
3026 if (setAtmIntfAdminStatus(value) < 0)
3027 return SNMP_ERR_COMMITFAILED;
3029 else if ((strncmp(ifrq.ifr_name,"ppp",strlen("ppp"))) == 0) {
3030 /* value is always down since after ppp is admin down the first time, dev is gone */
3031 if (setPppConnAdminDown(ifrq.ifr_name) < 0)
3032 return SNMP_ERR_COMMITFAILED;
3034 if (value == IF_ADMIN_STATUS_UP)
3035 ifrq.ifr_flags |= IFF_UP;
3037 ifrq.ifr_flags &= ~IFF_UP;
3038 if (ioctl(fd, SIOCSIFFLAGS, &ifrq) < 0) {
3040 return SNMP_ERR_COMMITFAILED;
3044 case FREE: /* Free any resources allocated */
3046 * No resources have been allocated
3050 return SNMP_ERR_NOERROR;
3051 } /* end of ifWriteEntry */
3053 int setPppConnAdminDown(char *devName)
3059 sprintf(path,"/proc/var/fyi/wan/%s/wanup",devName);
3061 fs = fopen(path, "w");
3071 #endif /* BUILD_SNMP_SET */