3 * Similar to the standard Unix ifconfig, but with only the necessary
4 * parts for AF_INET, and without any printing of if info (for now).
6 * Bjorn Wesen, Axis Communications AB
9 * Authors of the original ifconfig was:
10 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software
15 * Foundation; either version 2 of the License, or (at
16 * your option) any later version.
18 * $Id: ifconfig.c,v 1.1 2001/02/14 08:11:27 andersen Exp $
23 #include <sys/types.h>
27 #include <string.h> // strcmp and friends
28 #include <ctype.h> // isdigit and friends
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
34 #include <net/if_arp.h>
35 #include <linux/if_ether.h>
37 static int sockfd; /* socket fd we use to manipulate stuff with */
39 /* print usage and exit */
43 /* Set a certain interface flag. */
45 set_flag(char *ifname, short flag)
49 strcpy(ifr.ifr_name, ifname);
50 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
51 perror("SIOCGIFFLAGS");
54 strcpy(ifr.ifr_name, ifname);
55 ifr.ifr_flags |= flag;
56 if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
57 perror("SIOCSIFFLAGS");
64 /* Clear a certain interface flag. */
66 clr_flag(char *ifname, short flag)
70 strcpy(ifr.ifr_name, ifname);
71 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
72 perror("SIOCGIFFLAGS");
75 strcpy(ifr.ifr_name, ifname);
76 ifr.ifr_flags &= ~flag;
77 if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
78 perror("SIOCSIFFLAGS");
84 /* resolve XXX.YYY.ZZZ.QQQ -> binary */
87 INET_resolve(char *name, struct sockaddr_in *sin)
89 sin->sin_family = AF_INET;
92 /* Default is special, meaning 0.0.0.0. */
93 if (!strcmp(name, "default")) {
94 sin->sin_addr.s_addr = INADDR_ANY;
97 /* Look to see if it's a dotted quad. */
98 if (inet_aton(name, &sin->sin_addr)) {
105 /* Input an Ethernet address and convert to binary. */
107 in_ether(char *bufp, struct sockaddr *sap)
114 sap->sa_family = ARPHRD_ETHER;
119 while ((*bufp != '\0') && (i < ETH_ALEN)) {
124 else if (c >= 'a' && c <= 'f')
126 else if (c >= 'A' && c <= 'F')
131 _("in_ether(%s): invalid ether address!\n"),
141 else if (c >= 'a' && c <= 'f')
143 else if (c >= 'A' && c <= 'F')
145 else if (c == ':' || c == 0)
150 _("in_ether(%s): invalid ether address!\n"),
158 *ptr++ = (unsigned char) (val & 0377);
161 /* We might get a semicolon here - not required. */
175 int ifconfig_main(int argc, char **argv)
178 struct sockaddr_in sa;
182 int r, didnetmask = 0;
186 usage(ifconfig_usage);
189 /* Create a channel to the NET kernel. */
190 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
202 /* get interface name */
204 safe_strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
206 /* Process the remaining arguments. */
207 while (*spp != (char *) NULL) {
208 if (!strcmp(*spp, "arp")) {
209 goterr |= clr_flag(ifr.ifr_name, IFF_NOARP);
213 if (!strcmp(*spp, "-arp")) {
214 goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
219 if (!strcmp(*spp, "trailers")) {
220 goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
224 if (!strcmp(*spp, "-trailers")) {
225 goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
229 if (!strcmp(*spp, "promisc")) {
230 goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
234 if (!strcmp(*spp, "-promisc")) {
235 goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
239 if (!strcmp(*spp, "multicast")) {
240 goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
244 if (!strcmp(*spp, "-multicast")) {
245 goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
249 if (!strcmp(*spp, "allmulti")) {
250 goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
254 if (!strcmp(*spp, "-allmulti")) {
255 goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
259 if (!strcmp(*spp, "up")) {
260 goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
264 if (!strcmp(*spp, "down")) {
265 goterr |= clr_flag(ifr.ifr_name, IFF_UP);
270 if (!strcmp(*spp, "metric")) {
272 usage(ifconfig_usage);
273 ifr.ifr_metric = atoi(*spp);
274 if (ioctl(sockfd, SIOCSIFMETRIC, &ifr) < 0) {
275 fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
281 if (!strcmp(*spp, "mtu")) {
283 usage(ifconfig_usage);
284 ifr.ifr_mtu = atoi(*spp);
285 if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
286 fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
292 #ifdef SIOCSKEEPALIVE
293 if (!strcmp(*spp, "keepalive")) {
295 usage(ifconfig_usage);
296 ifr.ifr_data = (caddr_t) atoi(*spp);
297 if (ioctl(sockfd, SIOCSKEEPALIVE, &ifr) < 0) {
298 fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno));
307 if (!strcmp(*spp, "outfill")) {
309 usage(ifconfig_usage);
310 ifr.ifr_data = (caddr_t) atoi(*spp);
311 if (ioctl(sockfd, SIOCSOUTFILL, &ifr) < 0) {
312 fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno));
320 if (!strcmp(*spp, "-broadcast")) {
321 goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST);
325 if (!strcmp(*spp, "broadcast")) {
326 if (*++spp != NULL) {
327 safe_strncpy(host, *spp, (sizeof host));
328 if (INET_resolve(host, &sa) < 0) {
333 memcpy((char *) &ifr.ifr_broadaddr,
335 sizeof(struct sockaddr));
336 if (ioctl(sockfd, SIOCSIFBRDADDR, &ifr) < 0) {
337 perror("SIOCSIFBRDADDR");
342 goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
345 if (!strcmp(*spp, "dstaddr")) {
347 usage(ifconfig_usage);
348 safe_strncpy(host, *spp, (sizeof host));
349 if (INET_resolve(host, &sa) < 0) {
354 memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
355 sizeof(struct sockaddr));
356 if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
357 fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
364 if (!strcmp(*spp, "netmask")) {
365 if (*++spp == NULL || didnetmask)
366 usage(ifconfig_usage);
367 safe_strncpy(host, *spp, (sizeof host));
368 if (INET_resolve(host, &sa) < 0) {
374 memcpy((char *) &ifr.ifr_netmask, (char *) &sa,
375 sizeof(struct sockaddr));
376 if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
377 perror("SIOCSIFNETMASK");
384 if (!strcmp(*spp, "-pointopoint")) {
385 goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
389 if (!strcmp(*spp, "pointopoint")) {
390 if (*(spp + 1) != NULL) {
392 safe_strncpy(host, *spp, (sizeof host));
393 if (INET_resolve(host, &sa)) {
398 memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
399 sizeof(struct sockaddr));
400 if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
401 perror("SIOCSIFDSTADDR");
405 goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT);
410 if (!strcmp(*spp, "hw")) {
411 if (*++spp == NULL || strcmp("ether", *spp)) {
412 usage(ifconfig_usage);
415 if (*++spp == NULL) {
416 /* silently ignore it if no address */
420 safe_strncpy(host, *spp, (sizeof host));
421 if (in_ether(host, &sa2) < 0) {
422 fprintf(stderr, "invalid hw-addr %s\n", host);
427 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa2,
428 sizeof(struct sockaddr));
429 if (ioctl(sockfd, SIOCSIFHWADDR, &ifr) < 0) {
430 perror("SIOCSIFHWADDR");
437 /* If the next argument is a valid hostname, assume OK. */
438 safe_strncpy(host, *spp, (sizeof host));
440 if (INET_resolve(host, &sa) < 0) {
441 usage(ifconfig_usage);
443 memcpy((char *) &ifr.ifr_addr,
444 (char *) &sa, sizeof(struct sockaddr));
446 r = ioctl(sockfd, SIOCSIFADDR, &ifr);
449 perror("SIOCSIFADDR");
454 * Don't do the set_flag() if the address is an alias with a - at the
455 * end, since it's deleted already! - Roman
457 * Should really use regex.h here, not sure though how well it'll go
458 * with the cross-platform support etc.
462 short int found_colon = 0;
463 for (ptr = ifr.ifr_name; *ptr; ptr++ )
464 if (*ptr == ':') found_colon++;
466 if (!(found_colon && *(ptr - 1) == '-'))
467 goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
472 } /* end of while-loop */