1 #ifdef BUILD_SNMP_AT_MIB
3 * Template MIB group implementation - at.c
7 #include <net-snmp/net-snmp-config.h>
16 #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
18 #define _I_DEFINED_KERNEL
20 #include <sys/types.h>
21 #if TIME_WITH_SYS_TIME
23 # include <sys/timeb.h>
25 # include <sys/time.h>
30 # include <sys/time.h>
36 #include <sys/socket.h>
40 #include <netinet/in.h>
46 #include <net/if_var.h>
48 #ifdef _I_DEFINED_KERNEL
52 #if HAVE_NETINET_IF_ETHER_H
53 #include <netinet/if_ether.h>
56 #include <inet/mib2.h>
59 #include <sys/param.h>
62 #include <sys/sysctl.h>
66 #include <net/if_dl.h>
68 #include <sys/net/if_dl.h>
72 #include <sys/stream.h>
75 #include <net/route.h>
78 #include "kernel_sunos5.h"
89 #include <netinet/mib_kern.h>
92 #include <net-snmp/net-snmp-includes.h>
93 #include <net-snmp/agent/net-snmp-agent-includes.h>
94 #include <net-snmp/agent/auto_nlist.h>
97 #include "interfaces.h"
99 #if defined(HAVE_SYS_SYSCTL_H) && !defined(CAN_USE_SYSCTL)
100 # if defined(RTF_LLINFO) && !defined(irix6)
101 # define CAN_USE_SYSCTL 1
110 /*********************
112 * Kernel & interface information,
113 * and internal forward declarations
115 *********************/
119 static void ARP_Scan_Init(void);
120 #ifdef ARP_SCAN_FOUR_ARGUMENTS
121 static int ARP_Scan_Next(u_long *, char *, u_long *, u_short *);
123 static int ARP_Scan_Next(u_long *, char *, u_long *);
128 /*********************
130 * Public interface functions
132 *********************/
135 * define the structure we're going to ask the agent to register our
138 struct variable1 at_variables[] = {
139 {ATIFINDEX, ASN_INTEGER, RONLY, var_atEntry, 1, {1}},
140 {ATPHYSADDRESS, ASN_OCTET_STR, RONLY, var_atEntry, 1, {2}},
141 {ATNETADDRESS, ASN_IPADDRESS, RONLY, var_atEntry, 1, {3}}
145 * Define the OID pointer to the top of the mib tree that we're
146 * registering underneath
148 oid at_variables_oid[] = { SNMP_OID_MIB2, 3, 1, 1 };
154 * register ourselves with the agent to handle our mib tree
156 REGISTER_MIB("mibII/at", at_variables, variable1, at_variables_oid);
158 init_kernel_sunos5();
168 * vp IN - pointer to variable entry that points here
169 * name IN/OUT - IN/name requested, OUT/name found
170 * length IN/OUT - length of IN/OUT oid's
171 * exact IN - TRUE if an exact match was requested
172 * var_len OUT - length of variable or 0 if function returned
178 var_atEntry(struct variable *vp,
181 int exact, size_t * var_len, WriteMethod ** write_method)
184 * Address Translation table object identifier is of form:
185 * 1.3.6.1.2.1.3.1.1.1.interface.1.A.B.C.D, where A.B.C.D is IP address.
186 * Interface is at offset 10,
187 * IPADDR starts at offset 12.
189 * IP Net to Media table object identifier is of form:
190 * 1.3.6.1.2.1.4.22.1.1.1.interface.A.B.C.D, where A.B.C.D is IP address.
191 * Interface is at offset 10,
192 * IPADDR starts at offset 11.
198 static char PhysAddr[6], LowPhysAddr[6];
199 u_long Addr, LowAddr, foundone;
200 #ifdef ARP_SCAN_FOUR_ARGUMENTS
201 u_short ifIndex, lowIfIndex = 0;
202 #endif /* ARP_SCAN_FOUR_ARGUMENTS */
203 u_long ifType, lowIfType = 0;
208 * fill in object part of name for current (less sizeof instance part)
210 memcpy((char *) current, (char *) vp->name,
211 (int) vp->namelen * sizeof(oid));
213 if (current[6] == 3) { /* AT group oid */
215 } else { /* IP NetToMedia group oid */
219 LowAddr = 0; /* Don't have one yet */
223 #ifdef ARP_SCAN_FOUR_ARGUMENTS
224 if (ARP_Scan_Next(&Addr, PhysAddr, &ifType, &ifIndex) == 0)
226 current[10] = ifIndex;
228 if (current[6] == 3) { /* AT group oid */
231 } else { /* IP NetToMedia group oid */
234 #else /* ARP_SCAN_FOUR_ARGUMENTS */
235 if (ARP_Scan_Next(&Addr, PhysAddr, &ifType) == 0)
239 if (current[6] == 3) { /* AT group oid */
242 } else { /* IP NetToMedia group oid */
245 #endif /* ARP_SCAN_FOUR_ARGUMENTS */
246 cp = (u_char *) & Addr;
253 if (snmp_oid_compare(current, oid_length, name, *length) == 0) {
254 memcpy((char *) lowest, (char *) current,
255 oid_length * sizeof(oid));
258 #ifdef ARP_SCAN_FOUR_ARGUMENTS
259 lowIfIndex = ifIndex;
260 #endif /* ARP_SCAN_FOUR_ARGUMENTS */
261 memcpy(LowPhysAddr, PhysAddr, sizeof(PhysAddr));
263 break; /* no need to search further */
266 if ((snmp_oid_compare(current, oid_length, name, *length) > 0)
270 (current, oid_length, lowest, oid_length) < 0))) {
272 * if new one is greater than input and closer to input than
273 * previous lowest, save this one as the "next" one.
275 memcpy((char *) lowest, (char *) current,
276 oid_length * sizeof(oid));
279 #ifdef ARP_SCAN_FOUR_ARGUMENTS
280 lowIfIndex = ifIndex;
281 #endif /* ARP_SCAN_FOUR_ARGUMENTS */
282 memcpy(LowPhysAddr, PhysAddr, sizeof(PhysAddr));
290 memcpy((char *) name, (char *) lowest, oid_length * sizeof(oid));
291 *length = oid_length;
294 case IPMEDIAIFINDEX: /* also ATIFINDEX */
295 *var_len = sizeof long_return;
296 #ifdef ARP_SCAN_FOUR_ARGUMENTS
297 long_return = lowIfIndex;
298 #else /* ARP_SCAN_FOUR_ARGUMENTS */
302 long_return = 1; /* XXX */
303 #endif /* ARP_SCAN_FOUR_ARGUMENTS */
304 return (u_char *) & long_return;
305 case IPMEDIAPHYSADDRESS: /* also ATPHYSADDRESS */
306 *var_len = sizeof(LowPhysAddr);
307 return (u_char *) LowPhysAddr;
308 case IPMEDIANETADDRESS: /* also ATNETADDRESS */
309 *var_len = sizeof long_return;
310 long_return = LowAddr;
311 return (u_char *) & long_return;
313 *var_len = sizeof long_return;
314 long_return = lowIfType;
315 return (u_char *) & long_return;
317 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_atEntry\n",
324 typedef struct if_ip {
330 AT_Cmp(void *addr, void *ep)
332 mib2_ipNetToMediaEntry_t *mp = (mib2_ipNetToMediaEntry_t *) ep;
334 DEBUGMSGTL(("mibII/at", "......... AT_Cmp %lx<>%lx %d<>%d (%.5s)\n",
335 mp->ipNetToMediaNetAddress, ((if_ip_t *) addr)->ipAddr,
336 ((if_ip_t *) addr)->ifIdx,
337 Interface_Index_By_Name(mp->ipNetToMediaIfIndex.o_bytes,
338 mp->ipNetToMediaIfIndex.o_length),
339 mp->ipNetToMediaIfIndex.o_bytes));
340 if (mp->ipNetToMediaNetAddress != ((if_ip_t *) addr)->ipAddr)
342 else if (((if_ip_t *) addr)->ifIdx !=
343 Interface_Index_By_Name(mp->ipNetToMediaIfIndex.o_bytes,
344 mp->ipNetToMediaIfIndex.o_length))
348 DEBUGMSGTL(("mibII/at", "......... AT_Cmp returns %d\n", ret));
353 var_atEntry(struct variable * vp,
356 int exact, size_t * var_len, WriteMethod ** write_method)
359 * object identifier is of form:
360 * 1.3.6.1.2.1.3.1.1.1.interface.1.A.B.C.D, where A.B.C.D is IP address.
361 * Interface is at offset 10,
362 * IPADDR starts at offset 12.
364 #define AT_MAX_NAME_LENGTH 16
365 #define AT_IFINDEX_OFF 10
368 oid lowest[AT_MAX_NAME_LENGTH];
369 oid current[AT_MAX_NAME_LENGTH];
371 mib2_ipNetToMediaEntry_t entry, Lowentry;
377 * fill in object part of name for current (less sizeof instance part)
380 DEBUGMSGTL(("mibII/at", "var_atEntry: "));
381 DEBUGMSGOID(("mibII/at", vp->name, vp->namelen));
382 DEBUGMSG(("mibII/at", " %d\n", exact));
384 memset(&Lowentry, 0, sizeof(Lowentry));
385 memcpy((char *) current, (char *) vp->name, vp->namelen * sizeof(oid));
387 for (NextAddr.ipAddr = (u_long) - 1, NextAddr.ifIdx = 255, req_type =
389 NextAddr.ipAddr = entry.ipNetToMediaNetAddress, NextAddr.ifIdx =
390 current[AT_IFINDEX_OFF], req_type = GET_NEXT) {
392 (MIB_IP_NET, &entry, sizeof(mib2_ipNetToMediaEntry_t),
393 req_type, &AT_Cmp, &NextAddr) != 0)
395 current[AT_IFINDEX_OFF] =
396 Interface_Index_By_Name(entry.ipNetToMediaIfIndex.o_bytes,
397 entry.ipNetToMediaIfIndex.o_length);
398 if (current[6] == 3) { /* AT group oid */
399 current[AT_IFINDEX_OFF + 1] = 1;
400 offset = AT_IFINDEX_OFF + 2;
401 olength = AT_IFINDEX_OFF + 6;
403 offset = AT_IFINDEX_OFF + 1;
404 olength = AT_IFINDEX_OFF + 5;
406 COPY_IPADDR(cp, (u_char *) & entry.ipNetToMediaNetAddress, op,
409 if (snmp_oid_compare(current, olength, name, *length) == 0) {
410 memcpy((char *) lowest, (char *) current,
411 olength * sizeof(oid));
414 break; /* no need to search further */
417 if (snmp_oid_compare(current, olength, name, *length) > 0
418 && snmp_oid_compare(current, olength, lowest,
421 * if new one is greater than input and closer to input than
422 * previous lowest, and is not equal to it, save this one as the "next" one.
424 memcpy((char *) lowest, (char *) current,
425 olength * sizeof(oid));
431 DEBUGMSGTL(("mibII/at", "... Found = %d\n", Found));
434 memcpy((char *) name, (char *) lowest, olength * sizeof(oid));
439 *var_len = sizeof long_return;
441 Interface_Index_By_Name(Lowentry.ipNetToMediaIfIndex.o_bytes,
442 Lowentry.ipNetToMediaIfIndex.o_length);
443 return (u_char *) & long_return;
444 case IPMEDIAPHYSADDRESS:
445 *var_len = Lowentry.ipNetToMediaPhysAddress.o_length;
446 (void) memcpy(return_buf, Lowentry.ipNetToMediaPhysAddress.o_bytes,
448 return (u_char *) return_buf;
449 case IPMEDIANETADDRESS:
450 *var_len = sizeof long_return;
451 long_return = Lowentry.ipNetToMediaNetAddress;
452 return (u_char *) & long_return;
454 *var_len = sizeof long_return;
455 long_return = Lowentry.ipNetToMediaType;
456 return (u_char *) & long_return;
458 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_atEntry\n",
463 #endif /* solaris2 */
466 /*********************
468 * Internal implementation functions
470 *********************/
474 static int arptab_size, arptab_current;
476 static char *lim, *rtnext;
479 #ifdef STRUCT_ARPHD_HAS_AT_NEXT
480 static struct arphd *at = 0;
481 static struct arptab *at_ptr, at_entry;
482 static struct arpcom at_com;
483 #elif defined(hpux11)
484 static mib_ipNetToMediaEnt *at = (mib_ipNetToMediaEnt *) 0;
488 * at used to be allocated every time we needed to look at the arp cache.
489 * This cause us to parse /proc/net/arp twice for each request and didn't
490 * allow us to filter things like we'd like to. So now we use it
491 * semi-statically. We initialize it to size 0 and if we need more room
492 * we realloc room for ARP_CACHE_INCR more entries in the table.
493 * We never release what we've taken . . .
495 #define ARP_CACHE_INCR 1024
496 static struct arptab *at = NULL;
497 static int arptab_curr_max_size = 0;
500 #endif /* CAN_USE_SYSCTL */
505 #ifndef CAN_USE_SYSCTL
517 at = (mib_ipNetToMediaEnt *) 0;
520 if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
521 p.objid = ID_ipNetToMediaTableNum;
522 p.buffer = (void *) &val;
525 if ((ret = get_mib_info(fd, &p)) == 0)
528 if (arptab_size > 0) {
529 ulen = (unsigned) arptab_size *sizeof(mib_ipNetToMediaEnt);
530 at = (mib_ipNetToMediaEnt *) malloc(ulen);
531 p.objid = ID_ipNetToMediaTable;
532 p.buffer = (void *) at;
534 if ((ret = get_mib_info(fd, &p)) < 0)
546 auto_nlist(ARPTAB_SIZE_SYMBOL, (char *) &arptab_size,
548 #ifdef STRUCT_ARPHD_HAS_AT_NEXT
549 at = (struct arphd *) malloc(arptab_size * sizeof(struct arphd));
551 at = (struct arptab *) malloc(arptab_size * sizeof(struct arptab));
554 #ifdef STRUCT_ARPHD_HAS_AT_NEXT
555 auto_nlist(ARPTAB_SYMBOL, (char *) at,
556 arptab_size * sizeof(struct arphd));
557 at_ptr = at[0].at_next;
559 auto_nlist(ARPTAB_SYMBOL, (char *) at,
560 arptab_size * sizeof(struct arptab));
567 static time_t tm = 0; /* Time of last scan */
571 int za, zb, zc, zd, ze, zf, zg, zh, zi, zj;
574 arptab_current = 0; /* Anytime this is called we need to reset 'current' */
576 if (time(NULL) < tm + 1) { /*Our cool one second cache implementation :-) */
580 in = fopen("/proc/net/arp", "r");
582 snmp_log(LOG_ERR, "snmpd: Cannot open /proc/net/arp\n");
588 * Get rid of the header line
590 fgets(line, sizeof(line), in);
593 while (fgets(line, sizeof(line), in)) {
596 if (i >= arptab_curr_max_size) {
597 struct arptab *newtab = (struct arptab *)
598 realloc(at, (sizeof(struct arptab) *
599 (arptab_curr_max_size + ARP_CACHE_INCR)));
602 "Error allocating more space for arpcache. "
603 "Cache will continue to be limited to %d entries",
604 arptab_curr_max_size);
607 arptab_curr_max_size += ARP_CACHE_INCR;
613 "%d.%d.%d.%d 0x%*x 0x%x %x:%x:%x:%x:%x:%x %*[^ ] %20s\n",
614 &za, &zb, &zc, &zd, &tmp_flags, &ze, &zf, &zg, &zh, &zi,
616 snmp_log(LOG_ERR, "Bad line in /proc/net/arp: %s", line);
620 * Invalidated entries have their flag set to 0.
621 * * We want to ignore them
623 if (tmp_flags == 0) {
626 at[i].at_flags = tmp_flags;
627 at[i].at_enaddr[0] = ze;
628 at[i].at_enaddr[1] = zf;
629 at[i].at_enaddr[2] = zg;
630 at[i].at_enaddr[3] = zh;
631 at[i].at_enaddr[4] = zi;
632 at[i].at_enaddr[5] = zj;
633 tmp_a = ((u_long) za << 24) |
634 ((u_long) zb << 16) | ((u_long) zc << 8) | ((u_long) zd);
635 at[i].at_iaddr.s_addr = htonl(tmp_a);
636 at[i].if_index = Interface_Index_By_Name(ifname, strlen(ifname));
644 #else /* CAN_USE_SYSCTL */
653 mib[4] = NET_RT_FLAGS;
658 rtnext = lim = at = 0;
660 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
661 snmp_log_perror("route-sysctl-estimate");
663 if ((at = malloc(needed ? needed : 1)) == NULL)
664 snmp_log_perror("malloc");
666 if (sysctl(mib, 6, at, &needed, NULL, 0) < 0)
667 snmp_log_perror("actual retrieval of routing table");
675 #endif /* CAN_USE_SYSCTL */
678 #ifdef ARP_SCAN_FOUR_ARGUMENTS
680 ARP_Scan_Next(u_long * IPAddr, char *PhysAddr, u_long * ifType,
684 ARP_Scan_Next(u_long * IPAddr, char *PhysAddr, u_long * ifType)
687 #ifndef CAN_USE_SYSCTL
689 if (arptab_current < arptab_size) {
693 *IPAddr = at[arptab_current].at_iaddr.s_addr;
696 at_flags & ATF_PERM) ? 4 /*static */ : 3 /*dynamic */ ;
697 *ifIndex = at[arptab_current].if_index;
698 memcpy(PhysAddr, &at[arptab_current].at_enaddr,
699 sizeof(at[arptab_current].at_enaddr));
702 * increment to point next entry
710 #elif defined(hpux11)
711 if (arptab_current < arptab_size) {
715 *IPAddr = at[arptab_current].NetAddr;
716 memcpy(PhysAddr, at[arptab_current].PhysAddr.o_bytes,
717 at[arptab_current].PhysAddr.o_length);
718 *ifType = at[arptab_current].Type;
719 *ifIndex = at[arptab_current].IfIndex;
721 * increment to point next entry
729 #elif !defined(ARP_SCAN_FOUR_ARGUMENTS) || defined(hpux)
730 register struct arptab *atab;
732 while (arptab_current < arptab_size) {
733 #ifdef STRUCT_ARPHD_HAS_AT_NEXT
735 * The arp table is an array of linked lists of arptab entries.
736 * Unused slots have pointers back to the array entry itself
739 if (at_ptr == (auto_nlist_value(ARPTAB_SYMBOL) +
740 arptab_current * sizeof(struct arphd))) {
745 at_ptr = at[arptab_current].at_next;
749 klookup(at_ptr, (char *) &at_entry, sizeof(struct arptab));
750 klookup(at_entry.at_ac, (char *) &at_com, sizeof(struct arpcom));
752 at_ptr = at_entry.at_next;
754 *ifIndex = at_com.ac_if.if_index; /* not strictly ARPHD */
755 #else /* STRUCT_ARPHD_HAS_AT_NEXT */
756 atab = &at[arptab_current++];
757 #endif /* STRUCT_ARPHD_HAS_AT_NEXT */
758 if (!(atab->at_flags & ATF_COM))
760 *ifType = (atab->at_flags & ATF_PERM) ? 4 : 3;
761 *IPAddr = atab->at_iaddr.s_addr;
762 #if defined (sunV3) || defined(sparc) || defined(hpux)
763 memcpy(PhysAddr, (char *) &atab->at_enaddr,
764 sizeof(atab->at_enaddr));
766 #if defined(mips) || defined(ibm032)
767 memcpy(PhysAddr, (char *) atab->at_enaddr,
768 sizeof(atab->at_enaddr));
772 #endif /* linux || hpux11 || !ARP_SCAN_FOUR_ARGUMENTS || hpux */
774 return 0; /* we need someone with an irix box to fix this section */
776 #else /* !CAN_USE_SYSCTL */
777 struct rt_msghdr *rtm;
778 struct sockaddr_inarp *sin;
779 struct sockaddr_dl *sdl;
781 while (rtnext < lim) {
782 rtm = (struct rt_msghdr *) rtnext;
783 sin = (struct sockaddr_inarp *) (rtm + 1);
784 sdl = (struct sockaddr_dl *) (sin + 1);
785 rtnext += rtm->rtm_msglen;
787 *IPAddr = sin->sin_addr.s_addr;
788 memcpy(PhysAddr, (char *) LLADDR(sdl), sdl->sdl_alen);
789 *ifIndex = sdl->sdl_index;
790 *ifType = 1; /* XXX */
794 return (0); /* "EOF" */
795 #endif /* !CAN_USE_SYSCTL */
797 #endif /* solaris2 */
800 #include <iphlpapi.h>
802 extern WriteMethod write_arp;
803 MIB_IPNETROW *arp_row = NULL;
807 var_atEntry(struct variable *vp,
810 int exact, size_t * var_len, WriteMethod ** write_method)
813 * Address Translation table object identifier is of form:
814 * 1.3.6.1.2.1.3.1.?.interface.1.A.B.C.D, where A.B.C.D is IP address.
815 * Interface is at offset 10,
816 * IPADDR starts at offset 12.
818 * IP Net to Media table object identifier is of form:
819 * 1.3.6.1.2.1.4.22.1.?.interface.A.B.C.D, where A.B.C.D is IP address.
820 * Interface is at offset 10,
821 * IPADDR starts at offset 11.
828 int lowState = -1; /* Don't have one yet */
829 PMIB_IPNETTABLE pIpNetTable = NULL;
830 DWORD status = NO_ERROR;
831 DWORD dwActualSize = 0;
836 * fill in object part of name for current (less sizeof instance part)
838 memcpy((char *) current, (char *) vp->name,
839 (int) vp->namelen * sizeof(oid));
841 if (current[6] == 3) { /* AT group oid */
843 } else { /* IP NetToMedia group oid */
847 status = GetIpNetTable(pIpNetTable, &dwActualSize, TRUE);
848 if (status == ERROR_INSUFFICIENT_BUFFER) {
849 pIpNetTable = (PMIB_IPNETTABLE) malloc(dwActualSize);
850 if (pIpNetTable != NULL) {
852 * Get the sorted IpNet Table
854 status = GetIpNetTable(pIpNetTable, &dwActualSize, TRUE);
859 if (status == NO_ERROR) {
860 for (i = 0; i < pIpNetTable->dwNumEntries; ++i) {
861 current[10] = pIpNetTable->table[i].dwIndex;
864 if (current[6] == 3) { /* AT group oid */
867 } else { /* IP NetToMedia group oid */
870 cp = (u_char *) & pIpNetTable->table[i].dwAddr;
877 if (snmp_oid_compare(current, oid_length, name, *length) ==
879 memcpy((char *) lowest, (char *) current,
880 oid_length * sizeof(oid));
882 break; /* no need to search further */
885 if (snmp_oid_compare(current, oid_length, name, *length) >
887 memcpy((char *) lowest, (char *) current,
888 oid_length * sizeof(oid));
890 break; /* As the table is sorted, no need to search further */
895 if (arp_row == NULL) {
897 * Free allocated memory in case of SET request's FREE phase
899 arp_row = (PMIB_IPNETROW) malloc(sizeof(MIB_IPNETROW));
902 if (lowState < 0 || status != NO_ERROR) {
904 * for creation of new row, only ipNetToMediaTable case is considered
906 if (*length == 15 || *length == 16) {
908 *write_method = write_arp;
909 arp_row->dwIndex = name[10];
911 if (*length == 15) { /* ipNetToMediaTable */
913 } else { /* at Table */
918 dest_addr[0] = (u_char) name[i];
919 dest_addr[1] = (u_char) name[i + 1];
920 dest_addr[2] = (u_char) name[i + 2];
921 dest_addr[3] = (u_char) name[i + 3];
922 arp_row->dwAddr = *((DWORD *) dest_addr);
924 arp_row->dwType = 4; /* Static */
925 arp_row->dwPhysAddrLen = 0;
932 memcpy((char *) name, (char *) lowest, oid_length * sizeof(oid));
933 *length = oid_length;
934 *write_method = write_arp;
935 *arp_row = pIpNetTable->table[i];
938 case IPMEDIAIFINDEX: /* also ATIFINDEX */
939 *var_len = sizeof long_return;
940 long_return = pIpNetTable->table[i].dwIndex;
942 return (u_char *) & long_return;
943 case IPMEDIAPHYSADDRESS: /* also ATPHYSADDRESS */
944 *var_len = pIpNetTable->table[i].dwPhysAddrLen;
945 memcpy(return_buf, pIpNetTable->table[i].bPhysAddr, *var_len);
947 return (u_char *) return_buf;
948 case IPMEDIANETADDRESS: /* also ATNETADDRESS */
949 *var_len = sizeof long_return;
950 long_return = pIpNetTable->table[i].dwAddr;
952 return (u_char *) & long_return;
954 *var_len = sizeof long_return;
955 long_return = pIpNetTable->table[i].dwType;
957 return (u_char *) & long_return;
959 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_atEntry\n",
966 write_arp(int action,
969 size_t var_val_len, u_char * statP, oid * name, size_t length)
971 int var, retval = SNMP_ERR_NOERROR;
972 static PMIB_IPNETROW oldarp_row = NULL;
973 MIB_IPNETROW temp_row;
974 DWORD status = NO_ERROR;
977 * IP Net to Media table object identifier is of form:
978 * 1.3.6.1.2.1.4.22.1.?.interface.A.B.C.D, where A.B.C.D is IP address.
979 * Interface is at offset 10,
980 * IPADDR starts at offset 11.
983 if (name[6] == 3) { /* AT group oid */
985 snmp_log(LOG_ERR, "length error\n");
986 return SNMP_ERR_NOCREATION;
988 } else { /* IP NetToMedia group oid */
990 snmp_log(LOG_ERR, "length error\n");
991 return SNMP_ERR_NOCREATION;
997 * #define for ipNetToMediaTable entries are 1 less than corresponding sub-id in MIB
998 * * i.e. IPMEDIAIFINDEX defined as 0, but ipNetToMediaIfIndex registered as 1
1004 case IPMEDIAIFINDEX:
1005 if (var_val_type != ASN_INTEGER) {
1006 snmp_log(LOG_ERR, "not integer\n");
1007 return SNMP_ERR_WRONGTYPE;
1009 if ((*((int *) var_val)) < 0) {
1010 snmp_log(LOG_ERR, "invalid media ifIndex");
1011 return SNMP_ERR_WRONGVALUE;
1013 if (var_val_len > sizeof(int)) {
1014 snmp_log(LOG_ERR, "bad length\n");
1015 return SNMP_ERR_WRONGLENGTH;
1018 case IPMEDIANETADDRESS:
1019 if (var_val_type != ASN_IPADDRESS) {
1020 snmp_log(LOG_ERR, "not IP Address\n");
1021 return SNMP_ERR_WRONGTYPE;
1023 if ((*((int *) var_val)) < 0) {
1024 snmp_log(LOG_ERR, "invalid media net address");
1025 return SNMP_ERR_WRONGVALUE;
1027 if (var_val_len > sizeof(DWORD)) {
1028 snmp_log(LOG_ERR, "bad length\n");
1029 return SNMP_ERR_WRONGLENGTH;
1033 if (var_val_type != ASN_INTEGER) {
1034 snmp_log(LOG_ERR, "not integer\n");
1035 return SNMP_ERR_WRONGTYPE;
1037 if ((*((int *) var_val)) < 1 || (*((int *) var_val)) > 4) {
1038 snmp_log(LOG_ERR, "invalid media type");
1039 return SNMP_ERR_WRONGVALUE;
1041 if (var_val_len > sizeof(int)) {
1042 snmp_log(LOG_ERR, "bad length\n");
1043 return SNMP_ERR_WRONGLENGTH;
1046 case IPMEDIAPHYSADDRESS:
1047 if (var_val_type != ASN_OCTET_STR) {
1048 snmp_log(LOG_ERR, "not octet str");
1049 return SNMP_ERR_WRONGTYPE;
1051 if (var_val_len != 6) {
1052 snmp_log(LOG_ERR, "not correct ipAddress length: %d",
1054 return SNMP_ERR_WRONGLENGTH;
1058 DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_rte\n",
1060 return SNMP_ERR_NOTWRITABLE;
1065 * Save the old value, in case of UNDO
1067 if (oldarp_row == NULL) {
1068 oldarp_row = (PMIB_IPNETROW) malloc(sizeof(MIB_IPNETROW));
1069 *oldarp_row = *arp_row;
1072 case ACTION: /* Perform the SET action (if reversible) */
1075 case IPMEDIAIFINDEX:
1076 temp_row = *arp_row;
1077 arp_row->dwIndex = *((int *) var_val);
1079 * In case of new entry, physical address is mandatory.
1080 * * SetIpNetEntry will be done in COMMIT case
1083 if (SetIpNetEntry(arp_row) != NO_ERROR) {
1084 arp_row->dwIndex = temp_row.dwIndex;
1085 retval = SNMP_ERR_COMMITFAILED;
1088 * Don't know yet, whether change in ifIndex creates new row or not
1094 * temp_row.dwType = 2;
1097 * if(SetIpNetEntry(&temp_row) != NO_ERROR)
1100 * retval = SNMP_ERR_COMMITFAILED;
1107 case IPMEDIANETADDRESS:
1108 temp_row = *arp_row;
1109 arp_row->dwAddr = *((int *) var_val);
1111 if (SetIpNetEntry(arp_row) != NO_ERROR) {
1112 arp_row->dwAddr = oldarp_row->dwAddr;
1113 retval = SNMP_ERR_COMMITFAILED;
1115 temp_row.dwType = 2;
1116 if (SetIpNetEntry(&temp_row) != NO_ERROR) {
1118 "Failed in ACTION, while deleting old row \n");
1119 retval = SNMP_ERR_COMMITFAILED;
1125 arp_row->dwType = *((int *) var_val);
1127 if (SetIpNetEntry(arp_row) != NO_ERROR)
1128 retval = SNMP_ERR_COMMITFAILED;
1131 case IPMEDIAPHYSADDRESS:
1132 memcpy(arp_row->bPhysAddr, var_val, var_val_len);
1133 arp_row->dwPhysAddrLen = var_val_len;
1135 if (SetIpNetEntry(arp_row) != NO_ERROR)
1136 retval = SNMP_ERR_COMMITFAILED;
1140 DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_arp\n",
1142 retval = SNMP_ERR_NOTWRITABLE;
1147 * Reverse the SET action and free resources
1149 if (oldarp_row != NULL) {
1151 * UNDO the changes done for existing entry.
1154 if ((status = SetIpNetEntry(oldarp_row)) != NO_ERROR) {
1155 snmp_log(LOG_ERR, "Error in case UNDO, status : %d\n",
1157 retval = SNMP_ERR_UNDOFAILED;
1161 if (oldarp_row->dwAddr != arp_row->dwAddr) {
1162 arp_row->dwType = 2; /*If row was added/created delete that row */
1164 if ((status = SetIpNetEntry(arp_row)) != NO_ERROR) {
1166 "Error while deleting added row, status : %d\n",
1168 retval = SNMP_ERR_UNDOFAILED;
1180 * if new entry and physical address specified, create new entry
1183 if (arp_row->dwPhysAddrLen != 0) {
1184 if ((status = CreateIpNetEntry(arp_row)) != NO_ERROR) {
1186 "Inside COMMIT: CreateIpNetEntry failed, status %d\n",
1188 retval = SNMP_ERR_COMMITFAILED;
1192 * For new entry, physical address must be set.
1195 "Can't create new entry without physical address\n");
1196 retval = SNMP_ERR_WRONGVALUE;
1199 * unset the create_flag, so that CreateIpNetEntry called only once
1206 * Free any resources allocated
1224 #endif /* BUILD_SNMP_AT_MIB */