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