/* Display the contents of the ARP cache in the kernel. */ static int arp_show(char *name) { char host[100]; struct sockaddr_storage ss; char ip[100]; char hwa[100]; char mask[100]; char line[200]; char dev[100]; int type, flags; FILE *fp; const char *hostname; int num, entries = 0, showed = 0; host[0] = '\0'; if (name != NULL) { /* Resolve the host name. */ safe_strncpy(host, name, (sizeof host)); if (ap->input(0, host, &ss) < 0) { ap->herror(host); return (-1); } safe_strncpy(host, ap->sprint(&ss, 1), sizeof(host)); } /* Open the PROCps kernel table. */ if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) { perror(_PATH_PROCNET_ARP); return (-1); } /* Bypass header -- read until newline */ if (fgets(line, sizeof(line), fp) != (char *) NULL) { safe_strncpy(mask, "-", sizeof(mask)); safe_strncpy(dev, "-", sizeof(dev)); /* Read the ARP cache entries. */ for (; fgets(line, sizeof(line), fp);) { num = sscanf(line, "%s 0x%x 0x%x %99s %99s %99s\n", ip, &type, &flags, hwa, mask, dev); if (num < 4) break; entries++; /* if the user specified hw-type differs, skip it */ if (hw_set && (type != hw->type)) continue; /* if the user specified address differs, skip it */ if (host[0] && strcmp(ip, host)) continue; /* if the user specified device differs, skip it */ if (device[0] && strcmp(dev, device)) continue; showed++; /* This IS ugly but it works -be */ if (opt_n) hostname = "?"; else { if (ap->input(0, ip, &ss) < 0) hostname = ip; else hostname = ap->sprint(&ss, opt_n | 0x8000); if (strcmp(hostname, ip) == 0) hostname = "?"; } if (opt_e) arp_disp_2(hostname[0] == '?' ? ip : hostname, type, flags, hwa, mask, dev); else arp_disp(hostname, ip, type, flags, hwa, mask, dev); } } if (opt_v) printf(_("Entries: %d\tSkipped: %d\tFound: %d\n"), entries, entries - showed, showed); if (!showed) { if (host[0] && !opt_a) printf(_("%s (%s) -- no entry\n"), name, host); else if (hw_set || host[0] || device[0]) { printf(_("arp: in %d entries no match found.\n"), entries); } } (void) fclose(fp); return (0); }
/* Called only from main, once */ static int arp_show(char *name) { const char *host; const char *hostname; FILE *fp; struct sockaddr sa; int type, flags; int num; unsigned entries = 0, shown = 0; char ip[128]; char hwa[128]; char mask[128]; char line[128]; char dev[128]; host = NULL; if (name != NULL) { /* Resolve the host name. */ if (ap->input(name, &sa) < 0) { bb_herror_msg_and_die("%s", name); } host = xstrdup(ap->sprint(&sa, 1)); } fp = xfopen("/proc/net/arp", "r"); /* Bypass header -- read one line */ fgets(line, sizeof(line), fp); /* Read the ARP cache entries. */ while (fgets(line, sizeof(line), fp)) { mask[0] = '-'; mask[1] = '\0'; dev[0] = '-'; dev[1] = '\0'; /* All these strings can't overflow * because fgets above reads limited amount of data */ num = sscanf(line, "%s 0x%x 0x%x %s %s %s\n", ip, &type, &flags, hwa, mask, dev); if (num < 4) break; entries++; /* if the user specified hw-type differs, skip it */ if (hw_set && (type != hw->type)) continue; /* if the user specified address differs, skip it */ if (host && strcmp(ip, host) != 0) continue; /* if the user specified device differs, skip it */ if (device[0] && strcmp(dev, device) != 0) continue; shown++; /* This IS ugly but it works -be */ hostname = "?"; if (!(option_mask32 & ARP_OPT_n)) { if (ap->input(ip, &sa) < 0) hostname = ip; else hostname = ap->sprint(&sa, (option_mask32 & ARP_OPT_n) | 0x8000); if (strcmp(hostname, ip) == 0) hostname = "?"; } arp_disp(hostname, ip, type, flags, hwa, mask, dev); } if (option_mask32 & ARP_OPT_v) printf("Entries: %d\tSkipped: %d\tFound: %d\n", entries, entries - shown, shown); if (!shown) { if (hw_set || host || device[0]) printf("No match found in %d entries\n", entries); } if (ENABLE_FEATURE_CLEAN_UP) { free((char*)host); fclose(fp); } return 0; }