3 * arp.c --- arp utility for AmiTCP/IP
5 * Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
6 * Helsinki University of Technology, Finland.
8 * Copyright © 2005 Pavel Fedin
10 * Created : Sun Apr 18 05:08:20 1993 ppessi
11 * Last modified: Wed Feb 16 19:48:50 1994 ppessi
14 * Revision 1.2 2005/12/22 06:44:55 sonic_amiga
15 * - Fixed address printout in "arp" tool.
16 * - "netstat" fully works now.
17 * - Improved hostname handling.
18 * - Fixed FD_ACCEPT generation
19 * - DHCP client now supports nameservers option
21 * Revision 1.1.1.1 2005/12/07 10:50:36 sonic_amiga
22 * First full import into the CVS
24 * Revision 3.2 1994/05/02 19:39:03 jraja
25 * Update for the new net.lib
27 * Revision 3.1 1994/02/21 20:32:19 ppessi
28 * Changed the version tag.
30 * Revision 1.10 1993/11/07 00:19:45 ppessi
31 * Reverted back to scanf()
33 * Revision 1.9 1993/10/29 01:26:40 ppessi
34 * Implemented dumping of arp tables.
35 * Cleaned up code, fixed close() bug.
38 static const char version
[] __attribute__((used
)) = "$VER: arp 3.2 (12.09.2005) "
39 "Copyright © 2005 Pavel Fedin <sonic_amiga@rambler.ru>\n"
40 "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
41 "Helsinki University of Technology, Finland.\n"
42 "Copyright © 1984 The Regents of the University of California.\n"
43 "All rights reserved.\n";
47 * Copyright © 1984 Regents of the University of California.
48 * All rights reserved.
50 * This code is derived from software contributed to Berkeley by
51 * Sun Microsystems, Inc.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 * must display the following acknowledgement:
63 * This product includes software developed by the University of
64 * California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 * may be used to endorse or promote products derived from this software
67 * without specific prior written permission.
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82 /****** netutil.doc/arp *****************************************************
85 * Arp - address resolution display and control
89 * arp -a [netname | hostname]
91 * arp -s hostname address [temp] [pub]
95 * Arp displays and modifies the Internet to hardware address
96 * translation tables used by the Address Resolution Protocol. The
97 * hardware address is a hexadecimal string with each octet separated
98 * by a colon, for instance 0:12:ff:a. The length of the address must
99 * be correct for the specified interface.
102 * none If no options are specified (first form above), arp displays
103 * the current ARP entry for hostname. The hostname must either
104 * appear in the hostname database (SEE hosts), or be a DARPA
105 * Internet address expressed in Internet standard "dot
106 * notation". Hostname can also be resolved by nameserver.
108 * -a Display all current ARP entries by reading the address mapping
109 * table of the specified (sub)network. `Hostname' is used to as
110 * default network specifier.
112 * -d If an ARP entry exists for the host called hostname, delete
113 * it. [This requires super-user privileges.]
115 * -s Create an ARP entry for the host called hostname with the
116 * hardware station address address. The hardware station address
117 * is given as hexadecimal bytes separated by colons. If an ARP
118 * entry already exists for hostname, the existing entry is
119 * updated with the new information. The entry is permanent
120 * unless the word temp is given in the command. If the word pub
121 * is specified, the entry is published, which means that this
122 * system will act as an ARP server responding to requests for
123 * hostname even though the host address is not its own.
125 * -f Read file filename and set multiple entries in the ARP tables.
126 * Entries in the file should be of the form:
128 * hostname address [temp] [pub]
130 * Argument meanings are the same as for the -s option.
133 * Arp was developed by the University of California, Berkeley, for the
137 * ifconfig, netif.protocols/arp, "net/if_arp.h"
139 *****************************************************************************
144 * arp - display, set, and delete arp table entries
148 #include <proto/dos.h>
149 #include <proto/socket.h>
150 #if !defined(__AROS__)
151 #include <clib/netlib_protos.h>
153 #include <proto/exec.h>
157 #include <sys/param.h>
158 #include <sys/socket.h>
159 #include <sys/sockio.h>
161 #include <arpa/inet.h>
163 #include <netinet/in.h>
169 #if defined(__AROS__)
174 struct Library
* SocketBase
;
176 #define max(a,b) ((a) > (b) ? (a) : (b))
178 static int file(char *name
);
179 static int set(int argc
, char **argv
);
180 static void get(char *host
);
181 static void delete(char *host
);
182 static int arpreq_print(struct arpreq
*ar
, int bynumber
);
183 static void sana_print(const u_char
*cp
, int len
);
184 static int sana_aton(const char *a
, u_char
*n
, u_char
*lenp
);
185 static void usage(void);
186 static void dump(char *name
);
187 char * strsep(register char **stringp
, register const char *delim
);
190 "usage: arp hostname\n"
191 " arp -a [netname | hostname]\n"
193 " arp -s hostname address [temp] [pub]\n"
194 " arp -f filename\n";
196 #define SOCKET_VERSION 3
197 const TEXT socket_name
[] = "bsdsocket.library";
205 if (!(SocketBase
= OpenLibrary(socket_name
, SOCKET_VERSION
)))
210 while ((ch
= getopt(argc
, argv
, "adsf")) != EOF
)
214 char myname
[MAXHOSTNAMELEN
];
222 gethostname(myname
, sizeof(myname
));
233 if (argc
< 4 || argc
> 7)
235 exit(set(argc
-2, &argv
[2]) ? 1 : 0);
239 exit (file(argv
[2]) ? 1 : 0);
251 * Process a file to set standard arp entries
258 char line
[100], arg
[5][50], *args
[5];
260 if ((fp
= fopen(name
, "r")) == NULL
) {
261 fprintf(stderr
, "arp: cannot open %s\n", name
);
265 args
[0] = &arg
[0][0];
266 args
[1] = &arg
[1][0];
267 args
[2] = &arg
[2][0];
268 args
[3] = &arg
[3][0];
269 args
[4] = &arg
[4][0];
272 while(fgets(line
, 100, fp
) != NULL
) {
273 i
= sscanf(line
, "%s %s %s %s %s", arg
[0], arg
[1], arg
[2], arg
[3], arg
[4]);
275 fprintf(stderr
, "arp: bad line: %s\n", line
);
287 * Set an individual arp entry
290 set(int argc
, char **argv
)
294 struct sockaddr_in
*sin
;
297 char *host
= argv
[0], *eaddr
= argv
[1];
301 bzero((caddr_t
)&ar
, sizeof ar
);
302 sin
= (struct sockaddr_in
*)&ar
.arp_pa
;
303 sin
->sin_len
= sizeof(*sin
);
304 sin
->sin_family
= AF_INET
;
305 sin
->sin_addr
.s_addr
= inet_addr(host
);
306 if (sin
->sin_addr
.s_addr
== -1) {
307 if (!(hp
= gethostbyname(host
))) {
308 fprintf(stderr
, "arp: %s: ", host
);
309 /* TODO: NicJA - Implement herror() */
310 #if !defined(__AROS__)
311 herror((char *)NULL
);
315 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
316 sizeof sin
->sin_addr
);
318 ea
= (u_char
*)ar
.arp_ha
.sa_data
;
319 if (sana_aton(eaddr
, ea
, &ar
.arp_ha
.sa_len
))
321 ar
.arp_ha
.sa_len
+= 2;
322 ar
.arp_flags
= ATF_PERM
;
324 if (strncmp(argv
[0], "temp", 4) == 0)
325 ar
.arp_flags
&= ~ATF_PERM
;
326 else if (strncmp(argv
[0], "pub", 3) == 0)
327 ar
.arp_flags
|= ATF_PUBL
;
328 else if (strncmp(argv
[0], "trail", 5) == 0)
329 ar
.arp_flags
|= ATF_USETRAILERS
;
333 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
335 perror("arp: socket");
338 if (IoctlSocket(s
, SIOCSARP
, (caddr_t
)&ar
) < 0) {
348 * Display an individual arp entry
355 struct sockaddr_in
*sin
;
358 bzero((caddr_t
)&ar
, sizeof ar
);
359 sin
= (struct sockaddr_in
*)&ar
.arp_pa
;
360 sin
->sin_len
= sizeof(*sin
);
361 sin
->sin_family
= AF_INET
;
362 sin
->sin_addr
.s_addr
= inet_addr(host
);
363 if (sin
->sin_addr
.s_addr
== -1) {
364 if (!(hp
= gethostbyname(host
))) {
365 fprintf(stderr
, "arp: %s: ", host
);
366 /* TODO: NicJA - Implement herror() */
367 #if !defined(__AROS__)
368 herror((char *)NULL
);
372 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
, sizeof sin
->sin_addr
);
374 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
376 perror("arp: socket");
379 if (IoctlSocket(s
, SIOCGARP
, (caddr_t
)&ar
) < 0) {
381 printf("%s (%s) -- no entry\n", host
, inet_ntoa(sin
->sin_addr
));
388 (void)arpreq_print(&ar
, 0);
392 * Delete an arp entry
399 struct sockaddr_in
*sin
;
402 bzero((caddr_t
)&ar
, sizeof ar
);
403 sin
= (struct sockaddr_in
*)&ar
.arp_pa
;
404 sin
->sin_len
= sizeof(*sin
);
405 sin
->sin_family
= AF_INET
;
406 sin
->sin_addr
.s_addr
= inet_addr(host
);
407 if (sin
->sin_addr
.s_addr
== -1) {
408 if (!(hp
= gethostbyname(host
))) {
409 fprintf(stderr
, "arp: %s: ", host
);
410 /* TODO: NicJA - Implement herror() */
411 #if !defined(__AROS__)
412 herror((char *)NULL
);
416 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
417 sizeof sin
->sin_addr
);
419 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
421 perror("arp: socket");
424 if (IoctlSocket(s
, SIOCDARP
, (caddr_t
)&ar
) < 0) {
426 printf("%s (%s) -- no entry\n",
427 host
, inet_ntoa(sin
->sin_addr
));
433 printf("%s (%s) deleted\n", host
, inet_ntoa(sin
->sin_addr
));
437 * Dump the entire arp table
442 struct arptabreq atr
;
444 struct sockaddr_in
*sin
;
448 bzero((caddr_t
)&atr
, sizeof atr
);
450 /* Identify the used interface according the host/net name */
451 sin
= (struct sockaddr_in
*)&atr
.atr_arpreq
.arp_pa
;
452 sin
->sin_len
= sizeof(*sin
);
453 sin
->sin_family
= AF_INET
;
454 sin
->sin_addr
.s_addr
= inet_addr(host
);
455 if (sin
->sin_addr
.s_addr
== -1) {
457 struct netent
*np
= NULL
;
458 if (!(hp
= gethostbyname(host
)) &&
459 !(np
= getnetbyname(host
))) {
460 fprintf(stderr
, "arp: %s: ", host
);
461 /* TODO: NicJA - Implement herror() */
462 #if !defined(__AROS__)
463 herror((char *)NULL
);
468 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
, sizeof sin
->sin_addr
);
470 bcopy((char *)&np
->n_net
, (char *)&sin
->sin_addr
, sizeof np
->n_net
);
473 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
475 perror("arp: socket");
479 if (IoctlSocket(s
, SIOCGARPT
, (caddr_t
)&atr
) < 0) {
484 n
= atr
.atr_size
= atr
.atr_inuse
;
486 ar
= atr
.atr_table
= malloc(sizeof(*ar
) * n
);
488 perror("arp: malloc");
491 if (IoctlSocket(s
, SIOCGARPT
, (caddr_t
)&atr
) < 0) {
495 /* Entries may be deleted */
496 n
= max(n
, atr
.atr_inuse
);
502 bynumber
= arpreq_print(ar
++, bynumber
);
507 arpreq_print(struct arpreq
*ar
, int bynumber
)
509 struct sockaddr_in
*sin
;
513 sin
= (struct sockaddr_in
*)&ar
->arp_pa
;
516 hp
= gethostbyaddr((caddr_t
)&sin
->sin_addr
,
517 sizeof(struct in_addr
), AF_INET
);
525 if (h_errno
== TRY_AGAIN
)
529 Printf("%s (%s) at ", host
, inet_ntoa(sin
->sin_addr
));
530 if (ar
->arp_flags
& ATF_COM
)
531 sana_print(ar
->arp_ha
.sa_data
, ar
->arp_ha
.sa_len
- 2);
533 Printf("(incomplete)");
534 if (ar
->arp_flags
& ATF_PERM
)
535 Printf(" permanent");
536 if (ar
->arp_flags
& ATF_PUBL
)
537 Printf(" published");
538 if (ar
->arp_flags
& ATF_USETRAILERS
)
546 sana_print(const u_char
*cp
, int len
)
549 "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx";
553 format
[4*len
- 1] = '\0';
554 for (i
= 0; i
< len
; i
++)
556 VPrintf(format
, (RAWARG
)o
);
561 sana_aton(const char *str
, u_char
*n
, u_char
*lenp
)
567 for (i
= 0; i
< 16; a
++) {
569 while ((c
= *a
- '0') <= 9
570 || (c
= c
- 'A' + '0' + 10) >= 9 && c
< 16 /*ABCDEF*/
571 || (c
= c
- 'a' + 'A') >= 9 && c
< 16) /*abcdef*/ {
573 o
[i
] = (o
[i
] << 4) + c
;
588 fprintf(stderr
, "arp: invalid SANA-II address '%s'\n", str
);