2 * Copyright © 1983, 1989 The Regents of the University of California.
4 * Copyright © 2005 Pavel Fedin
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 static char sccsid
[] = "@(#)route.c 5.35 (Berkeley) 6/27/91";
39 /****** netutil.doc/route ***************************************************
42 * route - manually manipulate the routing tables
45 * route [-n] [-q] [-v] command [modifiers] destination gateway
48 * Route is a program used to manually manipulate the network routing
51 * Options supported by route:
53 * -n Prevent attempts to print host and network names
54 * symbolically when reporting actions.
56 * -v (verbose) Print additional details.
58 * -q Suppress all output.
60 * Commands accepted by route:
63 * delete Delete a specific route.
65 * The destination is the destination host or network, gateway is the
66 * next-hop gateway to which packets should be addressed. Routes to a
67 * particular host are distinguished from those to a network by
68 * interpreting the Internet address associated with destination. The
69 * optional modifiers -net and -host force the destination to be
70 * interpreted as a network or a host, respectively. Otherwise, if the
71 * destination has a ``local address part'' of INADDR_ANY, or if the
72 * destination is the symbolic name of a network, then the route is
73 * assumed to be to a network; otherwise, it is presumed to be a route
76 * For example, 128.32 is interpreted as -host 128.0.0.32; 128.32.130
77 * is interpreted as -host 128.32.0.130; -net 128.32 is interpreted as
78 * 128.32.0.0; and -net 128.32.130 is interpreted as 128.32.130.0.
80 * To add a default route, give the destination as 'default'.
82 * If the route is via an interface rather than via a gateway, the
83 * -interface modifier should be specified; the gateway given is the
84 * address of this host on the common network, indicating the interface
85 * to be used for transmission.
87 * The optional -netmask qualifier is used to specify the netmask of
88 * the interface. One specifies an additional ensuing address parameter
89 * (to be interpreted as a network mask). The implicit network mask
90 * generated can be overridden by making sure this option follows the
91 * destination parameter.
93 * All symbolic names specified for a destination or gateway are looked
94 * up first as a host name using gethostbyname(). If this lookup fails,
95 * getnetbyname() is then used to interpret the name as that of a
99 * add [host | network ] %s: gateway %s flags %x
100 * The specified route is being added to the tables. The values
101 * printed are from the routing table entry supplied in the
102 * IoctlSocket() call. If the gateway address used was not the
103 * primary address of the gateway (the first one returned by
104 * gethostbyname()), the gateway address is printed numerically
105 * as well as symbolically.
107 * delete [ host | network ] %s: gateway %s flags %x
108 * As above, but when deleting an entry.
110 * Network is unreachable
111 * An attempt to add a route failed because the gateway listed
112 * was not on a directly-connected network. The next-hop
113 * gateway must be given.
116 * A delete operation was attempted for an entry which wasn't
117 * present in the tables.
119 * routing table overflow
120 * An add operation was attempted, but the system was low on
121 * resources and was unable to allocate memory to create the
125 * ifconfig, protocols/routing
128 * The route command appeared in 4.2BSD.
130 *****************************************************************************
136 #include <sys/errno.h>
141 #include <stdio.h> /* NC */
142 #include <sys/param.h>
143 #include <sys/socket.h>
144 #include <sys/sockio.h>
146 #include <net/route.h>
147 #include <netinet/in.h>
148 #include <arpa/inet.h>
153 #include <proto/socket.h>
154 #include <proto/exec.h>
155 #define herror(x) perror(x)
156 #define ioctl IoctlSocket
157 /*#include <clib/netlib_protos.h>*/
163 #include "keywords.h"
167 struct ortentry route
;
170 struct sockaddr_in s_in
;
172 struct sockaddr_ns sns
;
173 struct sockaddr_iso siso
;
174 struct sockaddr_dl sdl
;
175 struct sockaddr_x25 sx25
;
177 } so_dst
, so_gate
, so_mask
, so_genmask
, so_ifa
, so_ifp
;
179 union sockunion
*so_addrs
[] =
180 { &so_dst
, &so_gate
, &so_mask
, &so_genmask
, &so_ifp
, &so_ifa
, 0};
182 typedef union sockunion
*sup
;
185 int forcehost
, forcenet
, doflush
, nflag
, af
, qflag
, tflag
, Cflag
,
187 int iflag
, verbose
, aflen
= sizeof (struct sockaddr_in
);
188 int locking
, lockrest
, debugonly
;
189 struct sockaddr_in s_in
= { sizeof(s_in
), AF_INET
};
190 struct rt_metrics rt_metrics
;
193 struct in_addr
inet_makeaddr();
195 char *routename(struct sockaddr
*sa
), *netname(struct sockaddr
*sa
);
196 void flushroutes(int argc
, char *argv
[]),
197 newroute(int argc
, char **argv
), monitor(void), sockaddr();
198 void print_getmsg(), print_rtmsg(), pmsg_common(), sodump(), bprintf();
199 int getaddr(int which
, char *s
, struct hostent
**hpp
), rtmsg();
200 int GetOpt(int argc
, char **argv
, char *opts
);
201 VOID
CleanUpExit(LONG error
);
203 extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa();
206 #define SOCKET_VERSION 3
207 struct Library
*SocketBase
;
208 const TEXT version
[] = "route 3.4 (14.10.2005)";
209 const TEXT socket_name
[] = "bsdsocket.library";
215 (void) fprintf(stderr
, "route: botched keyword: %s\n", cp
);
216 (void) fprintf(stderr
,
217 "usage: route [ -Cnqv ] cmd [[ -<qualifers> ] args ]\n");
227 (void) fprintf(stderr
, "route: ");
229 (void) fprintf(stderr
, "%s: ", s
);
230 (void) fprintf(stderr
, "%s\n", strerror(sverrno
));
236 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
237 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
247 SocketBase
= OpenLibrary(socket_name
, SOCKET_VERSION
);
248 if(SocketBase
== NULL
) {
249 fprintf(stderr
, "route: cannot open bsdsocket.library version 3\n");
252 SetErrnoPtr(&errno
, sizeof(errno
));
257 while ((ch
= GetOpt(argc
, argv
, "Cnqtv")) != EOF
)
260 Cflag
= 1; /* Use old ioctls. */
281 Cflag
= 1; /* Force old ioctls. */
284 s
= socket(AF_INET
, SOCK_RAW
, 0);
288 switch (keyword(*argv
)) {
297 usage("change or get with -C");
302 newroute(argc
, argv
);
311 flushroutes(argc
, argv
);
322 * Purge all entries in the routing tables not
323 * associated with network interfaces.
326 flushroutes(argc
, argv
)
331 int needed
, seqno
, rlen
;
332 char *buf
, *next
, *lim
;
333 register struct rt_msghdr
*rtm
;
336 quit("must be root to alter routing table");
337 shutdown(s
, 0); /* Don't want to read back our messages */
340 if (argc
== 2 && **argv
== '-')
341 switch (keyword(*argv
+ 1)) {
362 if ((needed
= getkerninfo(KINFO_RT_DUMP
, 0, 0, 0)) < 0)
363 quit("route-getkerninfo-estimate");
364 if ((buf
= malloc(needed
)) == NULL
)
366 if ((rlen
= getkerninfo(KINFO_RT_DUMP
, buf
, &needed
, 0)) < 0)
367 quit("actual retrieval of routing table");
370 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
371 rtm
= (struct rt_msghdr
*)next
;
372 if ((rtm
->rtm_flags
& RTF_GATEWAY
) == 0)
375 struct sockaddr
*sa
= (struct sockaddr
*)(rtm
+ 1);
377 if (sa
->sa_family
!= af
)
380 rtm
->rtm_type
= RTM_DELETE
;
381 rtm
->rtm_seq
= seqno
;
382 rlen
= write(s
, next
, rtm
->rtm_msglen
);
383 if (rlen
< (int)rtm
->rtm_msglen
) {
384 (void) fprintf(stderr
,
385 "route: write to routing socket: %s\n",
387 (void) printf("got only %d for rlen\n", rlen
);
394 print_rtmsg(rtm
, rlen
);
396 struct sockaddr
*sa
= (struct sockaddr
*)(rtm
+ 1);
397 (void) printf("%-20.20s ", rtm
->rtm_flags
& RTF_HOST
?
398 routename(sa
) : netname(sa
));
399 sa
= (struct sockaddr
*)(sa
->sa_len
+ (char *)sa
);
400 (void) printf("%-20.20s ", routename(sa
));
401 (void) printf("done\n");
412 static char line
[50];
414 static char domain
[MAXHOSTNAMELEN
+ 1];
415 static int first
= 1;
420 if (gethostname(domain
, MAXHOSTNAMELEN
) == 0 &&
421 (cp
= index(domain
, '.')))
422 (void) strcpy(domain
, cp
+ 1);
426 switch (sa
->sa_family
) {
430 in
= ((struct sockaddr_in
*)sa
)->sin_addr
;
433 if (in
.s_addr
== INADDR_ANY
)
435 if (cp
== 0 && !nflag
) {
436 hp
= gethostbyaddr((char *)&in
, sizeof (struct in_addr
),
439 if ((cp
= index(hp
->h_name
, '.')) &&
440 !strcmp(cp
+ 1, domain
))
448 #define C(x) ((unsigned int)((x) & 0xff))
449 in
.s_addr
= ntohl(in
.s_addr
);
450 (void) sprintf(line
, "%u.%u.%u.%u", C(in
.s_addr
>> 24),
451 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8), C(in
.s_addr
));
457 return (ns_print((struct sockaddr_ns
*)sa
));
460 return (link_ntoa((struct sockaddr_dl
*)sa
));
463 (void) sprintf(line
, "iso %s",
464 iso_ntoa(&((struct sockaddr_iso
*)sa
)->siso_addr
));
468 { u_short
*s
= (u_short
*)sa
->sa_data
;
469 u_short
*slim
= s
+ ((sa
->sa_len
+ 1) >> 1);
470 char *cp
= line
+ sprintf(line
, "(%d)", sa
->sa_family
);
473 cp
+= sprintf(cp
, " %x", *s
++);
481 * Return the name of the network whose address is given.
482 * The address is assumed to be that of a net or subnet, not a host.
489 static char line
[50];
490 struct netent
*np
= 0;
496 switch (sa
->sa_family
) {
500 in
= ((struct sockaddr_in
*)sa
)->sin_addr
;
502 i
= in
.s_addr
= ntohl(in
.s_addr
);
507 mask
= IN_CLASSA_NET
;
509 } else if (IN_CLASSB(i
)) {
510 mask
= IN_CLASSB_NET
;
513 mask
= IN_CLASSC_NET
;
517 * If there are more bits than the standard mask
518 * would suggest, subnets must be in use.
519 * Guess at the subnet mask, assuming reasonable
520 * width subnet fields.
522 while (in
.s_addr
&~ mask
)
523 mask
= (long)mask
>> subnetshift
;
524 net
= in
.s_addr
& mask
;
525 while ((mask
& 1) == 0)
526 mask
>>= 1, net
>>= 1;
527 np
= getnetbyaddr(net
, AF_INET
);
533 else if ((in
.s_addr
& 0xffffff) == 0)
534 (void) sprintf(line
, "%u", C(in
.s_addr
>> 24));
535 else if ((in
.s_addr
& 0xffff) == 0)
536 (void) sprintf(line
, "%u.%u", C(in
.s_addr
>> 24),
538 else if ((in
.s_addr
& 0xff) == 0)
539 (void) sprintf(line
, "%u.%u.%u", C(in
.s_addr
>> 24),
540 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8));
542 (void) sprintf(line
, "%u.%u.%u.%u", C(in
.s_addr
>> 24),
543 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8),
549 return (ns_print((struct sockaddr_ns
*)sa
));
553 return (link_ntoa((struct sockaddr_dl
*)sa
));
556 (void) sprintf(line
, "iso %s",
557 iso_ntoa(&((struct sockaddr_iso
*)sa
)->siso_addr
));
561 { u_short
*s
= (u_short
*)sa
->sa_data
;
562 u_short
*slim
= s
+ ((sa
->sa_len
+ 1)>>1);
563 char *cp
= line
+ sprintf(line
, "af %d:", sa
->sa_family
);
566 cp
+= sprintf(cp
, " %x", *s
++);
574 set_metric(char *value
, int key
)
578 u_long noval
, *valp
= &noval
;
581 #define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break
582 caseof(K_MTU
, RTV_MTU
, rmx_mtu
);
583 caseof(K_HOPCOUNT
, RTV_HOPCOUNT
, rmx_hopcount
);
584 caseof(K_EXPIRE
, RTV_EXPIRE
, rmx_expire
);
585 caseof(K_RECVPIPE
, RTV_RPIPE
, rmx_recvpipe
);
586 caseof(K_SENDPIPE
, RTV_SPIPE
, rmx_sendpipe
);
587 caseof(K_SSTHRESH
, RTV_SSTHRESH
, rmx_ssthresh
);
588 caseof(K_RTT
, RTV_RTT
, rmx_rtt
);
589 caseof(K_RTTVAR
, RTV_RTTVAR
, rmx_rttvar
);
592 if (lockrest
|| locking
)
593 rt_metrics
.rmx_locks
|= flag
;
603 register char **argv
;
605 char *cmd
, *dest
= "", *gateway
= "", *err
;
606 int ishost
= 0, ret
, attempts
, oerrno
, flags
= 0;
608 struct hostent
*hp
= 0;
612 quit("must be root to alter routing table");
616 shutdown(s
, 0); /* Don't want to read back our messages */
618 if (**(++argv
)== '-') {
619 switch (key
= keyword(1 + *argv
)) {
623 aflen
= sizeof(struct sockaddr_dl
);
628 aflen
= sizeof(struct sockaddr_iso
);
633 aflen
= sizeof(struct sockaddr_in
);
638 aflen
= sizeof(struct sockaddr_x25
);
642 aflen
= sizeof(union sockunion
);
646 aflen
= sizeof(struct sockaddr_ns
);
672 flags
|= RTF_CLONING
;
675 flags
|= RTF_XRESOLVE
;
679 (void) getaddr(RTA_IFA
, *++argv
, 0);
683 (void) getaddr(RTA_IFP
, *++argv
, 0);
687 (void) getaddr(RTA_GENMASK
, *++argv
, 0);
691 (void) getaddr(RTA_GATEWAY
, *++argv
, 0);
695 ishost
= getaddr(RTA_DST
, *++argv
, &hp
);
700 (void) getaddr(RTA_NETMASK
, *++argv
, 0);
714 set_metric(*++argv
, key
);
720 if ((rtm_addrs
& RTA_DST
) == 0) {
722 ishost
= getaddr(RTA_DST
, *argv
, &hp
);
723 } else if ((rtm_addrs
& RTA_GATEWAY
) == 0) {
725 (void) getaddr(RTA_GATEWAY
, *argv
, &hp
);
727 int ret
= atoi(*argv
);
729 printf("%s,%s", "old usage of trailing 0",
730 "assuming route to if\n");
733 } else if (ret
> 0 && ret
< 10) {
734 printf("old usage of trailing digit, ");
735 printf("assuming route via gateway\n");
739 (void) getaddr(RTA_NETMASK
, *argv
, 0);
751 flags
|= RTF_GATEWAY
;
752 for (attempts
= 1; ; attempts
++) {
754 if (Cflag
&& (af
== AF_INET
|| af
== AF_NS
)) {
755 D(printf ("Flags: 0x%08lx\n", flags
);)
756 D(printf ("Dst = 0x%08lx\n", so_dst
.s_in
.sin_addr
.s_addr
);)
757 D(printf ("Gate = 0x%08lx\n", so_gate
.s_in
.sin_addr
.s_addr
);)
758 route
.rt_flags
= flags
;
759 route
.rt_dst
= so_dst
.sa
;
760 route
.rt_gateway
= so_gate
.sa
;
761 if ((ret
= ioctl(s
, *cmd
== 'a' ? SIOCADDRT
: SIOCDELRT
,
762 (caddr_t
)&route
)) == 0)
766 if ((ret
= rtmsg(*cmd
, flags
)) == 0)
770 if (errno
!= ENETUNREACH
&& errno
!= ESRCH
)
772 if (af
== AF_INET
&& hp
&& hp
->h_addr_list
[1]) {
774 bcopy(hp
->h_addr_list
[0], (caddr_t
)&so_dst
.s_in
.sin_addr
,
782 (void) printf("%s %s %s: gateway %s", cmd
, ishost
? "host" : "net",
784 if (attempts
> 1 && ret
== 0)
786 struct sockaddr_in
*route_sin
= (struct sockaddr_in
*)&route
.rt_gateway
;
787 (void) printf(" (%s)",
788 Inet_NtoA(route_sin
->sin_addr
.s_addr
));
795 err
= "not in table";
798 err
= "entry in use";
801 err
= "routing table overflow";
804 err
= strerror(oerrno
);
807 (void) printf(": %s\n", err
);
812 inet_makenetandmask(u_long net
, register struct sockaddr_in
*s_in
)
814 u_long addr
, mask
= 0;
817 rtm_addrs
|= RTA_NETMASK
;
820 else if (net
< 128) {
821 addr
= net
<< IN_CLASSA_NSHIFT
;
822 mask
= IN_CLASSA_NET
;
823 } else if (net
< 65536) {
824 addr
= net
<< IN_CLASSB_NSHIFT
;
825 mask
= IN_CLASSB_NET
;
826 } else if (net
< 16777216L) {
827 addr
= net
<< IN_CLASSC_NSHIFT
;
828 mask
= IN_CLASSC_NET
;
831 if ((addr
& IN_CLASSA_HOST
) == 0)
832 mask
= IN_CLASSA_NET
;
833 else if ((addr
& IN_CLASSB_HOST
) == 0)
834 mask
= IN_CLASSB_NET
;
835 else if ((addr
& IN_CLASSC_HOST
) == 0)
836 mask
= IN_CLASSC_NET
;
840 s_in
->sin_addr
.s_addr
= htonl(addr
);
841 s_in
= &so_mask
.s_in
;
842 s_in
->sin_addr
.s_addr
= htonl(mask
);
844 s_in
->sin_family
= 0;
845 cp
= (char *)(&s_in
->sin_addr
+ 1);
846 while (*--cp
== 0 && cp
> (char *)s_in
)
848 s_in
->sin_len
= 1 + cp
- (char *)s_in
;
852 * Interpret an argument as a network address of some kind,
853 * returning 1 if a host address, 0 if a network address.
856 getaddr(which
, s
, hpp
)
859 struct hostent
**hpp
;
863 struct ns_addr
ns_addr();
864 struct iso_addr
*iso_addr();
872 aflen
= sizeof(struct sockaddr_in
);
876 case RTA_DST
: su
= so_addrs
[0]; su
->sa
.sa_family
= af
; break;
877 case RTA_GATEWAY
: su
= so_addrs
[1]; su
->sa
.sa_family
= af
; break;
878 case RTA_NETMASK
: su
= so_addrs
[2]; break;
879 case RTA_GENMASK
: su
= so_addrs
[3]; break;
880 case RTA_IFP
: su
= so_addrs
[4]; su
->sa
.sa_family
= af
; break;
881 case RTA_IFA
: su
= so_addrs
[5]; su
->sa
.sa_family
= af
; break;
882 default: usage("Internal Error"); /*NOTREACHED*/
884 su
->sa
.sa_len
= aflen
;
885 if (strcmp(s
, "default") == 0) {
889 (void) getaddr(RTA_NETMASK
, s
, 0);
912 if (((val
= inet_addr(s
)) != -1) &&
913 (which
!= RTA_DST
|| forcenet
== 0)) {
914 su
->s_in
.sin_addr
.s_addr
= val
;
915 if (Inet_LnaOf(su
->s_in
.sin_addr
.s_addr
) != INADDR_ANY
)
919 out
: if (which
== RTA_DST
)
920 inet_makenetandmask(val
, &su
->s_in
);
924 val
= inet_network(s
);
928 np
= getnetbyname(s
);
933 hp
= gethostbyname(s
);
936 su
->s_in
.sin_family
= hp
->h_addrtype
;
937 bcopy(hp
->h_addr
, (char *)&su
->s_in
.sin_addr
, hp
->h_length
);
940 (void) fprintf(stderr
, "%s: bad value\n", s
);
944 if (which
== RTA_DST
) {
945 extern short ns_bh
[3];
946 struct sockaddr_ns
*sms
= &(so_mask
.sns
);
947 bzero((char *)sms
, sizeof(*sms
));
950 sms
->sns_addr
.x_net
= *(union ns_net
*)ns_bh
;
951 rtm_addrs
|= RTA_NETMASK
;
953 su
->sns
.sns_addr
= ns_addr(s
);
954 return (!ns_nullhost(su
->sns
.sns_addr
));
956 su
->siso
.siso_addr
= *iso_addr(s
);
957 if (which
== RTA_NETMASK
|| which
== RTA_GENMASK
) {
958 register char *cp
= (char *)TSEL(&su
->siso
);
959 su
->siso
.siso_nlen
= 0;
960 do {--cp
;} while ((cp
> (char *)su
) && (*cp
== 0));
961 su
->siso
.siso_len
= 1 + cp
- (char *)su
;
965 ccitt_addr(s
, &su
->sx25
);
968 link_addr(s
, &su
->sdl
);
971 su
->sa
.sa_len
= sizeof(*su
);
972 sockaddr(s
, &su
->sa
);
979 short ns_nullh
[] = {0,0,0};
980 short ns_bh
[] = {-1,-1,-1};
985 struct sockaddr_ns
*sns
;
988 union { union ns_net net_e
; u_long long_e
; } net
;
990 static char mybuf
[50], cport
[10], chost
[25];
995 work
= sns
->sns_addr
;
996 port
= ntohs(work
.x_port
);
998 net
.net_e
= work
.x_net
;
999 if (ns_nullhost(work
) && net
.long_e
== 0) {
1002 (void) sprintf(mybuf
, "*.%XH", port
);
1006 if (bcmp((char *)ns_bh
, (char *)work
.x_host
.c_host
, 6) == 0)
1008 else if (bcmp((char *)ns_nullh
, (char *)work
.x_host
.c_host
, 6) == 0)
1011 q
= work
.x_host
.c_host
;
1012 (void) sprintf(chost
, "%02X%02X%02X%02X%02X%02XH",
1013 q
[0], q
[1], q
[2], q
[3], q
[4], q
[5]);
1014 for (p
= chost
; *p
== '0' && p
< chost
+ 12; p
++)
1019 (void) sprintf(cport
, ".%XH", htons(port
));
1023 (void) sprintf(mybuf
,"%XH.%s%s", ntohl(net
.long_e
), host
, cport
);
1037 n
= read(s
, msg
, 2048);
1038 (void) printf("got message of size %d\n", n
);
1039 print_rtmsg((struct rt_msghdr
*)msg
);
1046 struct rt_msghdr m_rtm
;
1056 register char *cp
= m_rtmsg
.m_space
;
1059 #define NEXTADDR(w, u) \
1060 if (rtm_addrs & (w)) {\
1061 l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
1062 if (verbose) sodump(&(u),"u");\
1066 bzero((char *)&m_rtmsg
, sizeof(m_rtmsg
));
1069 else if (cmd
== 'c')
1071 else if (cmd
== 'g')
1075 #define rtm m_rtmsg.m_rtm
1077 rtm
.rtm_flags
= flags
;
1078 rtm
.rtm_version
= RTM_VERSION
;
1079 rtm
.rtm_seq
= ++seq
;
1080 rtm
.rtm_addrs
= rtm_addrs
;
1081 rtm
.rtm_rmx
= rt_metrics
;
1082 rtm
.rtm_inits
= rtm_inits
;
1084 if (rtm_addrs
& RTA_NETMASK
)
1086 NEXTADDR(RTA_DST
, so_dst
);
1087 NEXTADDR(RTA_GATEWAY
, so_gate
);
1088 NEXTADDR(RTA_NETMASK
, so_mask
);
1089 NEXTADDR(RTA_GENMASK
, so_genmask
);
1090 NEXTADDR(RTA_IFP
, so_ifp
);
1091 NEXTADDR(RTA_IFA
, so_ifa
);
1092 rtm
.rtm_msglen
= l
= cp
- (char *)&m_rtmsg
;
1094 print_rtmsg(&rtm
, l
);
1097 if ((rlen
= write(s
, (char *)&m_rtmsg
, l
)) < 0) {
1098 perror("writing to routing socket");
1101 if (cmd
== RTM_GET
) {
1103 l
= read(s
, (char *)&m_rtmsg
, sizeof(m_rtmsg
));
1104 } while (l
> 0 && (rtm
.rtm_seq
!= seq
|| rtm
.rtm_pid
!= pid
));
1106 (void) fprintf(stderr
,
1107 "route: read from routing socket: %s\n",
1110 print_getmsg(&rtm
, l
);
1119 register char *cp1
, *cp2
;
1122 if ((rtm_addrs
& RTA_DST
) == 0)
1124 switch(so_dst
.sa
.sa_family
) {
1125 case AF_NS
: case AF_INET
: case 0:
1128 olen
= MIN(so_dst
.siso
.siso_nlen
, so_mask
.sa
.sa_len
- 6);
1130 cp1
= so_mask
.sa
.sa_len
+ 1 + (char *)&so_dst
;
1131 cp2
= so_dst
.sa
.sa_len
+ 1 + (char *)&so_dst
;
1134 cp2
= so_mask
.sa
.sa_len
+ 1 + (char *)&so_mask
;
1135 while (cp1
> so_dst
.sa
.sa_data
)
1137 switch(so_dst
.sa
.sa_family
) {
1139 so_dst
.siso
.siso_nlen
= olen
;
1143 char *msgtypes
[] = {
1145 "RTM_ADD: Add Route",
1146 "RTM_DELETE: Delete Route",
1147 "RTM_CHANGE: Change Metrics or flags",
1148 "RTM_GET: Report Metrics",
1149 "RTM_LOSING: Kernel Suspects Partitioning",
1150 "RTM_REDIRECT: Told to use different route",
1151 "RTM_MISS: Lookup failed on this address",
1152 "RTM_LOCK: fix specified metrics",
1153 "RTM_OLDADD: caused by SIOCADDRT",
1154 "RTM_OLDDEL: caused by SIOCDELRT",
1158 char metricnames
[] =
1159 "\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
1161 "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\017PROTO2\020PROTO1";
1165 print_rtmsg(rtm
, msglen
)
1166 register struct rt_msghdr
*rtm
;
1171 if (rtm
->rtm_version
!= RTM_VERSION
) {
1172 (void) printf("routing message version %d not understood\n",
1176 (void) printf("%s\npid: %d, len %d, seq %d, errno %d, flags:",
1177 msgtypes
[rtm
->rtm_type
], rtm
->rtm_pid
, rtm
->rtm_msglen
,
1178 rtm
->rtm_seq
, rtm
->rtm_errno
);
1179 bprintf(stdout
, rtm
->rtm_flags
, routeflags
);
1184 print_getmsg(rtm
, msglen
)
1185 register struct rt_msghdr
*rtm
;
1188 if (rtm
->rtm_version
!= RTM_VERSION
) {
1189 (void)printf("routing message version %d not understood\n",
1193 if (rtm
->rtm_msglen
> msglen
) {
1194 (void)printf("get length mismatch, in packet %d, returned %d\n",
1195 rtm
->rtm_msglen
, msglen
);
1197 (void) printf("RTM_GET: errno %d, flags:", rtm
->rtm_errno
);
1198 bprintf(stdout
, rtm
->rtm_flags
, routeflags
);
1199 (void) printf("\nmetric values:\n ");
1200 #define metric(f, e)\
1201 printf("%s: %d%s", __STRING(f), rtm->rtm_rmx.__CONCAT(rmx_,f), e)
1202 metric(recvpipe
, ", ");
1203 metric(sendpipe
, ", ");
1204 metric(ssthresh
, ", ");
1206 metric(rttvar
, ", ");
1207 metric(hopcount
, ", ");
1209 metric(expire
, "\n");
1216 register struct rt_msghdr
*rtm
;
1219 register struct sockaddr
*sa
;
1222 (void) printf("\nlocks: ");
1223 bprintf(stdout
, rtm
->rtm_rmx
.rmx_locks
, metricnames
);
1224 (void) printf(" inits: ");
1225 bprintf(stdout
, rtm
->rtm_inits
, metricnames
);
1226 (void) printf("\nsockaddrs: ");
1227 bprintf(stdout
, rtm
->rtm_addrs
,
1228 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
1229 (void) putchar('\n');
1230 cp
= ((char *)(rtm
+ 1));
1232 for (i
= 1; i
; i
<<= 1)
1233 if (i
& rtm
->rtm_addrs
) {
1234 sa
= (struct sockaddr
*)cp
;
1235 (void) printf(" %s", routename(sa
));
1238 (void) putchar('\n');
1239 (void) fflush(stdout
);
1254 if (b
& (1 << (i
-1))) {
1261 for (; (i
= *s
) > 32; s
++)
1268 (void) putc('>', fp
);
1276 register struct keytab
*kt
= keywords
;
1278 while (kt
->kt_cp
&& strcmp(kt
->kt_cp
, cp
))
1288 switch (su
->sa
.sa_family
) {
1290 (void) printf("%s: link %s; ",
1291 which
, link_ntoa(&su
->sdl
));
1294 (void) printf("%s: iso %s; ",
1295 which
, iso_ntoa(&su
->siso
.siso_addr
));
1298 (void) printf("%s: inet %s; ",
1299 which
, inet_ntoa(su
->s_in
.sin_addr
));
1302 (void) printf("%s: xns %s; ",
1303 which
, ns_ntoa(su
->sns
.sns_addr
));
1306 (void) fflush(stdout
);
1319 register char *addr
;
1320 register struct sockaddr
*sa
;
1322 register char *cp
= (char *)sa
;
1323 int size
= sa
->sa_len
;
1324 char *cplim
= cp
+ size
;
1325 register int byte
= 0, state
= VIRGIN
, new;
1329 if ((*addr
>= '0') && (*addr
<= '9')) {
1331 } else if ((*addr
>= 'a') && (*addr
<= 'f')) {
1332 new = *addr
- 'a' + 10;
1333 } else if ((*addr
>= 'A') && (*addr
<= 'F')) {
1334 new = *addr
- 'A' + 10;
1335 } else if (*addr
== 0)
1340 switch (state
/* | INPUT */) {
1341 case GOTTWO
| DIGIT
:
1342 *cp
++ = byte
; /*FALLTHROUGH*/
1343 case VIRGIN
| DIGIT
:
1344 state
= GOTONE
; byte
= new; continue;
1345 case GOTONE
| DIGIT
:
1346 state
= GOTTWO
; byte
= new + (byte
<< 4); continue;
1347 default: /* | DELIM */
1348 state
= VIRGIN
; *cp
++ = byte
; byte
= 0; continue;
1351 *cp
++ = byte
; /* FALLTHROUGH */
1356 } while (cp
< cplim
);
1357 sa
->sa_len
= cp
- (char *)sa
;
1371 if(opterr) { fprintf(stderr, "%s%s%lc\n", argv[0], s, c); }
1378 int GetOpt(int argc
, char **argv
, char *opts
)
1385 if(optind
>= argc
||
1386 argv
[optind
][0] != '-' || argv
[optind
][1] == '\0')
1388 else if(strcmp(argv
[optind
], "--") == 0) {
1392 optopt
= c
= argv
[optind
][sp
];
1393 if(c
== ':' || (cp
=index(opts
, c
)) == NULL
) {
1394 ERR(": illegal option -- ", c
);
1395 if(argv
[optind
][++sp
] == '\0') {
1402 if(argv
[optind
][sp
+1] != '\0')
1403 optarg
= &argv
[optind
++][sp
+1];
1404 else if(++optind
>= argc
) {
1405 ERR(": option requires an argument -- ", c
);
1409 optarg
= argv
[optind
++];
1412 if(argv
[optind
][++sp
] == '\0') {
1422 VOID
CleanUpExit(LONG error
)
1424 CloseLibrary(SocketBase
);