BSD 4_2 release
[unix-history] / usr / src / etc / route.c
CommitLineData
4bec325f 1#ifndef lint
89a108e6 2static char sccsid[] = "@(#)route.c 4.8 (Berkeley) 83/08/21";
4bec325f
BJ
3#endif
4
4bec325f
BJ
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <sys/ioctl.h>
63c817da 8#include <sys/mbuf.h>
94a2d2a7 9
63c817da 10#define KERNEL
4bec325f 11#include <net/route.h>
94a2d2a7
SL
12#include <netinet/in.h>
13
14#include <stdio.h>
4bec325f
BJ
15#include <errno.h>
16#include <ctype.h>
accbc2e3 17#include <netdb.h>
4bec325f
BJ
18
19struct rtentry route;
20int options;
21int s;
22struct sockaddr_in sin = { AF_INET };
379dcc38 23struct in_addr inet_makeaddr();
4bec325f
BJ
24
25main(argc, argv)
26 int argc;
27 char *argv[];
28{
29
30 if (argc < 2)
63c817da 31 printf("usage: route [ -f ] [ cmd args ]\n"), exit(1);
5a635333 32 s = socket(AF_INET, SOCK_RAW, 0, 0);
4bec325f 33 if (s < 0) {
5a635333 34 perror("route: socket");
4bec325f
BJ
35 exit(1);
36 }
37 argc--, argv++;
63c817da
SL
38 if (strcmp(*argv, "-f") == 0) {
39 argc--, argv++;
40 flushroutes();
41 }
42 if (argc > 0) {
43 if (strcmp(*argv, "add") == 0)
44 newroute(argc, argv);
45 else if (strcmp(*argv, "delete") == 0)
46 newroute(argc, argv);
47 else if (strcmp(*argv, "change") == 0)
48 changeroute(argc-1, argv+1);
49 else
50 printf("%s: huh?\n", *argv);
51 }
52}
53
54/*
55 * Purge all entries in the routing tables not
56 * associated with network interfaces.
57 */
58#include <nlist.h>
59
60struct nlist nl[] = {
61#define N_RTHOST 0
62 { "_rthost" },
63#define N_RTNET 1
64 { "_rtnet" },
65 "",
66};
67
68flushroutes()
69{
70 struct mbuf mb;
71 register struct rtentry *rt;
72 register struct mbuf *m;
73 struct mbuf *routehash[RTHASHSIZ];
74 int i, doinghost = 1, kmem;
75 char *routename();
76
77 nlist("/vmunix", nl);
78 if (nl[N_RTHOST].n_value == 0) {
79 printf("route: \"rthost\", symbol not in namelist\n");
80 exit(1);
81 }
82 if (nl[N_RTNET].n_value == 0) {
83 printf("route: \"rtnet\", symbol not in namelist\n");
84 exit(1);
85 }
86 kmem = open("/dev/kmem", 0);
87 if (kmem < 0) {
88 perror("route: /dev/kmem");
89 exit(1);
90 }
91 lseek(kmem, nl[N_RTHOST].n_value, 0);
92 read(kmem, routehash, sizeof (routehash));
93 printf("Flushing routing tables:\n");
94again:
95 for (i = 0; i < RTHASHSIZ; i++) {
96 if (routehash[i] == 0)
97 continue;
98 m = routehash[i];
99 while (m) {
100 lseek(kmem, m, 0);
101 read(kmem, &mb, sizeof (mb));
102 rt = mtod(&mb, struct rtentry *);
103 if (rt->rt_flags & RTF_GATEWAY) {
104 struct sockaddr_in *sin;
105
106 sin = (struct sockaddr_in *)&rt->rt_dst;
107 printf("%-15.15s ", routename(sin->sin_addr));
108 sin = (struct sockaddr_in *)&rt->rt_gateway;
109 printf("%-15.15s ", routename(sin->sin_addr));
110 if (ioctl(s, SIOCDELRT, (caddr_t)rt) < 0)
111 error("delete");
112 else
113 printf("done\n");
114 }
115 m = mb.m_next;
116 }
117 }
118 if (doinghost) {
119 lseek(kmem, nl[N_RTNET].n_value, 0);
120 read(kmem, routehash, sizeof (routehash));
121 doinghost = 0;
122 goto again;
123 }
124 close(kmem);
125}
126
127char *
128routename(in)
129 struct in_addr in;
130{
131 char *cp = 0;
132 static char line[50];
133 int lna, net;
134
135 net = inet_netof(in);
136 lna = inet_lnaof(in);
137 if (lna == INADDR_ANY) {
138 struct netent *np = getnetbyaddr(net, AF_INET);
139
140 if (np)
141 cp = np->n_name;
142 } else {
143 struct hostent *hp;
144
145 hp = gethostbyaddr(&in, sizeof (struct in_addr),
146 AF_INET);
147 if (hp)
148 cp = hp->h_name;
149 }
150 if (cp)
151 strcpy(line, cp);
152 else {
153 u_char *ucp = (u_char *)&in;
154 if (lna == INADDR_ANY)
155 sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]);
156 else
157 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1],
158 ucp[2], ucp[3]);
159 }
160 return (line);
4bec325f
BJ
161}
162
163newroute(argc, argv)
164 int argc;
165 char *argv[];
166{
167 struct sockaddr_in *sin;
168 char *cmd;
169
183ef13b
SL
170 if (argc < 3 || argc > 4) {
171 printf("usage: %s destination gateway [ metric ]\n", argv[0]);
4bec325f
BJ
172 return;
173 }
183ef13b
SL
174 cmd = argv[0];
175 getaddr(argv[1], &route.rt_dst);
176 getaddr(argv[2], &route.rt_gateway);
4bec325f
BJ
177 sin = (struct sockaddr_in *)&route.rt_dst;
178 route.rt_flags = RTF_UP;
accbc2e3 179 if (inet_lnaof(sin->sin_addr) != 0)
4bec325f 180 route.rt_flags |= RTF_HOST;
183ef13b
SL
181 if (argc > 3 && atoi(argv[3]) > 0)
182 route.rt_flags |= RTF_GATEWAY;
63c817da
SL
183 printf("%s %s: gateway ", cmd, routename(sin->sin_addr));
184 sin = (struct sockaddr_in *)&route.rt_gateway;
185 printf("%s, flags %x\n", routename(sin->sin_addr), route.rt_flags);
4bec325f
BJ
186 if (ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, (caddr_t)&route))
187 error(cmd);
188}
189
190changeroute(argc, argv)
191 int argc;
192 char *argv[];
193{
194 printf("not supported\n");
195}
196
197error(cmd)
198 char *cmd;
199{
200 extern int errno;
201
202 if (errno == ESRCH)
203 fprintf(stderr, "not in table\n");
204 else if (errno == EBUSY)
205 fprintf(stderr, "entry in use\n");
206 else if (errno == ENOBUFS)
207 fprintf(stderr, "routing table overflow\n");
208 else
209 perror(cmd);
210}
211
212getaddr(s, sin)
213 char *s;
214 struct sockaddr_in *sin;
215{
accbc2e3 216 struct hostent *hp;
379dcc38
SL
217 struct netent *np;
218 u_long val;
accbc2e3 219
89a108e6
SL
220 if (strcmp(s, "default") == 0) {
221 sin->sin_family = AF_INET;
222 sin->sin_addr = inet_makeaddr(0, INADDR_ANY);
223 return;
224 }
accbc2e3 225 hp = gethostbyname(s);
379dcc38
SL
226 if (hp) {
227 sin->sin_family = hp->h_addrtype;
228 bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
4bec325f 229 return;
4bec325f 230 }
379dcc38
SL
231 np = getnetbyname(s);
232 if (np) {
233 sin->sin_family = np->n_addrtype;
234 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
235 return;
236 }
237 sin->sin_family = AF_INET;
238 val = inet_addr(s);
239 if (val != -1) {
240 sin->sin_addr.s_addr = val;
241 return;
242 }
243 val = inet_network(s);
244 if (val != -1) {
245 sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
246 return;
247 }
248 fprintf(stderr, "%s: bad value\n", s);
249 exit(1);
183ef13b 250}