date and time created 84/05/16 15:19:24 by ralph
[unix-history] / usr / src / sbin / route / route.c
CommitLineData
4bec325f 1#ifndef lint
6edb1941 2static char sccsid[] = "@(#)route.c 4.9 (Berkeley) 84/05/11";
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];
6edb1941
MK
133 struct hostent *hp;
134 struct netent *np;
135 int lna, net, subnet;
63c817da
SL
136
137 net = inet_netof(in);
6edb1941 138 subnet = inet_subnetof(in);
63c817da
SL
139 lna = inet_lnaof(in);
140 if (lna == INADDR_ANY) {
6edb1941 141 np = getnetbyaddr(net, AF_INET);
63c817da
SL
142 if (np)
143 cp = np->n_name;
6edb1941
MK
144 else if (net == 0)
145 cp = "default";
146 } else if ((subnet != net) && ((lna & 0xff) == 0) &&
147 (np = getnetbyaddr(subnet, AF_INET))) {
148 struct in_addr subnaddr, inet_makeaddr();
63c817da 149
6edb1941
MK
150 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
151 if (bcmp(&in, &subnaddr, sizeof(in)) == 0)
152 cp = np->n_name;
153 } else {
154 hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET);
63c817da
SL
155 if (hp)
156 cp = hp->h_name;
157 }
158 if (cp)
159 strcpy(line, cp);
160 else {
161 u_char *ucp = (u_char *)&in;
162 if (lna == INADDR_ANY)
163 sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]);
164 else
165 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1],
166 ucp[2], ucp[3]);
167 }
168 return (line);
4bec325f
BJ
169}
170
171newroute(argc, argv)
172 int argc;
173 char *argv[];
174{
175 struct sockaddr_in *sin;
176 char *cmd;
6edb1941 177 int ishost;
4bec325f 178
183ef13b 179 cmd = argv[0];
6edb1941
MK
180 if (*cmd == 'a') {
181 if (argc != 4) {
182 printf("usage: %s destination gateway metric\n", cmd);
183 printf("(metric of 0 if gateway is this host)\n");
184 return;
185 }
186 } else {
187 if (argc != 3) {
188 printf("usage: %s destination gateway\n", cmd);
189 return;
190 }
191 }
192 ishost = getaddr(argv[1], &route.rt_dst);
193 (void) getaddr(argv[2], &route.rt_gateway);
4bec325f
BJ
194 sin = (struct sockaddr_in *)&route.rt_dst;
195 route.rt_flags = RTF_UP;
6edb1941 196 if (ishost)
4bec325f 197 route.rt_flags |= RTF_HOST;
6edb1941 198 if (atoi(argv[3]) > 0)
183ef13b 199 route.rt_flags |= RTF_GATEWAY;
63c817da
SL
200 printf("%s %s: gateway ", cmd, routename(sin->sin_addr));
201 sin = (struct sockaddr_in *)&route.rt_gateway;
202 printf("%s, flags %x\n", routename(sin->sin_addr), route.rt_flags);
4bec325f
BJ
203 if (ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, (caddr_t)&route))
204 error(cmd);
205}
206
207changeroute(argc, argv)
208 int argc;
209 char *argv[];
210{
211 printf("not supported\n");
212}
213
214error(cmd)
215 char *cmd;
216{
217 extern int errno;
218
219 if (errno == ESRCH)
220 fprintf(stderr, "not in table\n");
221 else if (errno == EBUSY)
222 fprintf(stderr, "entry in use\n");
223 else if (errno == ENOBUFS)
224 fprintf(stderr, "routing table overflow\n");
225 else
226 perror(cmd);
227}
228
6edb1941
MK
229/*
230 * Interpret an argument as a network address of some kind,
231 * returning 1 if a host address, 0 if a network address.
232 */
4bec325f
BJ
233getaddr(s, sin)
234 char *s;
235 struct sockaddr_in *sin;
236{
accbc2e3 237 struct hostent *hp;
379dcc38
SL
238 struct netent *np;
239 u_long val;
accbc2e3 240
89a108e6
SL
241 if (strcmp(s, "default") == 0) {
242 sin->sin_family = AF_INET;
243 sin->sin_addr = inet_makeaddr(0, INADDR_ANY);
6edb1941 244 return(0);
89a108e6 245 }
accbc2e3 246 hp = gethostbyname(s);
379dcc38
SL
247 if (hp) {
248 sin->sin_family = hp->h_addrtype;
249 bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
6edb1941 250 return(1);
4bec325f 251 }
379dcc38
SL
252 np = getnetbyname(s);
253 if (np) {
254 sin->sin_family = np->n_addrtype;
255 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
6edb1941 256 return(0);
379dcc38
SL
257 }
258 sin->sin_family = AF_INET;
259 val = inet_addr(s);
260 if (val != -1) {
261 sin->sin_addr.s_addr = val;
6edb1941 262 return(inet_lnaof(sin->sin_addr) != INADDR_ANY);
379dcc38
SL
263 }
264 val = inet_network(s);
265 if (val != -1) {
266 sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
6edb1941 267 return(0);
379dcc38
SL
268 }
269 fprintf(stderr, "%s: bad value\n", s);
270 exit(1);
183ef13b 271}
6edb1941
MK
272
273/*
274 * Return the possible subnetwork number from an internet address.
275 * If the address is of the form of a subnet address (most significant
276 * bit of the host part is set), believe the subnet exists.
277 * Otherwise, return the network number.
278 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
279 * INSIDE OF THE HOST PART. We can only believe this if we have other
280 * information (e.g., we can find a name for this number).
281 */
282inet_subnetof(in)
283 struct in_addr in;
284{
285 register u_long i = ntohl(in.s_addr);
286
287 if (IN_CLASSA(i)) {
288 if (IN_SUBNETA(i))
289 return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
290 else
291 return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
292 } else if (IN_CLASSB(i)) {
293 if (IN_SUBNETB(i))
294 return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
295 else
296 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
297 } else
298 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
299}