/** * check entry for update * */ static void _snarf_arp_entry(netsnmp_arp_entry *arp_entry, netsnmp_container *container) { inetNetToMediaTable_rowreq_ctx *rowreq_ctx; int inetAddressType; DEBUGTRACE; netsnmp_assert(NULL != arp_entry); netsnmp_assert(NULL != container); /* * convert the addr len to an inetAddressType */ switch (arp_entry->arp_ipaddress_len) { case 4: inetAddressType = INETADDRESSTYPE_IPV4; break; case 6: inetAddressType = INETADDRESSTYPE_IPV6; break; default: netsnmp_access_arp_entry_free(arp_entry); snmp_log(LOG_ERR, "unsupported address type\n"); return; } /* * allocate an row context and set the index(es), then add it to * the container */ rowreq_ctx = inetNetToMediaTable_allocate_rowreq_ctx(arp_entry, NULL); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == inetNetToMediaTable_indexes_set (rowreq_ctx, rowreq_ctx->data->if_index, inetAddressType, rowreq_ctx->data->arp_ipaddress, rowreq_ctx->data->arp_ipaddress_len))) { rowreq_ctx->inetNetToMediaRowStatus = ROWSTATUS_ACTIVE; CONTAINER_INSERT(container, rowreq_ctx); } else { if (rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "inetNetToMediaTable cache.\n"); inetNetToMediaTable_release_rowreq_ctx(rowreq_ctx); } else netsnmp_access_arp_entry_free(arp_entry); } }
static void netsnmp_access_arp_read_netlink(int fd, void *data) { netsnmp_arp_access *access = (netsnmp_arp_access *) data; netsnmp_arp_entry *entry; char buf[16384]; struct nlmsghdr *h; int r, len; do { r = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); if (r < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) return; snmp_log(LOG_WARNING, "netlink buffer overrun\n"); access->synchronized = 0; if (access->cache_expired != NULL) *access->cache_expired = 1; return; } } while (0); len = r; for (h = (struct nlmsghdr *) buf; NLMSG_OK(h, len); h = NLMSG_NEXT(h, len)) { if (h->nlmsg_type == NLMSG_DONE) { access->synchronized = 1; continue; } entry = netsnmp_access_arp_entry_create(); if (NULL == entry) break; DEBUGMSGTL(("access:netlink:arp", "arp netlink notification\n")); entry->generation = access->generation; r = fillup_entry_info (entry, h); if (r > 0) { access->update_hook(access, entry); } else { if (r < 0) { NETSNMP_LOGONCE((LOG_ERR, "filling entry info failed\n")); DEBUGMSGTL(("access:netlink:arp", "filling entry info failed\n")); } netsnmp_access_arp_entry_free(entry); } } }
int _load_v4(netsnmp_container *container, int idx_offset) { FILE *in; char line[128]; int rc = 0; netsnmp_arp_entry *entry; netsnmp_assert(NULL != container); #define PROCFILE "/proc/net/arp" if (!(in = fopen(PROCFILE, "r"))) { snmp_log(LOG_ERR,"could not open " PROCFILE "\n"); return -2; } /* * Get rid of the header line */ fgets(line, sizeof(line), in); /* * IP address | HW | Flag | HW address | Mask | Device * 192.168.1.4 0x1 0x2 00:40:63:CC:1C:8C * eth0 */ while (fgets(line, sizeof(line), in)) { int za, zb, zc, zd, ze, zf, zg, zh, zi, zj; int tmp_flags; char ifname[21]; rc = sscanf(line, "%d.%d.%d.%d 0x%*x 0x%x %x:%x:%x:%x:%x:%x %*[^ ] %20s\n", &za, &zb, &zc, &zd, &tmp_flags, &ze, &zf, &zg, &zh, &zi, &zj, ifname); if (12 != rc) { snmp_log(LOG_ERR, PROCFILE " data format error (%d!=12)\n", rc); snmp_log(LOG_ERR, " line ==|%s|\n", line); continue; } DEBUGMSGTL(("access:arp:container", "ip addr %d.%d.%d.%d, flags 0x%X, hw addr " "%x:%x:%x:%x:%x:%x, name %s\n", za,zb,zc,zd, tmp_flags, ze,zf,zg,zh,zi,zj, ifname )); /* */ entry = netsnmp_access_arp_entry_create(); if(NULL == entry) { rc = -3; break; } /* * look up ifIndex */ entry->if_index = netsnmp_access_interface_index_find(ifname); if(0 == entry->if_index) { snmp_log(LOG_ERR,"couldn't find ifIndex for '%s', skipping\n", ifname); netsnmp_access_arp_entry_free(entry); continue; } /* * now that we've passed all the possible 'continue', assign * index offset. */ entry->ns_arp_index = ++idx_offset; /* * parse ip addr */ entry->arp_ipaddress[0] = za; entry->arp_ipaddress[1] = zb; entry->arp_ipaddress[2] = zc; entry->arp_ipaddress[3] = zd; entry->arp_ipaddress_len = 4; /* * parse hw addr */ entry->arp_physaddress[0] = ze; entry->arp_physaddress[1] = zf; entry->arp_physaddress[2] = zg; entry->arp_physaddress[3] = zh; entry->arp_physaddress[4] = zi; entry->arp_physaddress[5] = zj; entry->arp_physaddress_len = 6; /* * what can we do with hw? from arp manpage: default value of this parameter is ether (i.e. hardware code 0x01 for IEEE 802.3 10Mbps Ethernet). Other values might include network technologies such as ARCnet (arcnet) , PROnet (pronet) , AX.25 (ax25) and NET/ROM (netrom). */ /* * parse mask */ /* xxx-rks: what is mask? how to interpret '*'? */ /* * process type */ if(tmp_flags & ATF_PERM) entry->arp_type = INETNETTOMEDIATYPE_STATIC; else entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC; /* * process status * if flags are 0, we can't tell the difference between * stale or incomplete. */ if(tmp_flags & ATF_COM) entry->arp_state = INETNETTOMEDIASTATE_REACHABLE; else entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN; /* * add entry to container */ CONTAINER_INSERT(container, entry); } fclose(in); if( rc < 0 ) return rc; return idx_offset; }
void _access_arp_entry_release(netsnmp_arp_entry * entry, void *context) { netsnmp_access_arp_entry_free(entry); }
static int _load_v6(netsnmp_container *container, int idx_offset) { char buffer[16384]; #if defined(HAVE_LINUX_RTNETLINK_H) struct nlmsghdr *nlmp; #endif int sd = 0; int status = 0; int rc = 0; int len, req_len; netsnmp_arp_entry *entry; netsnmp_assert(NULL != container); #if defined(HAVE_LINUX_RTNETLINK_H) if((sd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { snmp_log(LOG_ERR,"Unable to create netlink socket\n"); return -2; } if(get_translation_table_info (sd, &status, buffer, sizeof(buffer)) < 0) { snmp_log(LOG_ERR,"Unable to fetch translation table info\n"); close(sd); return -2; } for (nlmp = (struct nlmsghdr *)buffer; status > sizeof(*nlmp); ) { len = nlmp->nlmsg_len; req_len = len - sizeof(*nlmp); if (req_len < 0 || len > status) { snmp_log(LOG_ERR,"invalid length\n"); return -2; } if (!NLMSG_OK (nlmp, status)) { snmp_log(LOG_ERR,"NLMSG not OK\n"); return -2; } entry = netsnmp_access_arp_entry_create(); if(NULL == entry) { rc = -3; break; } entry->ns_arp_index = ++idx_offset; if(fillup_entry_info (entry, nlmp) < 0) { DEBUGMSGTL(("access:arp:load_v6", "skipping netlink message that" " did not contain valid ARP information\n")); netsnmp_access_arp_entry_free(entry); status -= NLMSG_ALIGN(len); nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len)); continue; } CONTAINER_INSERT(container, entry); status -= NLMSG_ALIGN(len); nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len)); } close(sd); #endif if(rc<0) { return rc; } return idx_offset; }
static int _load_v4(netsnmp_arp_access *access) { FILE *in; char line[128]; int rc = 0; netsnmp_arp_entry *entry; char arp[3*NETSNMP_ACCESS_ARP_PHYSADDR_BUF_SIZE+1]; char *arp_token; int i; netsnmp_assert(NULL != access); #define PROCFILE "/proc/net/arp" if (!(in = fopen(PROCFILE, "r"))) { snmp_log(LOG_DEBUG,"could not open " PROCFILE "\n"); return -2; } /* * Get rid of the header line */ fgets(line, sizeof(line), in); /* * IP address | HW | Flag | HW address | Mask | Device * 192.168.1.4 0x1 0x2 00:40:63:CC:1C:8C * eth0 */ while (fgets(line, sizeof(line), in)) { int za, zb, zc, zd; unsigned int tmp_flags; char ifname[21]; rc = sscanf(line, "%d.%d.%d.%d 0x%*x 0x%x %96s %*[^ ] %20s\n", &za, &zb, &zc, &zd, &tmp_flags, arp, ifname); if (7 != rc) { snmp_log(LOG_ERR, PROCFILE " data format error (%d!=12)\n", rc); snmp_log(LOG_ERR, " line ==|%s|\n", line); continue; } DEBUGMSGTL(("access:arp:container", "ip addr %d.%d.%d.%d, flags 0x%X, hw addr " "%s, name %s\n", za,zb,zc,zd, tmp_flags, arp, ifname )); /* */ entry = netsnmp_access_arp_entry_create(); if(NULL == entry) { rc = -3; break; } /* * look up ifIndex */ entry->generation = access->generation; entry->if_index = netsnmp_access_interface_index_find(ifname); if(0 == entry->if_index) { snmp_log(LOG_ERR,"couldn't find ifIndex for '%s', skipping\n", ifname); netsnmp_access_arp_entry_free(entry); continue; } /* * now that we've passed all the possible 'continue', assign * index offset. */ /* entry->ns_arp_index = ++idx_offset; */ /* * parse ip addr */ entry->arp_ipaddress[0] = za; entry->arp_ipaddress[1] = zb; entry->arp_ipaddress[2] = zc; entry->arp_ipaddress[3] = zd; entry->arp_ipaddress_len = 4; /* * parse hw addr */ for (arp_token = strtok(arp, ":"), i=0; arp_token != NULL; arp_token = strtok(NULL, ":"), i++) { entry->arp_physaddress[i] = strtol(arp_token, NULL, 16); } entry->arp_physaddress_len = i; /* * what can we do with hw? from arp manpage: default value of this parameter is ether (i.e. hardware code 0x01 for IEEE 802.3 10Mbps Ethernet). Other values might include network technologies such as ARCnet (arcnet) , PROnet (pronet) , AX.25 (ax25) and NET/ROM (netrom). */ /* * parse mask */ /* xxx-rks: what is mask? how to interpret '*'? */ /* * process type */ if(tmp_flags & ATF_PERM) entry->arp_type = INETNETTOMEDIATYPE_STATIC; else entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC; /* * process status * if flags are 0, we can't tell the difference between * stale or incomplete. */ if(tmp_flags & ATF_COM) entry->arp_state = INETNETTOMEDIASTATE_REACHABLE; else entry->arp_state = INETNETTOMEDIASTATE_UNKNOWN; /* * add entry to container */ access->update_hook(access, entry); } fclose(in); return 0; }