4.3BSD beta release manual page
[unix-history] / usr / src / sbin / route / route.c
CommitLineData
4bec325f 1#ifndef lint
f508555e 2static char sccsid[] = "@(#)route.c 4.13 (Berkeley) 84/10/31";
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;
19int options;
20int s;
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)
63c817da 30 printf("usage: route [ -f ] [ cmd args ]\n"), exit(1);
f508555e 31 s = socket(AF_INET, SOCK_RAW, 0);
4bec325f 32 if (s < 0) {
5a635333 33 perror("route: socket");
4bec325f
BJ
34 exit(1);
35 }
36 argc--, argv++;
63c817da
SL
37 if (strcmp(*argv, "-f") == 0) {
38 argc--, argv++;
39 flushroutes();
40 }
41 if (argc > 0) {
42 if (strcmp(*argv, "add") == 0)
43 newroute(argc, argv);
44 else if (strcmp(*argv, "delete") == 0)
45 newroute(argc, argv);
46 else if (strcmp(*argv, "change") == 0)
47 changeroute(argc-1, argv+1);
48 else
49 printf("%s: huh?\n", *argv);
50 }
51}
52
53/*
54 * Purge all entries in the routing tables not
55 * associated with network interfaces.
56 */
57#include <nlist.h>
58
59struct nlist nl[] = {
60#define N_RTHOST 0
61 { "_rthost" },
62#define N_RTNET 1
63 { "_rtnet" },
f508555e
MK
64#define N_RTHASHSIZE 2
65 { "_rthashsize" },
63c817da
SL
66 "",
67};
68
69flushroutes()
70{
71 struct mbuf mb;
72 register struct rtentry *rt;
73 register struct mbuf *m;
f508555e
MK
74 struct mbuf **routehash;
75 int rthashsize, i, doinghost = 1, kmem;
63c817da
SL
76 char *routename();
77
78 nlist("/vmunix", nl);
79 if (nl[N_RTHOST].n_value == 0) {
80 printf("route: \"rthost\", symbol not in namelist\n");
81 exit(1);
82 }
83 if (nl[N_RTNET].n_value == 0) {
84 printf("route: \"rtnet\", symbol not in namelist\n");
85 exit(1);
86 }
f508555e
MK
87 if (nl[N_RTHASHSIZE].n_value == 0) {
88 printf("route: \"rthashsize\", symbol not in namelist\n");
89 exit(1);
90 }
63c817da
SL
91 kmem = open("/dev/kmem", 0);
92 if (kmem < 0) {
93 perror("route: /dev/kmem");
94 exit(1);
95 }
f508555e
MK
96 lseek(kmem, nl[N_RTHASHSIZE].n_value, 0);
97 read(kmem, &rthashsize, sizeof (rthashsize));
98 routehash = (struct mbuf **)malloc(rthashsize*sizeof (struct mbuf *));
99
63c817da 100 lseek(kmem, nl[N_RTHOST].n_value, 0);
f508555e 101 read(kmem, routehash, rthashsize*sizeof (struct mbuf *));
63c817da
SL
102 printf("Flushing routing tables:\n");
103again:
f508555e 104 for (i = 0; i < rthashsize; i++) {
63c817da
SL
105 if (routehash[i] == 0)
106 continue;
107 m = routehash[i];
108 while (m) {
109 lseek(kmem, m, 0);
110 read(kmem, &mb, sizeof (mb));
111 rt = mtod(&mb, struct rtentry *);
112 if (rt->rt_flags & RTF_GATEWAY) {
113 struct sockaddr_in *sin;
114
115 sin = (struct sockaddr_in *)&rt->rt_dst;
116 printf("%-15.15s ", routename(sin->sin_addr));
117 sin = (struct sockaddr_in *)&rt->rt_gateway;
118 printf("%-15.15s ", routename(sin->sin_addr));
119 if (ioctl(s, SIOCDELRT, (caddr_t)rt) < 0)
120 error("delete");
121 else
122 printf("done\n");
123 }
124 m = mb.m_next;
125 }
126 }
127 if (doinghost) {
128 lseek(kmem, nl[N_RTNET].n_value, 0);
f508555e 129 read(kmem, routehash, rthashsize*sizeof (struct mbuf *));
63c817da
SL
130 doinghost = 0;
131 goto again;
132 }
133 close(kmem);
f508555e 134 free(routehash);
63c817da
SL
135}
136
137char *
138routename(in)
139 struct in_addr in;
140{
141 char *cp = 0;
142 static char line[50];
6edb1941
MK
143 struct hostent *hp;
144 struct netent *np;
145 int lna, net, subnet;
63c817da
SL
146
147 net = inet_netof(in);
6edb1941 148 subnet = inet_subnetof(in);
63c817da
SL
149 lna = inet_lnaof(in);
150 if (lna == INADDR_ANY) {
6edb1941 151 np = getnetbyaddr(net, AF_INET);
63c817da
SL
152 if (np)
153 cp = np->n_name;
6edb1941
MK
154 else if (net == 0)
155 cp = "default";
156 } else if ((subnet != net) && ((lna & 0xff) == 0) &&
157 (np = getnetbyaddr(subnet, AF_INET))) {
158 struct in_addr subnaddr, inet_makeaddr();
63c817da 159
6edb1941
MK
160 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
161 if (bcmp(&in, &subnaddr, sizeof(in)) == 0)
162 cp = np->n_name;
fd1f860b
MK
163 else
164 goto host;
6edb1941 165 } else {
fd1f860b 166host:
6edb1941 167 hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET);
63c817da
SL
168 if (hp)
169 cp = hp->h_name;
170 }
171 if (cp)
172 strcpy(line, cp);
173 else {
174 u_char *ucp = (u_char *)&in;
175 if (lna == INADDR_ANY)
176 sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]);
177 else
178 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1],
179 ucp[2], ucp[3]);
180 }
181 return (line);
4bec325f
BJ
182}
183
184newroute(argc, argv)
185 int argc;
186 char *argv[];
187{
188 struct sockaddr_in *sin;
189 char *cmd;
c4693c18 190 int ishost, metric = 0;
4bec325f 191
183ef13b 192 cmd = argv[0];
6edb1941
MK
193 if (*cmd == 'a') {
194 if (argc != 4) {
195 printf("usage: %s destination gateway metric\n", cmd);
196 printf("(metric of 0 if gateway is this host)\n");
197 return;
198 }
c4693c18 199 metric = atoi(argv[3]);
6edb1941
MK
200 } else {
201 if (argc != 3) {
202 printf("usage: %s destination gateway\n", cmd);
203 return;
204 }
205 }
206 ishost = getaddr(argv[1], &route.rt_dst);
207 (void) getaddr(argv[2], &route.rt_gateway);
4bec325f
BJ
208 sin = (struct sockaddr_in *)&route.rt_dst;
209 route.rt_flags = RTF_UP;
6edb1941 210 if (ishost)
4bec325f 211 route.rt_flags |= RTF_HOST;
c4693c18 212 if (metric > 0)
183ef13b 213 route.rt_flags |= RTF_GATEWAY;
63c817da
SL
214 printf("%s %s: gateway ", cmd, routename(sin->sin_addr));
215 sin = (struct sockaddr_in *)&route.rt_gateway;
216 printf("%s, flags %x\n", routename(sin->sin_addr), route.rt_flags);
4bec325f
BJ
217 if (ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, (caddr_t)&route))
218 error(cmd);
219}
220
221changeroute(argc, argv)
222 int argc;
223 char *argv[];
224{
225 printf("not supported\n");
226}
227
228error(cmd)
229 char *cmd;
230{
231 extern int errno;
232
233 if (errno == ESRCH)
234 fprintf(stderr, "not in table\n");
235 else if (errno == EBUSY)
236 fprintf(stderr, "entry in use\n");
237 else if (errno == ENOBUFS)
238 fprintf(stderr, "routing table overflow\n");
239 else
240 perror(cmd);
241}
242
6edb1941
MK
243/*
244 * Interpret an argument as a network address of some kind,
245 * returning 1 if a host address, 0 if a network address.
246 */
4bec325f
BJ
247getaddr(s, sin)
248 char *s;
249 struct sockaddr_in *sin;
250{
accbc2e3 251 struct hostent *hp;
379dcc38
SL
252 struct netent *np;
253 u_long val;
accbc2e3 254
89a108e6
SL
255 if (strcmp(s, "default") == 0) {
256 sin->sin_family = AF_INET;
257 sin->sin_addr = inet_makeaddr(0, INADDR_ANY);
6edb1941 258 return(0);
89a108e6 259 }
379dcc38
SL
260 np = getnetbyname(s);
261 if (np) {
262 sin->sin_family = np->n_addrtype;
263 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
6edb1941 264 return(0);
379dcc38 265 }
78160c55
MK
266 hp = gethostbyname(s);
267 if (hp) {
268 sin->sin_family = hp->h_addrtype;
269 bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
270 return(1);
271 }
379dcc38
SL
272 sin->sin_family = AF_INET;
273 val = inet_addr(s);
274 if (val != -1) {
275 sin->sin_addr.s_addr = val;
6edb1941 276 return(inet_lnaof(sin->sin_addr) != INADDR_ANY);
379dcc38
SL
277 }
278 val = inet_network(s);
279 if (val != -1) {
280 sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
6edb1941 281 return(0);
379dcc38
SL
282 }
283 fprintf(stderr, "%s: bad value\n", s);
284 exit(1);
183ef13b 285}
6edb1941
MK
286
287/*
288 * Return the possible subnetwork number from an internet address.
289 * If the address is of the form of a subnet address (most significant
290 * bit of the host part is set), believe the subnet exists.
291 * Otherwise, return the network number.
292 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
293 * INSIDE OF THE HOST PART. We can only believe this if we have other
294 * information (e.g., we can find a name for this number).
295 */
296inet_subnetof(in)
297 struct in_addr in;
298{
299 register u_long i = ntohl(in.s_addr);
300
301 if (IN_CLASSA(i)) {
302 if (IN_SUBNETA(i))
303 return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
304 else
305 return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
306 } else if (IN_CLASSB(i)) {
307 if (IN_SUBNETB(i))
308 return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
309 else
310 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
311 } else
312 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
313}