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