tools/llvm: Do not build with symbols
[minix3.git] / minix / commands / add_route / add_route.c
blob34f5fdc3e10ff872e6afb25d70fc053e2c3b7b35
1 /*
2 add_route.c
4 Created August 7, 1991 by Philip Homburg
5 */
7 #include <sys/types.h>
8 #include <sys/ioctl.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
16 #include <net/hton.h>
17 #include <net/netlib.h>
18 #include <netdb.h>
19 #include <net/gen/in.h>
20 #include <net/gen/inet.h>
21 #include <net/gen/route.h>
22 #include <net/gen/socket.h>
23 #include <net/gen/ip_io.h>
25 static char *prog_name;
26 static enum { ADD, DEL } action;
28 static void usage(void);
29 static int name_to_ip(const char *name, ipaddr_t *addr);
30 static int parse_cidr(const char *cidr, ipaddr_t *addr, ipaddr_t *mask);
32 int main(int argc, char *argv[])
34 struct netent *netent;
35 ipaddr_t gateway, destination, netmask, defaultmask=0;
36 u8_t high_byte;
37 nwio_route_t route;
38 int ip_fd, itab;
39 int r;
40 int metric;
41 char *check;
42 char *ip_device;
43 char *netmask_str, *metric_str, *destination_str, *gateway_str;
44 int c;
45 char *d_arg, *g_arg, *m_arg, *n_arg, *I_arg;
46 int i_flag, o_flag, D_flag, v_flag;
47 int cidr;
49 prog_name= strrchr(argv[0], '/');
50 if (prog_name == NULL) prog_name= argv[0]; else prog_name++;
52 if (strcmp(prog_name, "add_route") == 0)
53 action= ADD;
54 else if (strcmp(prog_name, "del_route") == 0)
55 action= DEL;
56 else
58 fprintf(stderr, "Don't know what to do when named '%s'\n",
59 prog_name);
60 exit(1);
63 i_flag= 0;
64 o_flag= 0;
65 D_flag= 0;
66 v_flag= 0;
67 g_arg= NULL;
68 d_arg= NULL;
69 m_arg= NULL;
70 n_arg= NULL;
71 I_arg= NULL;
72 while ((c= getopt(argc, argv, "iovDg:d:m:n:I:?")) != -1)
74 switch(c)
76 case 'i':
77 if (i_flag)
78 usage();
79 i_flag= 1;
80 break;
81 case 'o':
82 if (o_flag)
83 usage();
84 o_flag= 1;
85 break;
86 case 'v':
87 if (v_flag)
88 usage();
89 v_flag= 1;
90 break;
91 case 'D':
92 if (D_flag)
93 usage();
94 D_flag= 1;
95 break;
96 case 'g':
97 if (g_arg)
98 usage();
99 g_arg= optarg;
100 break;
101 case 'd':
102 if (d_arg)
103 usage();
104 d_arg= optarg;
105 break;
106 case 'm':
107 if (m_arg)
108 usage();
109 m_arg= optarg;
110 break;
111 case 'n':
112 if (n_arg)
113 usage();
114 n_arg= optarg;
115 break;
116 case 'I':
117 if (I_arg)
118 usage();
119 I_arg= optarg;
120 break;
121 case '?':
122 usage();
123 default:
124 fprintf(stderr, "%s: getopt failed\n", prog_name);
125 exit(1);
128 if (optind != argc)
129 usage();
130 if (i_flag && o_flag)
131 usage();
132 itab= i_flag;
134 if (i_flag)
136 if (g_arg == NULL || d_arg == NULL || m_arg == NULL)
137 usage();
139 else
141 if (g_arg == NULL || (d_arg == NULL && n_arg != NULL))
143 usage();
147 gateway_str= g_arg;
148 destination_str= d_arg;
149 metric_str= m_arg;
150 netmask_str= n_arg;
151 ip_device= I_arg;
153 if (!name_to_ip(gateway_str, &gateway))
155 fprintf(stderr, "%s: unknown host '%s'\n", prog_name,
156 gateway_str);
157 exit(1);
160 destination= 0;
161 netmask= 0;
162 cidr= 0;
164 if (destination_str)
166 if (parse_cidr(destination_str, &destination, &netmask))
167 cidr= 1;
168 else if (inet_aton(destination_str, &destination))
170 else if ((netent= getnetbyname(destination_str)) != NULL)
171 destination= netent->n_net;
172 else if (!name_to_ip(destination_str, &destination))
174 fprintf(stderr, "%s: unknown network/host '%s'\n",
175 prog_name, destination_str);
176 exit(1);
178 high_byte= *(u8_t *)&destination;
179 if (!(high_byte & 0x80)) /* class A or 0 */
181 if (destination)
182 defaultmask= htonl(0xff000000);
185 else if (!(high_byte & 0x40)) /* class B */
187 defaultmask= htonl(0xffff0000);
190 else if (!(high_byte & 0x20)) /* class C */
192 defaultmask= htonl(0xffffff00);
194 else /* class D is multicast ... */
196 fprintf(stderr, "%s: Warning: Martian address '%s'\n",
197 prog_name, inet_ntoa(destination));
198 defaultmask= htonl(0xffffffff);
200 if (destination & ~defaultmask)
202 /* host route */
203 defaultmask= htonl(0xffffffff);
205 if (!cidr)
206 netmask= defaultmask;
209 if (netmask_str)
211 if (cidr)
212 usage();
213 if (inet_aton(netmask_str, &netmask) == 0)
215 fprintf(stderr, "%s: illegal netmask'%s'\n", prog_name,
216 netmask_str);
217 exit(1);
221 if (metric_str)
223 metric= strtol(metric_str, &check, 0);
224 if (check[0] != '\0' || metric < 1)
226 fprintf(stderr, "%s: illegal metric %s\n",
227 prog_name, metric_str);
230 else
231 metric= 1;
233 if (!ip_device)
234 ip_device= getenv("IP_DEVICE");
235 if (!ip_device)
236 ip_device= IP_DEVICE;
238 ip_fd= open(ip_device, O_RDWR);
239 if (ip_fd == -1)
241 fprintf(stderr, "%s: unable to open('%s'): %s\n",
242 prog_name, ip_device, strerror(errno));
243 exit(1);
246 if (v_flag)
248 printf("%s %s route to %s ",
249 action == ADD ? "adding" : "deleting",
250 itab ? "input" : "output",
251 inet_ntoa(destination));
252 printf("with netmask %s ", inet_ntoa(netmask));
253 printf("using gateway %s", inet_ntoa(gateway));
254 if (itab && action == ADD)
255 printf(" at distance %d", metric);
256 printf("\n");
259 route.nwr_ent_no= 0;
260 route.nwr_dest= destination;
261 route.nwr_netmask= netmask;
262 route.nwr_gateway= gateway;
263 route.nwr_dist= action == ADD ? metric : 0;
264 route.nwr_flags= (action == DEL && D_flag) ? 0 : NWRF_STATIC;
265 route.nwr_pref= 0;
266 route.nwr_mtu= 0;
268 if (action == ADD)
269 r= ioctl(ip_fd, itab ? NWIOSIPIROUTE : NWIOSIPOROUTE, &route);
270 else
271 r= ioctl(ip_fd, itab ? NWIODIPIROUTE : NWIODIPOROUTE, &route);
272 if (r == -1)
274 fprintf(stderr, "%s: NWIO%cIP%cROUTE: %s\n",
275 prog_name,
276 action == ADD ? 'S' : 'D',
277 itab ? 'I' : 'O',
278 strerror(errno));
279 exit(1);
281 return(0);
284 static void usage(void)
286 fprintf(stderr,
287 "Usage: %s\n"
288 "\t[-o] %s-g gw [-d dst [-n netmask]] %s[-I ipdev] [-v]\n"
289 "\t-i %s-g gw -d dst [-n netmask] %s[-I ipdev] [-v]\n"
290 "Note: <dst> may be in CIDR notation\n",
291 prog_name,
292 action == DEL ? "[-D] " : "",
293 action == ADD ? "[-m metric] " : "",
294 action == DEL ? "[-D] " : "",
295 action == ADD ? "-m metric " : ""
297 exit(1);
300 static int name_to_ip(const char *name, ipaddr_t *addr)
302 /* Translate a name to an IP address. Try first with inet_aton(), then
303 * with gethostbyname(). (The latter can also recognize an IP address,
304 * but only decimals with at least one dot).)
306 struct hostent *hostent;
308 if (!inet_aton(name, addr)) {
309 if ((hostent= gethostbyname(name)) == NULL) return 0;
310 if (hostent->h_addrtype != AF_INET) return 0;
311 if (hostent->h_length != sizeof(*addr)) return 0;
312 memcpy(addr, hostent->h_addr, sizeof(*addr));
314 return 1;
317 static int parse_cidr(const char *cidr, ipaddr_t *addr, ipaddr_t *mask)
319 char *slash, *check;
320 ipaddr_t a;
321 int ok;
322 unsigned long len;
324 if ((slash= strchr(cidr, '/')) == NULL)
325 return 0;
327 *slash++= 0;
328 ok= 1;
330 if (!inet_aton(cidr, &a))
331 ok= 0;
333 len= strtoul(slash, &check, 10);
334 if (check == slash || *check != 0 || len > 32)
335 ok= 0;
337 *--slash= '/';
338 if (!ok)
339 return 0;
340 *addr= a;
341 *mask= htonl(len == 0 ? 0 : (0xFFFFFFFF << (32-len)) & 0xFFFFFFFF);
342 return 1;
346 * $PchId: add_route.c,v 1.6 2001/04/20 10:45:07 philip Exp $