coverity appeasement
[minix.git] / commands / add_route / add_route.c
bloba45892cb8573c158a20116771ff1dbd888852e8d
1 /*
2 add_route.c
4 Created August 7, 1991 by Philip Homburg
5 */
7 #define _POSIX_C_SOURCE 2
9 #include <sys/types.h>
10 #include <sys/ioctl.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
18 #include <net/hton.h>
19 #include <net/netlib.h>
20 #include <net/gen/netdb.h>
21 #include <net/gen/in.h>
22 #include <net/gen/inet.h>
23 #include <net/gen/route.h>
24 #include <net/gen/socket.h>
25 #include <net/gen/ip_io.h>
27 static char *prog_name;
28 static enum { ADD, DEL } action;
30 static void usage(void);
31 static int name_to_ip(const char *name, ipaddr_t *addr);
32 static int parse_cidr(const char *cidr, ipaddr_t *addr, ipaddr_t *mask);
34 int main(int argc, char *argv[])
36 struct netent *netent;
37 ipaddr_t gateway, destination, netmask, defaultmask=0;
38 u8_t high_byte;
39 nwio_route_t route;
40 int ip_fd, itab;
41 int r;
42 int metric;
43 char *check;
44 char *ip_device;
45 char *netmask_str, *metric_str, *destination_str, *gateway_str;
46 int c;
47 char *d_arg, *g_arg, *m_arg, *n_arg, *I_arg;
48 int i_flag, o_flag, D_flag, v_flag;
49 int cidr;
51 prog_name= strrchr(argv[0], '/');
52 if (prog_name == NULL) prog_name= argv[0]; else prog_name++;
54 if (strcmp(prog_name, "add_route") == 0)
55 action= ADD;
56 else if (strcmp(prog_name, "del_route") == 0)
57 action= DEL;
58 else
60 fprintf(stderr, "Don't know what to do when named '%s'\n",
61 prog_name);
62 exit(1);
65 i_flag= 0;
66 o_flag= 0;
67 D_flag= 0;
68 v_flag= 0;
69 g_arg= NULL;
70 d_arg= NULL;
71 m_arg= NULL;
72 n_arg= NULL;
73 I_arg= NULL;
74 while ((c= getopt(argc, argv, "iovDg:d:m:n:I:?")) != -1)
76 switch(c)
78 case 'i':
79 if (i_flag)
80 usage();
81 i_flag= 1;
82 break;
83 case 'o':
84 if (o_flag)
85 usage();
86 o_flag= 1;
87 break;
88 case 'v':
89 if (v_flag)
90 usage();
91 v_flag= 1;
92 break;
93 case 'D':
94 if (D_flag)
95 usage();
96 D_flag= 1;
97 break;
98 case 'g':
99 if (g_arg)
100 usage();
101 g_arg= optarg;
102 break;
103 case 'd':
104 if (d_arg)
105 usage();
106 d_arg= optarg;
107 break;
108 case 'm':
109 if (m_arg)
110 usage();
111 m_arg= optarg;
112 break;
113 case 'n':
114 if (n_arg)
115 usage();
116 n_arg= optarg;
117 break;
118 case 'I':
119 if (I_arg)
120 usage();
121 I_arg= optarg;
122 break;
123 case '?':
124 usage();
125 default:
126 fprintf(stderr, "%s: getopt failed\n", prog_name);
127 exit(1);
130 if (optind != argc)
131 usage();
132 if (i_flag && o_flag)
133 usage();
134 itab= i_flag;
136 if (i_flag)
138 if (g_arg == NULL || d_arg == NULL || m_arg == NULL)
139 usage();
141 else
143 if (g_arg == NULL || (d_arg == NULL && n_arg != NULL))
145 usage();
149 gateway_str= g_arg;
150 destination_str= d_arg;
151 metric_str= m_arg;
152 netmask_str= n_arg;
153 ip_device= I_arg;
155 if (!name_to_ip(gateway_str, &gateway))
157 fprintf(stderr, "%s: unknown host '%s'\n", prog_name,
158 gateway_str);
159 exit(1);
162 destination= 0;
163 netmask= 0;
164 cidr= 0;
166 if (destination_str)
168 if (parse_cidr(destination_str, &destination, &netmask))
169 cidr= 1;
170 else if (inet_aton(destination_str, &destination))
172 else if ((netent= getnetbyname(destination_str)) != NULL)
173 destination= netent->n_net;
174 else if (!name_to_ip(destination_str, &destination))
176 fprintf(stderr, "%s: unknown network/host '%s'\n",
177 prog_name, destination_str);
178 exit(1);
180 high_byte= *(u8_t *)&destination;
181 if (!(high_byte & 0x80)) /* class A or 0 */
183 if (destination)
184 #ifdef __NBSD_LIBC
185 defaultmask= htonl(0xff000000);
186 #else
187 defaultmask= HTONL(0xff000000);
188 #endif
191 else if (!(high_byte & 0x40)) /* class B */
193 #ifdef __NBSD_LIBC
194 defaultmask= htonl(0xffff0000);
195 #else
196 defaultmask= HTONL(0xffff0000);
197 #endif
200 else if (!(high_byte & 0x20)) /* class C */
202 #ifdef __NBSD_LIBC
203 defaultmask= htonl(0xffffff00);
204 #else
205 defaultmask= HTONL(0xffffff00);
207 #endif
209 else /* class D is multicast ... */
211 fprintf(stderr, "%s: Warning: Martian address '%s'\n",
212 prog_name, inet_ntoa(destination));
213 #ifdef __NBSD_LIBC
214 defaultmask= htonl(0xffffffff);
215 #else
216 defaultmask= HTONL(0xffffffff);
217 #endif
219 if (destination & ~defaultmask)
221 /* host route */
222 #ifdef __NBSD_LIBC
223 defaultmask= htonl(0xffffffff);
224 #else
225 defaultmask= HTONL(0xffffffff);
226 #endif
228 if (!cidr)
229 netmask= defaultmask;
232 if (netmask_str)
234 if (cidr)
235 usage();
236 if (inet_aton(netmask_str, &netmask) == 0)
238 fprintf(stderr, "%s: illegal netmask'%s'\n", prog_name,
239 netmask_str);
240 exit(1);
244 if (metric_str)
246 metric= strtol(metric_str, &check, 0);
247 if (check[0] != '\0' || metric < 1)
249 fprintf(stderr, "%s: illegal metric %s\n",
250 prog_name, metric_str);
253 else
254 metric= 1;
256 if (!ip_device)
257 ip_device= getenv("IP_DEVICE");
258 if (!ip_device)
259 ip_device= IP_DEVICE;
261 ip_fd= open(ip_device, O_RDWR);
262 if (ip_fd == -1)
264 fprintf(stderr, "%s: unable to open('%s'): %s\n",
265 prog_name, ip_device, strerror(errno));
266 exit(1);
269 if (v_flag)
271 printf("%s %s route to %s ",
272 action == ADD ? "adding" : "deleting",
273 itab ? "input" : "output",
274 inet_ntoa(destination));
275 printf("with netmask %s ", inet_ntoa(netmask));
276 printf("using gateway %s", inet_ntoa(gateway));
277 if (itab && action == ADD)
278 printf(" at distance %d", metric);
279 printf("\n");
282 route.nwr_ent_no= 0;
283 route.nwr_dest= destination;
284 route.nwr_netmask= netmask;
285 route.nwr_gateway= gateway;
286 route.nwr_dist= action == ADD ? metric : 0;
287 route.nwr_flags= (action == DEL && D_flag) ? 0 : NWRF_STATIC;
288 route.nwr_pref= 0;
289 route.nwr_mtu= 0;
291 if (action == ADD)
292 r= ioctl(ip_fd, itab ? NWIOSIPIROUTE : NWIOSIPOROUTE, &route);
293 else
294 r= ioctl(ip_fd, itab ? NWIODIPIROUTE : NWIODIPOROUTE, &route);
295 if (r == -1)
297 fprintf(stderr, "%s: NWIO%cIP%cROUTE: %s\n",
298 prog_name,
299 action == ADD ? 'S' : 'D',
300 itab ? 'I' : 'O',
301 strerror(errno));
302 exit(1);
304 return(0);
307 static void usage(void)
309 fprintf(stderr,
310 "Usage: %s\n"
311 "\t[-o] %s-g gw [-d dst [-n netmask]] %s[-I ipdev] [-v]\n"
312 "\t-i %s-g gw -d dst [-n netmask] %s[-I ipdev] [-v]\n"
313 "Note: <dst> may be in CIDR notation\n",
314 prog_name,
315 action == DEL ? "[-D] " : "",
316 action == ADD ? "[-m metric] " : "",
317 action == DEL ? "[-D] " : "",
318 action == ADD ? "-m metric " : ""
320 exit(1);
323 static int name_to_ip(const char *name, ipaddr_t *addr)
325 /* Translate a name to an IP address. Try first with inet_aton(), then
326 * with gethostbyname(). (The latter can also recognize an IP address,
327 * but only decimals with at least one dot).)
329 struct hostent *hostent;
331 if (!inet_aton(name, addr)) {
332 if ((hostent= gethostbyname(name)) == NULL) return 0;
333 if (hostent->h_addrtype != AF_INET) return 0;
334 if (hostent->h_length != sizeof(*addr)) return 0;
335 memcpy(addr, hostent->h_addr, sizeof(*addr));
337 return 1;
340 static int parse_cidr(const char *cidr, ipaddr_t *addr, ipaddr_t *mask)
342 char *slash, *check;
343 ipaddr_t a;
344 int ok;
345 unsigned long len;
347 if ((slash= strchr(cidr, '/')) == NULL)
348 return 0;
350 *slash++= 0;
351 ok= 1;
353 if (!inet_aton(cidr, &a))
354 ok= 0;
356 len= strtoul(slash, &check, 10);
357 if (check == slash || *check != 0 || len > 32)
358 ok= 0;
360 *--slash= '/';
361 if (!ok)
362 return 0;
363 *addr= a;
364 *mask= htonl(len == 0 ? 0 : (0xFFFFFFFF << (32-len)) & 0xFFFFFFFF);
365 return 1;
369 * $PchId: add_route.c,v 1.6 2001/04/20 10:45:07 philip Exp $