📄 arp.c
字号:
/* * arp This file contains an implementation of the command * that maintains the kernel's ARP cache. It is derived * from Berkeley UNIX arp(8), but cleaner and with sup- * port for devices other than Ethernet. * * NET-TOOLS A collection of programs that form the base set of the * NET-3 Networking Distribution for the LINUX operating * system. * * Version: $Id: arp.c,v 1.12 1999/03/24 09:49:43 philip Exp $ * * Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de> * * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * * Changes: * (based on work from Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>) * Alan Cox : modified for NET3 * Andrew Tridgell : proxy arp netmasks * Bernd Eckenfels : -n option * Bernd Eckenfels : Use only /proc for display * {1.60} Bernd Eckenfels : new arpcode (-i) for 1.3.42 but works * with 1.2.x, too * {1.61} Bernd Eckenfels : more verbose messages * {1.62} Bernd Eckenfels : check -t for hw adresses and try to * explain EINVAL (jeff) *970125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle *970201 {1.64} Bernd Eckenfels : net-features.h support *970203 {1.65} Bernd Eckenfels : "#define" in "#if", * -H|-A additional to -t|-p *970214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A *970412 {1.67} Bernd Eckenfels : device=""; is default *970514 {1.68} Bernd Eckenfels : -N and -D *970517 {1.69} Bernd Eckenfels : usage() fixed *970622 {1.70} Bernd Eckenfels : arp -d priv *970106 {1.80} Bernd Eckenfels : new syntax without -D and with "dev <If>", * ATF_MAGIC, ATF_DONTPUB support. * Typo fix (Debian Bug#5728 Giuliano Procida) *970803 {1.81} Bernd Eckenfels : removed junk comment line 1 *970925 {1.82} Bernd Eckenfels : include fix for libc6 *980213 (1.83) Phil Blundell: set ATF_COM on new entries *980629 (1.84) Arnaldo Carvalho de Melo: gettext instead of catgets *990101 {1.85} Bernd Eckenfels fixed usage and return codes *990105 (1.86) Phil Blundell: don't ignore EINVAL in arp_set * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software * Foundation; either version 2 of the License, or (at * your option) any later version. */#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>/* #include <linux/netdevice.h> *//* #include <linux/if_arp.h> */#include <net/if_arp.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <ctype.h>#include <fcntl.h>#include <string.h>#include <getopt.h>#include <unistd.h>#include "net-support.h"#include "pathnames.h"#include "version.h"#include "config.h"#include "intl.h"#include "util.h"#define DFLT_AF "inet"#define DFLT_HW "ether"#define FEATURE_ARP#include "lib/net-features.h"char *Release = RELEASE, *Version = "arp 1.85 (1999-01-05)";int opt_n = 0; /* do not resolve addresses */int opt_N = 0; /* use symbolic names */int opt_v = 0; /* debugging output flag */int opt_D = 0; /* HW-address is devicename */int opt_e = 0; /* 0=BSD output, 1=new linux */int opt_a = 0; /* all entries, substring match */struct aftype *ap; /* current address family */struct hwtype *hw; /* current hardware type */int sockfd = 0; /* active socket descriptor */int hw_set = 0; /* flag if hw-type was set (-H) */char device[16] = ""; /* current device */static void usage(void);/* Delete an entry from the ARP cache. */static int arp_del(char **args){ char host[128]; struct arpreq req; struct sockaddr sa; int flags = 0; int err; memset((char *) &req, 0, sizeof(req)); /* Resolve the host name. */ if (*args == NULL) { fprintf(stderr, _("arp: need host name\n")); return (-1); } safe_strncpy(host, *args, (sizeof host)); if (ap->input(0, host, &sa) < 0) { ap->herror(host); return (-1); } /* If a host has more than one address, use the correct one! */ memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr)); if (hw_set) req.arp_ha.sa_family = hw->type; req.arp_flags = ATF_PERM; args++; while (*args != NULL) { if (opt_v) fprintf(stderr, "args=%s\n", *args); if (!strcmp(*args, "pub")) { flags |= 1; args++; continue; } if (!strcmp(*args, "priv")) { flags |= 2; args++; continue; } if (!strcmp(*args, "temp")) { req.arp_flags &= ~ATF_PERM; args++; continue; } if (!strcmp(*args, "trail")) { req.arp_flags |= ATF_USETRAILERS; args++; continue; } if (!strcmp(*args, "dontpub")) {#ifdef HAVE_ATF_DONTPUB req.arp_flags |= ATF_DONTPUB;#else ENOSUPP("arp", "ATF_DONTPUB");#endif args++; continue; } if (!strcmp(*args, "auto")) {#ifdef HAVE_ATF_MAGIC req.arp_flags |= ATF_MAGIC;#else ENOSUPP("arp", "ATF_MAGIC");#endif args++; continue; } if (!strcmp(*args, "dev")) { if (*++args == NULL) usage(); safe_strncpy(device, *args, sizeof(device)); args++; continue; } if (!strcmp(*args, "netmask")) { if (*++args == NULL) usage(); if (strcmp(*args, "255.255.255.255") != 0) { strcpy(host, *args); if (ap->input(0, host, &sa) < 0) { ap->herror(host); return (-1); } memcpy((char *) &req.arp_netmask, (char *) &sa, sizeof(struct sockaddr)); req.arp_flags |= ATF_NETMASK; } args++; continue; } usage(); } if (flags == 0) flags = 3; strcpy(req.arp_dev, device); err = -1; /* Call the kernel. */ if (flags & 2) { if (opt_v) fprintf(stderr, "arp: SIOCDARP(nopub)\n"); if ((err = ioctl(sockfd, SIOCDARP, &req) < 0)) { if (errno == ENXIO) { if (flags & 1) goto nopub; printf(_("No ARP entry for %s\n"), host); return (-1); } perror("SIOCDARP(priv)"); return (-1); } } if ((flags & 1) && (err)) { nopub: req.arp_flags |= ATF_PUBL; if (opt_v) fprintf(stderr, "arp: SIOCDARP(pub)\n"); if (ioctl(sockfd, SIOCDARP, &req) < 0) { if (errno == ENXIO) { printf(_("No ARP entry for %s\n"), host); return (-1); } perror("SIOCDARP(pub)"); return (-1); } } return (0);}/* Get the hardware address to a specified interface name */static int arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw){ struct ifreq ifr; struct hwtype *xhw; strcpy(ifr.ifr_name, ifname); if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { fprintf(stderr, _("arp: cant get HW-Address for `%s': %s.\n"), ifname, strerror(errno)); return (-1); } if (hw && (ifr.ifr_hwaddr.sa_family != hw->type)) { fprintf(stderr, _("arp: protocol type mismatch.\n")); return (-1); } memcpy((char *) sa, (char *) &(ifr.ifr_hwaddr), sizeof(struct sockaddr)); if (opt_v) { if (!(xhw = get_hwntype(ifr.ifr_hwaddr.sa_family)) || (xhw->sprint == 0)) { xhw = get_hwntype(-1); } fprintf(stderr, _("arp: device `%s' has HW address %s `%s'.\n"), ifname, xhw->name, xhw->sprint(&ifr.ifr_hwaddr)); } return (0);}/* Set an entry in the ARP cache. */static int arp_set(char **args){ char host[128]; struct arpreq req; struct sockaddr sa; int flags; memset((char *) &req, 0, sizeof(req)); /* Resolve the host name. */ if (*args == NULL) { fprintf(stderr, _("arp: need host name\n")); return (-1); } safe_strncpy(host, *args++, (sizeof host)); if (ap->input(0, host, &sa) < 0) { ap->herror(host); return (-1); } /* If a host has more than one address, use the correct one! */ memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr)); /* Fetch the hardware address. */ if (*args == NULL) { fprintf(stderr, _("arp: need hardware address\n")); return (-1); } if (opt_D) { if (arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL) < 0) return (-1); } else { if (hw->input(*args++, &req.arp_ha) < 0) { fprintf(stderr, _("arp: invalid hardware address\n")); return (-1); } } /* Check out any modifiers. */ flags = ATF_PERM | ATF_COM; while (*args != NULL) { if (!strcmp(*args, "temp")) { flags &= ~ATF_PERM; args++; continue; } if (!strcmp(*args, "pub")) { flags |= ATF_PUBL; args++; continue; } if (!strcmp(*args, "priv")) { flags &= ~ATF_PUBL; args++; continue; } if (!strcmp(*args, "trail")) { flags |= ATF_USETRAILERS; args++; continue; } if (!strcmp(*args, "dontpub")) {#ifdef HAVE_ATF_DONTPUB flags |= ATF_DONTPUB;#else ENOSUPP("arp", "ATF_DONTPUB");#endif args++; continue; } if (!strcmp(*args, "auto")) {#ifdef HAVE_ATF_MAGIC flags |= ATF_MAGIC;#else ENOSUPP("arp", "ATF_MAGIC");#endif args++; continue; } if (!strcmp(*args, "dev")) { if (*++args == NULL) usage(); safe_strncpy(device, *args, sizeof(device)); args++; continue; } if (!strcmp(*args, "netmask")) { if (*++args == NULL) usage(); if (strcmp(*args, "255.255.255.255") != 0) { strcpy(host, *args); if (ap->input(0, host, &sa) < 0) { ap->herror(host); return (-1); } memcpy((char *) &req.arp_netmask, (char *) &sa, sizeof(struct sockaddr)); flags |= ATF_NETMASK; } args++; continue; } usage(); } /* Fill in the remainder of the request. */ req.arp_flags = flags; strcpy(req.arp_dev, device); /* Call the kernel. */ if (opt_v) fprintf(stderr, "arp: SIOCSARP()\n"); if (ioctl(sockfd, SIOCSARP, &req) < 0) { perror("SIOCSARP"); return (-1); } return (0);}/* Process an EtherFile */static int arp_file(char *name){ char buff[1024]; char *sp, *args[32]; int linenr, argc; FILE *fp; if ((fp = fopen(name, "r")) == NULL) { fprintf(stderr, _("arp: cannot open etherfile %s !\n"), name); return (-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -