/* Clear a certain interface flag. */ static int clr_flag(char *ifname, short flag) { struct ifreq ifr; int fd; if (strchr(ifname, ':')) { /* This is a v4 alias interface. Downing it via a socket for another AF may have bad consequences. */ fd = get_socket_for_af(AF_INET); if (fd < 0) { fprintf(stderr, _("No support for INET on this system.\n")); return -1; } } else fd = skfd; safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, _("%s: ERROR while getting interface flags: %s\n"), ifname, strerror(errno)); return -1; } safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_flags &= ~flag; if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { perror("SIOCSIFFLAGS"); return -1; } return (0); }
int main(int argc, char **argv) { struct sockaddr sa; char host[128]; struct aftype *ap; struct hwtype *hw; struct ifreq ifr; int goterr = 0, didnetmask = 0; char **spp; int fd; #if HAVE_AFINET6 extern struct aftype inet6_aftype; struct sockaddr_in6 sa6; struct in6_ifreq ifr6; unsigned long prefix_len; char *cp; #endif #if I18N bindtextdomain("net-tools", "/usr/share/locale"); textdomain("net-tools"); #endif /* Create a channel to the NET kernel. */ if ((skfd = sockets_open(0)) < 0) { perror("socket"); exit(1); } /* Find any options. */ argc--; argv++; while (argc && *argv[0] == '-') { if (!strcmp(*argv, "-a")) opt_a = 1; if (!strcmp(*argv, "-v")) opt_v = 1; if (!strcmp(*argv, "-V") || !strcmp(*argv, "-version") || !strcmp(*argv, "--version")) version(); if (!strcmp(*argv, "-?") || !strcmp(*argv, "-h") || !strcmp(*argv, "-help") || !strcmp(*argv, "--help")) usage(); argv++; argc--; } /* Do we have to show the current setup? */ if (argc == 0) { int err = if_print((char *) NULL); (void) close(skfd); exit(err < 0); } /* No. Fetch the interface name. */ spp = argv; safe_strncpy(ifr.ifr_name, *spp++, IFNAMSIZ); if (*spp == (char *) NULL) { int err = if_print(ifr.ifr_name); (void) close(skfd); exit(err < 0); } /* setup the vlan if required */ if (if_name_is_vlan(ifr.ifr_name)) { struct interface *i; if ((i = lookup_interface(ifr.ifr_name)) == NULL) { fprintf (stderr, "Couldn't lookup interfaces\n"); exit(1); } if (do_if_fetch(i) < 0) { int err; printf("Creating new vlan\n"); err = setup_vlan(ifr.ifr_name); if (err < 0) { fprintf(stderr, "Cannot init required vlan %s - %d\n", ifr.ifr_name, err); exit(err < 0); } } } /* The next argument is either an address family name, or an option. */ if ((ap = get_aftype(*spp)) == NULL) ap = get_aftype(DFLT_AF); else { /* XXX: should print the current setup if no args left, but only for this family */ spp++; addr_family = ap->af; } if (sockets_open(addr_family) < 0) { perror("family socket"); exit(1); } /* Process the remaining arguments. */ while (*spp != (char *) NULL) { if (!strcmp(*spp, "arp")) { goterr |= clr_flag(ifr.ifr_name, IFF_NOARP); spp++; continue; } if (!strcmp(*spp, "-arp")) { goterr |= set_flag(ifr.ifr_name, IFF_NOARP); spp++; continue; } #ifdef IFF_PORTSEL if (!strcmp(*spp, "media") || !strcmp(*spp, "port")) { if (*++spp == NULL) usage(); if (!strcasecmp(*spp, "auto")) { goterr |= set_flag(ifr.ifr_name, IFF_AUTOMEDIA); } else { int i, j, newport; char *endp; newport = strtol(*spp, &endp, 10); if (*endp != 0) { newport = -1; for (i = 0; if_port_text[i][0] && newport == -1; i++) { for (j = 0; if_port_text[i][j]; j++) { if (!strcasecmp(*spp, if_port_text[i][j])) { newport = i; break; } } } } spp++; if (newport == -1) { fprintf(stderr, _("Unknown media type.\n")); goterr = 1; } else { if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { goterr = 1; continue; } ifr.ifr_map.port = newport; if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { perror("SIOCSIFMAP"); goterr = 1; } } } continue; } #endif if (!strcmp(*spp, "trailers")) { goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS); spp++; continue; } if (!strcmp(*spp, "-trailers")) { goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS); spp++; continue; } if (!strcmp(*spp, "promisc")) { goterr |= set_flag(ifr.ifr_name, IFF_PROMISC); spp++; continue; } if (!strcmp(*spp, "-promisc")) { goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC); spp++; continue; } if (!strcmp(*spp, "multicast")) { goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST); spp++; continue; } if (!strcmp(*spp, "-multicast")) { goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST); spp++; continue; } if (!strcmp(*spp, "allmulti")) { goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI); spp++; continue; } if (!strcmp(*spp, "-allmulti")) { goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI); spp++; continue; } if (!strcmp(*spp, "up")) { goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING)); spp++; continue; } if (!strcmp(*spp, "down")) { goterr |= clr_flag(ifr.ifr_name, IFF_UP); spp++; continue; } #ifdef HAVE_DYNAMIC if (!strcmp(*spp, "dynamic")) { goterr |= set_flag(ifr.ifr_name, IFF_DYNAMIC); spp++; continue; } if (!strcmp(*spp, "-dynamic")) { goterr |= clr_flag(ifr.ifr_name, IFF_DYNAMIC); spp++; continue; } #endif if (!strcmp(*spp, "metric")) { if (*++spp == NULL) usage(); ifr.ifr_metric = atoi(*spp); if (ioctl(skfd, SIOCSIFMETRIC, &ifr) < 0) { fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "mtu")) { if (*++spp == NULL) usage(); ifr.ifr_mtu = atoi(*spp); if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) { fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #ifdef SIOCSKEEPALIVE if (!strcmp(*spp, "keepalive")) { if (*++spp == NULL) usage(); ifr.ifr_data = (caddr_t) atoi(*spp); if (ioctl(skfd, SIOCSKEEPALIVE, &ifr) < 0) { fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif #ifdef SIOCSOUTFILL if (!strcmp(*spp, "outfill")) { if (*++spp == NULL) usage(); ifr.ifr_data = (caddr_t) atoi(*spp); if (ioctl(skfd, SIOCSOUTFILL, &ifr) < 0) { fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif if (!strcmp(*spp, "-broadcast")) { goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST); spp++; continue; } if (!strcmp(*spp, "broadcast")) { if (*++spp != NULL) { safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa) < 0) { ap->herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_broadaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(ap->fd, SIOCSIFBRDADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFBRDADDR: %s\n", strerror(errno)); goterr = 1; } spp++; } goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST); continue; } if (!strcmp(*spp, "dstaddr")) { if (*++spp == NULL) usage(); safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa) < 0) { ap->herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFDSTADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "netmask")) { if (*++spp == NULL || didnetmask) usage(); safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa) < 0) { ap->herror(host); goterr = 1; spp++; continue; } didnetmask++; goterr = set_netmask(ap->fd, &ifr, &sa); spp++; continue; } #ifdef HAVE_TXQUEUELEN if (!strcmp(*spp, "txqueuelen")) { if (*++spp == NULL) usage(); ifr.ifr_qlen = strtoul(*spp, NULL, 0); if (ioctl(skfd, SIOCSIFTXQLEN, &ifr) < 0) { fprintf(stderr, "SIOCSIFTXQLEN: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif if (!strcmp(*spp, "mem_start")) { if (*++spp == NULL) usage(); if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { goterr = 1; continue; } ifr.ifr_map.mem_start = strtoul(*spp, NULL, 0); if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "io_addr")) { if (*++spp == NULL) usage(); if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { goterr = 1; continue; } ifr.ifr_map.base_addr = strtol(*spp, NULL, 0); if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "irq")) { if (*++spp == NULL) usage(); if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { goterr = 1; continue; } ifr.ifr_map.irq = atoi(*spp); if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "-pointopoint")) { goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT); spp++; continue; } if (!strcmp(*spp, "pointopoint")) { if (*(spp + 1) != NULL) { spp++; safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa)) { ap->herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFDSTADDR: %s\n", strerror(errno)); goterr = 1; } } goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT); spp++; continue; }; if (!strcmp(*spp, "hw")) { if (*++spp == NULL) usage(); if ((hw = get_hwtype(*spp)) == NULL) usage(); if (*++spp == NULL) usage(); safe_strncpy(host, *spp, (sizeof host)); if (hw->input(host, &sa) < 0) { fprintf(stderr, _("%s: invalid %s address.\n"), host, hw->name); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFHWADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #if HAVE_AFINET6 if (!strcmp(*spp, "add")) { if (*++spp == NULL) usage(); if ((cp = strchr(*spp, '/'))) { prefix_len = atol(cp + 1); if ((prefix_len < 0) || (prefix_len > 128)) usage(); *cp = 0; } else { prefix_len = 0; } safe_strncpy(host, *spp, (sizeof host)); if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) { inet6_aftype.herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); fd = get_socket_for_af(AF_INET6); if (fd < 0) { fprintf(stderr, _("No support for INET6 on this system.\n")); goterr = 1; spp++; continue; } if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { perror("SIOGIFINDEX"); goterr = 1; spp++; continue; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { perror("SIOCSIFADDR"); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "del")) { if (*++spp == NULL) usage(); if ((cp = strchr(*spp, '/'))) { prefix_len = atol(cp + 1); if ((prefix_len < 0) || (prefix_len > 128)) usage(); *cp = 0; } else { prefix_len = 0; } safe_strncpy(host, *spp, (sizeof host)); if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) { inet6_aftype.herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); fd = get_socket_for_af(AF_INET6); if (fd < 0) { fprintf(stderr, _("No support for INET6 on this system.\n")); goterr = 1; spp++; continue; } if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { perror("SIOGIFINDEX"); goterr = 1; spp++; continue; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; #ifdef SIOCDIFADDR if (ioctl(fd, SIOCDIFADDR, &ifr6) < 0) { fprintf(stderr, "SIOCDIFADDR: %s\n", strerror(errno)); goterr = 1; } #else fprintf(stderr, _("Address deletion not supported on this system.\n")); #endif spp++; continue; } if (!strcmp(*spp, "tunnel")) { if (*++spp == NULL) usage(); if ((cp = strchr(*spp, '/'))) { prefix_len = atol(cp + 1); if ((prefix_len < 0) || (prefix_len > 128)) usage(); *cp = 0; } else { prefix_len = 0; } safe_strncpy(host, *spp, (sizeof host)); if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) { inet6_aftype.herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); fd = get_socket_for_af(AF_INET6); if (fd < 0) { fprintf(stderr, _("No support for INET6 on this system.\n")); goterr = 1; spp++; continue; } if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { perror("SIOGIFINDEX"); goterr = 1; spp++; continue; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; if (ioctl(fd, SIOCSIFDSTADDR, &ifr6) < 0) { fprintf(stderr, "SIOCSIFDSTADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif /* If the next argument is a valid hostname, assume OK. */ safe_strncpy(host, *spp, (sizeof host)); /* FIXME: sa is too small for INET6 addresses, inet6 should use that too, broadcast is unexpected */ if (ap->getmask) { switch (ap->getmask(host, &sa, NULL)) { case -1: usage(); break; case 1: if (didnetmask) usage(); goterr = set_netmask(skfd, &ifr, &sa); didnetmask++; break; } } if (ap->input(0, host, &sa) < 0) { ap->herror(host); usage(); } memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr)); { int r = 0; /* to shut gcc up */ switch (ap->af) { #if HAVE_AFINET case AF_INET: fd = get_socket_for_af(AF_INET); if (fd < 0) { fprintf(stderr, _("No support for INET on this system.\n")); exit(1); } r = ioctl(fd, SIOCSIFADDR, &ifr); break; #endif #if HAVE_AFECONET case AF_ECONET: fd = get_socket_for_af(AF_ECONET); if (fd < 0) { fprintf(stderr, _("No support for ECONET on this system.\n")); exit(1); } r = ioctl(fd, SIOCSIFADDR, &ifr); break; #endif default: fprintf(stderr, _("Don't know how to set addresses for family %d.\n"), ap->af); exit(1); } if (r < 0) { perror("SIOCSIFADDR"); goterr = 1; } } /* * Don't do the set_flag() if the address is an alias with a - at the * end, since it's deleted already! - Roman * * Should really use regex.h here, not sure though how well it'll go * with the cross-platform support etc. */ { char *ptr; short int found_colon = 0; for (ptr = ifr.ifr_name; *ptr; ptr++ ) if (*ptr == ':') found_colon++; if (!(found_colon && *(ptr - 1) == '-')) goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING)); } spp++; } return (goterr); }
int main(int argc, char **argv) { struct sockaddr sa; struct sockaddr samask; struct sockaddr_in sin; char host[128]; struct aftype *ap; struct hwtype *hw; struct ifreq ifr; int goterr = 0, didnetmask = 0, neednetmask=0; char **spp; int fd; #if HAVE_AFINET6 extern struct aftype inet6_aftype; struct sockaddr_in6 sa6; struct in6_ifreq ifr6; unsigned long prefix_len; char *cp; #endif #if HAVE_AFINET extern struct aftype inet_aftype; #endif #if I18N setlocale (LC_ALL, ""); bindtextdomain("net-tools", "/usr/share/locale"); textdomain("net-tools"); #endif /* Find any options. */ argc--; argv++; while (argc && *argv[0] == '-') { if (!strcmp(*argv, "-a")) opt_a = 1; else if (!strcmp(*argv, "-s")) ife_short = 1; else if (!strcmp(*argv, "-v")) opt_v = 1; else if (!strcmp(*argv, "-V") || !strcmp(*argv, "-version") || !strcmp(*argv, "--version")) version(); else if (!strcmp(*argv, "-?") || !strcmp(*argv, "-h") || !strcmp(*argv, "-help") || !strcmp(*argv, "--help")) usage(); else { fprintf(stderr, _("ifconfig: option `%s' not recognised.\n"), argv[0]); fprintf(stderr, _("ifconfig: `--help' gives usage information.\n")); exit(1); } argv++; argc--; } /* Create a channel to the NET kernel. */ if ((skfd = sockets_open(0)) < 0) { perror("socket"); exit(1); } /* Do we have to show the current setup? */ if (argc == 0) { int err = if_print((char *) NULL); (void) close(skfd); exit(err < 0); } /* No. Fetch the interface name. */ spp = argv; safe_strncpy(ifr.ifr_name, *spp++, IFNAMSIZ); if (*spp == (char *) NULL) { int err = if_print(ifr.ifr_name); (void) close(skfd); exit(err < 0); } /* The next argument is either an address family name, or an option. */ if ((ap = get_aftype(*spp)) != NULL) spp++; /* it was a AF name */ else ap = get_aftype(DFLT_AF); if (ap) { addr_family = ap->af; skfd = ap->fd; } /* Process the remaining arguments. */ while (*spp != (char *) NULL) { if (!strcmp(*spp, "arp")) { goterr |= clr_flag(ifr.ifr_name, IFF_NOARP); spp++; continue; } if (!strcmp(*spp, "-arp")) { goterr |= set_flag(ifr.ifr_name, IFF_NOARP); spp++; continue; } #ifdef IFF_PORTSEL if (!strcmp(*spp, "media") || !strcmp(*spp, "port")) { if (*++spp == NULL) usage(); if (!strcasecmp(*spp, "auto")) { goterr |= set_flag(ifr.ifr_name, IFF_AUTOMEDIA); } else { int i, j, newport; char *endp; newport = strtol(*spp, &endp, 10); if (*endp != 0) { newport = -1; for (i = 0; if_port_text[i][0] && newport == -1; i++) { for (j = 0; if_port_text[i][j]; j++) { if (!strcasecmp(*spp, if_port_text[i][j])) { newport = i; break; } } } } spp++; if (newport == -1) { fprintf(stderr, _("Unknown media type.\n")); goterr = 1; } else { if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { perror("port: SIOCGIFMAP"); goterr = 1; continue; } ifr.ifr_map.port = newport; if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { perror("port: SIOCSIFMAP"); goterr = 1; } } } continue; } #endif if (!strcmp(*spp, "trailers")) { goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS); spp++; continue; } if (!strcmp(*spp, "-trailers")) { goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS); spp++; continue; } if (!strcmp(*spp, "promisc")) { goterr |= set_flag(ifr.ifr_name, IFF_PROMISC); spp++; continue; } if (!strcmp(*spp, "-promisc")) { goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC); if (test_flag(ifr.ifr_name, IFF_PROMISC) > 0) fprintf(stderr, _("Warning: Interface %s still in promisc mode... maybe other application is running?\n"), ifr.ifr_name); spp++; continue; } if (!strcmp(*spp, "multicast")) { goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST); spp++; continue; } if (!strcmp(*spp, "-multicast")) { goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST); if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0) fprintf(stderr, _("Warning: Interface %s still in MULTICAST mode.\n"), ifr.ifr_name); spp++; continue; } if (!strcmp(*spp, "allmulti")) { goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI); spp++; continue; } if (!strcmp(*spp, "-allmulti")) { goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI); if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0) fprintf(stderr, _("Warning: Interface %s still in ALLMULTI mode.\n"), ifr.ifr_name); spp++; continue; } if (!strcmp(*spp, "up")) { goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING)); spp++; continue; } if (!strcmp(*spp, "down")) { goterr |= clr_flag(ifr.ifr_name, IFF_UP); spp++; continue; } #ifdef HAVE_DYNAMIC if (!strcmp(*spp, "dynamic")) { goterr |= set_flag(ifr.ifr_name, IFF_DYNAMIC); spp++; continue; } if (!strcmp(*spp, "-dynamic")) { goterr |= clr_flag(ifr.ifr_name, IFF_DYNAMIC); spp++; if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0) fprintf(stderr, _("Warning: Interface %s still in DYNAMIC mode.\n"), ifr.ifr_name); continue; } #endif if (!strcmp(*spp, "metric")) { if (*++spp == NULL) usage(); ifr.ifr_metric = atoi(*spp); if (ioctl(skfd, SIOCSIFMETRIC, &ifr) < 0) { fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "mtu")) { if (*++spp == NULL) usage(); ifr.ifr_mtu = atoi(*spp); if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) { fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #ifdef SIOCSKEEPALIVE if (!strcmp(*spp, "keepalive")) { if (*++spp == NULL) usage(); ifr.ifr_data = (caddr_t) atoi(*spp); if (ioctl(skfd, SIOCSKEEPALIVE, &ifr) < 0) { fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif #ifdef SIOCSOUTFILL if (!strcmp(*spp, "outfill")) { if (*++spp == NULL) usage(); ifr.ifr_data = (caddr_t) atoi(*spp); if (ioctl(skfd, SIOCSOUTFILL, &ifr) < 0) { fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif if (!strcmp(*spp, "-broadcast")) { goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST); if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0) fprintf(stderr, _("Warning: Interface %s still in BROADCAST mode.\n"), ifr.ifr_name); spp++; continue; } if (!strcmp(*spp, "broadcast")) { if (*++spp != NULL) { safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa) < 0) { if (ap->herror) ap->herror(host); else fprintf(stderr, _("ifconfig: Error resolving '%s' for broadcast\n"), host); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_broadaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(ap->fd, SIOCSIFBRDADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFBRDADDR: %s\n", strerror(errno)); goterr = 1; } spp++; } goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST); continue; } if (!strcmp(*spp, "dstaddr")) { if (*++spp == NULL) usage(); safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa) < 0) { if (ap->herror) ap->herror(host); else fprintf(stderr, _("ifconfig: Error resolving '%s' for dstaddr\n"), host); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFDSTADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "netmask")) { if (*++spp == NULL || didnetmask) usage(); safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa) < 0) { if (ap->herror) ap->herror(host); else fprintf(stderr, _("ifconfig: Error resolving '%s' for netmask\n"), host); goterr = 1; spp++; continue; } didnetmask++; goterr |= set_netmask(ap->fd, &ifr, &sa); spp++; continue; } #ifdef HAVE_TXQUEUELEN if (!strcmp(*spp, "txqueuelen")) { if (*++spp == NULL) usage(); ifr.ifr_qlen = strtoul(*spp, NULL, 0); if (ioctl(skfd, SIOCSIFTXQLEN, &ifr) < 0) { fprintf(stderr, "SIOCSIFTXQLEN: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif if (!strcmp(*spp, "mem_start")) { if (*++spp == NULL) usage(); if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { fprintf(stderr, "mem_start: SIOCGIFMAP: %s\n", strerror(errno)); spp++; goterr = 1; continue; } ifr.ifr_map.mem_start = strtoul(*spp, NULL, 0); if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { fprintf(stderr, "mem_start: SIOCSIFMAP: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "io_addr")) { if (*++spp == NULL) usage(); if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { fprintf(stderr, "io_addr: SIOCGIFMAP: %s\n", strerror(errno)); spp++; goterr = 1; continue; } ifr.ifr_map.base_addr = strtol(*spp, NULL, 0); if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { fprintf(stderr, "io_addr: SIOCSIFMAP: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "irq")) { if (*++spp == NULL) usage(); if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) { fprintf(stderr, "irq: SIOCGIFMAP: %s\n", strerror(errno)); goterr = 1; spp++; continue; } ifr.ifr_map.irq = atoi(*spp); if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) { fprintf(stderr, "irq: SIOCSIFMAP: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } if (!strcmp(*spp, "-pointopoint")) { goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT); spp++; if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0) fprintf(stderr, _("Warning: Interface %s still in POINTOPOINT mode.\n"), ifr.ifr_name); continue; } if (!strcmp(*spp, "pointopoint")) { if (*(spp + 1) != NULL) { spp++; safe_strncpy(host, *spp, (sizeof host)); if (ap->input(0, host, &sa)) { if (ap->herror) ap->herror(host); else fprintf(stderr, _("ifconfig: Error resolving '%s' for pointopoint\n"), host); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) { fprintf(stderr, "SIOCSIFDSTADDR: %s\n", strerror(errno)); goterr = 1; } } goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT); spp++; continue; }; if (!strcmp(*spp, "hw")) { if (*++spp == NULL) usage(); if ((hw = get_hwtype(*spp)) == NULL) usage(); if (hw->input == NULL) { fprintf(stderr, _("hw address type `%s' has no handler to set address. failed.\n"), *spp); spp+=2; goterr = 1; continue; } if (*++spp == NULL) usage(); safe_strncpy(host, *spp, (sizeof host)); if (hw->input(host, &sa) < 0) { fprintf(stderr, _("%s: invalid %s address.\n"), host, hw->name); goterr = 1; spp++; continue; } memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa, sizeof(struct sockaddr)); if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) { if (errno == EBUSY) fprintf(stderr, "SIOCSIFHWADDR: %s - you may need to down the interface\n", strerror(errno)); else fprintf(stderr, "SIOCSIFHWADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #if HAVE_AFINET || HAVE_AFINET6 if (!strcmp(*spp, "add")) { if (*++spp == NULL) usage(); #if HAVE_AFINET6 if (strchr(*spp, ':')) { /* INET6 */ if ((cp = strchr(*spp, '/'))) { prefix_len = atol(cp + 1); if ((prefix_len < 0) || (prefix_len > 128)) usage(); *cp = 0; } else { prefix_len = 128; } safe_strncpy(host, *spp, (sizeof host)); if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) { if (inet6_aftype.herror) inet6_aftype.herror(host); else fprintf(stderr, _("ifconfig: Error resolving '%s' for add\n"), host); goterr = 1; spp++; continue; } memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); fd = get_socket_for_af(AF_INET6); if (fd < 0) { fprintf(stderr, _("No support for INET6 on this system.\n")); goterr = 1; spp++; continue; } if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { perror("SIOGIFINDEX"); goterr = 1; spp++; continue; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { perror("SIOCSIFADDR"); goterr = 1; } spp++; continue; } #endif #ifdef HAVE_AFINET { /* ipv4 address a.b.c.d */ unsigned long ip, nm, bc; safe_strncpy(host, *spp, (sizeof host)); if (inet_aftype.input(0, host, (struct sockaddr *)&sin) < 0) { ap->herror(host); goterr = 1; spp++; continue; } fd = get_socket_for_af(AF_INET); if (fd < 0) { fprintf(stderr, _("No support for INET on this system.\n")); goterr = 1; spp++; continue; } memcpy(&ip, &sin.sin_addr.s_addr, sizeof(unsigned long)); if (get_nmbc_parent(ifr.ifr_name, &nm, &bc) < 0) { fprintf(stderr, _("Interface %s not initialized\n"), ifr.ifr_name); goterr = 1; spp++; continue; } set_ifstate(ifr.ifr_name, ip, nm, bc, 1); } spp++; continue; #else fprintf(stderr, _("Bad address.\n")); #endif } #endif #if HAVE_AFINET || HAVE_AFINET6 if (!strcmp(*spp, "del")) { if (*++spp == NULL) usage(); #ifdef SIOCDIFADDR #if HAVE_AFINET6 if (strchr(*spp, ':')) { /* INET6 */ if ((cp = strchr(*spp, '/'))) { prefix_len = atol(cp + 1); if ((prefix_len < 0) || (prefix_len > 128)) usage(); *cp = 0; } else { prefix_len = 128; } safe_strncpy(host, *spp, (sizeof host)); if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) { inet6_aftype.herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); fd = get_socket_for_af(AF_INET6); if (fd < 0) { fprintf(stderr, _("No support for INET6 on this system.\n")); goterr = 1; spp++; continue; } if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { perror("SIOGIFINDEX"); goterr = 1; spp++; continue; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; if (opt_v) fprintf(stderr, "now deleting: ioctl(SIOCDIFADDR,{ifindex=%d,prefixlen=%ld})\n",ifr.ifr_ifindex,prefix_len); if (ioctl(fd, SIOCDIFADDR, &ifr6) < 0) { fprintf(stderr, "SIOCDIFADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif #ifdef HAVE_AFINET { /* ipv4 address a.b.c.d */ unsigned long ip, nm, bc; safe_strncpy(host, *spp, (sizeof host)); if (inet_aftype.input(0, host, (struct sockaddr *)&sin) < 0) { ap->herror(host); goterr = 1; spp++; continue; } fd = get_socket_for_af(AF_INET); if (fd < 0) { fprintf(stderr, _("No support for INET on this system.\n")); goterr = 1; spp++; continue; } memcpy(&ip, &sin.sin_addr.s_addr, sizeof(unsigned long)); if (get_nmbc_parent(ifr.ifr_name, &nm, &bc) < 0) { fprintf(stderr, _("Interface %s not initialized\n"), ifr.ifr_name); goterr = 1; spp++; continue; } set_ifstate(ifr.ifr_name, ip, nm, bc, 0); } spp++; continue; #else fprintf(stderr, _("Bad address.\n")); #endif #else fprintf(stderr, _("Address deletion not supported on this system.\n")); #endif } #endif #if HAVE_AFINET6 if (!strcmp(*spp, "tunnel")) { if (*++spp == NULL) usage(); if ((cp = strchr(*spp, '/'))) { prefix_len = atol(cp + 1); if ((prefix_len < 0) || (prefix_len > 128)) usage(); *cp = 0; } else { prefix_len = 128; } safe_strncpy(host, *spp, (sizeof host)); if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) { inet6_aftype.herror(host); goterr = 1; spp++; continue; } memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); fd = get_socket_for_af(AF_INET6); if (fd < 0) { fprintf(stderr, _("No support for INET6 on this system.\n")); goterr = 1; spp++; continue; } if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { perror("SIOGIFINDEX"); goterr = 1; spp++; continue; } ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; if (ioctl(fd, SIOCSIFDSTADDR, &ifr6) < 0) { fprintf(stderr, "SIOCSIFDSTADDR: %s\n", strerror(errno)); goterr = 1; } spp++; continue; } #endif /* If the next argument is a valid hostname, assume OK. */ safe_strncpy(host, *spp, (sizeof host)); /* FIXME: sa is too small for INET6 addresses, inet6 should use that too, broadcast is unexpected */ if (ap->getmask) { switch (ap->getmask(host, &samask, NULL)) { case -1: usage(); break; case 1: if (didnetmask) usage(); // remeber to set the netmask from samask later neednetmask = 1; break; } } if (ap->input == NULL) { fprintf(stderr, _("ifconfig: Cannot set address for this protocol family.\n")); exit(1); } if (ap->input(0, host, &sa) < 0) { if (ap->herror) ap->herror(host); else fprintf(stderr,_("ifconfig: error resolving '%s' to set address for af=%s\n"), host, ap->name); fprintf(stderr, _("ifconfig: `--help' gives usage information.\n")); exit(1); } memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr)); { int r = 0; /* to shut gcc up */ switch (ap->af) { #if HAVE_AFINET case AF_INET: fd = get_socket_for_af(AF_INET); if (fd < 0) { fprintf(stderr, _("No support for INET on this system.\n")); exit(1); } r = ioctl(fd, SIOCSIFADDR, &ifr); break; #endif #if HAVE_AFECONET case AF_ECONET: fd = get_socket_for_af(AF_ECONET); if (fd < 0) { fprintf(stderr, _("No support for ECONET on this system.\n")); exit(1); } r = ioctl(fd, SIOCSIFADDR, &ifr); break; #endif default: fprintf(stderr, _("Don't know how to set addresses for family %d.\n"), ap->af); exit(1); } if (r < 0) { perror("SIOCSIFADDR"); goterr = 1; } } /* * Don't do the set_flag() if the address is an alias with a - at the * end, since it's deleted already! - Roman * * Should really use regex.h here, not sure though how well it'll go * with the cross-platform support etc. */ { char *ptr; short int found_colon = 0; for (ptr = ifr.ifr_name; *ptr; ptr++ ) if (*ptr == ':') found_colon++; if (!(found_colon && *(ptr - 1) == '-')) goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING)); } spp++; } if (neednetmask) { goterr |= set_netmask(skfd, &ifr, &samask); didnetmask++; } if (opt_v && goterr) fprintf(stderr, _("WARNING: at least one error occured. (%d)\n"), goterr); return (goterr); }