2 * rarp This file contains an implementation of the command
3 * that maintains the kernel's RARP cache. It is derived
4 * from Fred N. van Kempen's arp command.
6 * Version: $Id: rarp.c,v 1.6 2001/04/08 17:05:05 pb Exp $
8 * Usage: rarp -d hostname Delete entry
9 * rarp -s hostname ethernet_address Add entry
10 * rarp -a Print entries
11 * rarp -f Add frop /etc/ethers
13 * Rewritten: Phil Blundell <Philip.Blundell@pobox.com> 1997-08-03
14 * gettext instead of catgets: Arnaldo Carvalho de Melo <acme@conectiva.com.br> 1998-06-29
15 * 1998-01-01 Bernd Eckenfels reorganised usage()
16 * 2001-04-04 Arnaldo Carvalho de Melo - use setlocale
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/ioctl.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
26 #include <net/if_arp.h>
36 #define DFLT_HW "ether"
40 #include "net-support.h"
42 #include "pathnames.h"
44 static char no_rarp_message
[] = N_("This kernel does not support RARP.\n");
46 static char version_string
[] = RELEASE
"\nrarp 1.03 (2001-04-04)\n";
48 static struct hwtype
*hardware
= NULL
;
50 /* Delete an entry from the RARP cache. */
51 static int rarp_delete(int fd
, struct hostent
*hp
)
54 struct sockaddr_in
*si
;
55 unsigned int found
= 0;
58 /* The host can have more than one address, so we loop on them. */
59 for (addr
= hp
->h_addr_list
; *addr
!= NULL
; addr
++) {
60 memset((char *) &req
, 0, sizeof(req
));
61 si
= (struct sockaddr_in
*) &req
.arp_pa
;
62 si
->sin_family
= hp
->h_addrtype
;
63 memcpy((char *) &si
->sin_addr
, *addr
, hp
->h_length
);
65 /* Call the kernel. */
66 if (ioctl(fd
, SIOCDRARP
, &req
) == 0) {
73 fputs(_(no_rarp_message
), stderr
);
83 printf(_("no RARP entry for %s.\n"), hp
->h_name
);
88 /* Set an entry in the RARP cache. */
89 static int rarp_set(int fd
, struct hostent
*hp
, char *hw_addr
)
92 struct sockaddr_in
*si
;
95 if (hardware
->input(hw_addr
, &sap
)) {
96 fprintf(stderr
, _("%s: bad hardware address\n"), hw_addr
);
99 /* Clear and fill in the request block. */
100 memset((char *) &req
, 0, sizeof(req
));
101 si
= (struct sockaddr_in
*) &req
.arp_pa
;
102 si
->sin_family
= hp
->h_addrtype
;
103 memcpy((char *) &si
->sin_addr
, hp
->h_addr_list
[0], hp
->h_length
);
104 req
.arp_ha
.sa_family
= hardware
->type
;
105 memcpy(req
.arp_ha
.sa_data
, sap
.sa_data
, hardware
->alen
);
107 /* Call the kernel. */
108 if (ioctl(fd
, SIOCSRARP
, &req
) < 0) {
110 fputs(_(no_rarp_message
), stderr
);
118 /* Process an EtherFile */
119 static int rarp_file(int fd
, const char *name
)
127 if ((fp
= fopen(name
, "r")) == NULL
) {
128 fprintf(stderr
, _("rarp: cannot open file %s:%s.\n"), name
, strerror(errno
));
131 /* Read the lines in the file. */
133 while (fgets(buff
, sizeof(buff
), fp
)) {
135 if (buff
[0] == '#' || buff
[0] == '\0')
137 if ((addr
= strtok(buff
, "\n \t")) == NULL
)
139 if ((host
= strtok(NULL
, "\n \t")) == NULL
) {
140 fprintf(stderr
, _("rarp: format error at %s:%u\n"), name
, linenr
);
143 if ((hp
= gethostbyname(host
)) == NULL
) {
144 fprintf(stderr
, _("rarp: %s: unknown host\n"), host
);
146 if (rarp_set(fd
, hp
, addr
) != 0) {
147 fprintf(stderr
, _("rarp: cannot set entry from %s:%u\n"), name
, linenr
);
155 static int display_cache(void)
157 FILE *fd
= fopen(_PATH_PROCNET_RARP
, "r");
161 fputs(_(no_rarp_message
), stderr
);
163 perror(_PATH_PROCNET_RARP
);
166 while (feof(fd
) == 0) {
167 if (fgets(buffer
, 255, fd
))
168 fputs(buffer
, stdout
);
174 static void usage(void)
176 fprintf(stderr
, _("Usage: rarp -a list entries in cache.\n"));
177 fprintf(stderr
, _(" rarp -d <hostname> delete entry from cache.\n"));
178 fprintf(stderr
, _(" rarp [<HW>] -s <hostname> <hwaddr> add entry to cache.\n"));
179 fprintf(stderr
, _(" rarp -f add entries from /etc/ethers.\n"));
180 fprintf(stderr
, _(" rarp -V display program version.\n\n"));
182 fprintf(stderr
, _(" <HW>=Use '-H <hw>' to specify hardware address type. Default: %s\n"), DFLT_HW
);
183 fprintf(stderr
, _(" List of possible hardware types (which support ARP):\n"));
184 print_hwlist(1); /* 1 = ARPable */
188 #define MODE_DISPLAY 1
189 #define MODE_DELETE 2
191 #define MODE_ETHERS 4
193 static struct option longopts
[] =
195 {"version", 0, NULL
, 'V'},
196 {"verbose", 0, NULL
, 'v'},
197 {"list", 0, NULL
, 'a'},
198 {"set", 0, NULL
, 's'},
199 {"delete", 0, NULL
, 'd'},
200 {"help", 0, NULL
, 'h'},
204 int main(int argc
, char **argv
)
206 int result
= 0, mode
= 0, c
, nargs
= 0, verbose
= 0;
212 setlocale (LC_ALL
, "");
213 bindtextdomain("net-tools", "/usr/share/locale");
214 textdomain("net-tools");
217 /* Get a default hardware type. */
218 hardware
= get_hwtype(DFLT_HW
);
221 c
= getopt_long(argc
, argv
, "-ht:aHdsVvf", longopts
, NULL
);
228 fprintf(stderr
, version_string
);
238 fprintf(stderr
, _("%s: illegal option mix.\n"), argv
[0]);
241 mode
= (c
== 'a' ? MODE_DISPLAY
: (c
== 'd' ? MODE_DELETE
: MODE_SET
));
250 hardware
= get_hwtype(optarg
);
260 args
[nargs
++] = optarg
;
268 if (hardware
== NULL
) {
269 fprintf(stderr
, _("rarp: %s: unknown hardware type.\n"), optarg
);
277 if (nargs
!= (mode
- 1)) {
280 result
= display_cache();
285 if (nargs
!= (mode
- 1)) {
288 if ((hp
= gethostbyname(args
[0])) == NULL
) {
289 fprintf(stderr
, _("rarp: %s: unknown host\n"), args
[0]);
292 if (fd
= socket(PF_INET
, SOCK_DGRAM
, 0), fd
< 0) {
296 result
= (mode
== MODE_DELETE
) ? rarp_delete(fd
, hp
) : rarp_set(fd
, hp
, args
[1]);
301 if (nargs
!= 0 && nargs
!= 1)
303 if (fd
= socket(PF_INET
, SOCK_DGRAM
, 0), fd
< 0) {
307 result
= rarp_file(fd
, nargs
? args
[0] : _PATH_ETHERS
);