diff options
| author | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2002-12-17 12:43:43 +0000 |
|---|---|---|
| committer | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2002-12-17 12:43:43 +0000 |
| commit | 4b57f7fc820efc15686c271a863cd725ea6daa16 (patch) | |
| tree | 02bcc90e955606069d534d156599ef7ff7fb24b5 | |
| parent | 02aaca817acffbbc6e5466421792c0e2bf886f9e (diff) | |
| download | busybox-w32-4b57f7fc820efc15686c271a863cd725ea6daa16.tar.gz busybox-w32-4b57f7fc820efc15686c271a863cd725ea6daa16.tar.bz2 busybox-w32-4b57f7fc820efc15686c271a863cd725ea6daa16.zip | |
Get interface names using ioctl rather than /proc, from Nick Fedchik
git-svn-id: svn://busybox.net/trunk/busybox@6224 69ca8d6d-28ef-0310-b511-8ec308f3f277
| -rw-r--r-- | networking/nameif.c | 132 |
1 files changed, 68 insertions, 64 deletions
diff --git a/networking/nameif.c b/networking/nameif.c index 4b2d090ca..a9d422110 100644 --- a/networking/nameif.c +++ b/networking/nameif.c | |||
| @@ -22,21 +22,20 @@ | |||
| 22 | * | 22 | * |
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | |||
| 25 | #include <sys/syslog.h> | 26 | #include <sys/syslog.h> |
| 26 | #include <sys/socket.h> | 27 | #include <sys/socket.h> |
| 27 | #include <sys/ioctl.h> | 28 | #include <sys/ioctl.h> |
| 28 | |||
| 29 | #include <errno.h> | 29 | #include <errno.h> |
| 30 | #include <getopt.h> | 30 | #include <getopt.h> |
| 31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
| 32 | #include <string.h> | 32 | #include <string.h> |
| 33 | #include <net/if.h> | 33 | #include <net/if.h> |
| 34 | #include <netinet/ether.h> | 34 | #include <netinet/ether.h> |
| 35 | #include <linux/sockios.h> | ||
| 35 | 36 | ||
| 36 | #include "busybox.h" | 37 | #include "busybox.h" |
| 37 | 38 | ||
| 38 | /* set interface name, from <linux/sockios.h> */ | ||
| 39 | #define SIOCSIFNAME 0x8923 | ||
| 40 | /* Octets in one ethernet addr, from <linux/if_ether.h> */ | 39 | /* Octets in one ethernet addr, from <linux/if_ether.h> */ |
| 41 | #define ETH_ALEN 6 | 40 | #define ETH_ALEN 6 |
| 42 | 41 | ||
| @@ -46,12 +45,12 @@ | |||
| 46 | 45 | ||
| 47 | typedef struct mactable_s { | 46 | typedef struct mactable_s { |
| 48 | struct mactable_s *next; | 47 | struct mactable_s *next; |
| 49 | struct mactable_s **pprev; | 48 | struct mactable_s *prev; |
| 50 | char *ifname; | 49 | char *ifname; |
| 51 | struct ether_addr *mac; | 50 | struct ether_addr *mac; |
| 52 | } mactable_t; | 51 | } mactable_t; |
| 53 | 52 | ||
| 54 | static void serror_msg_and_die(const char use_syslog, const char *s, ...) | 53 | static void serror(const char use_syslog, const char *s, ...) |
| 55 | { | 54 | { |
| 56 | va_list ap; | 55 | va_list ap; |
| 57 | 56 | ||
| @@ -67,20 +66,35 @@ static void serror_msg_and_die(const char use_syslog, const char *s, ...) | |||
| 67 | } | 66 | } |
| 68 | 67 | ||
| 69 | va_end(ap); | 68 | va_end(ap); |
| 70 | 69 | ||
| 71 | exit(EXIT_FAILURE); | 70 | exit(EXIT_FAILURE); |
| 72 | } | 71 | } |
| 73 | 72 | ||
| 73 | /* Check ascii str_macaddr, convert and copy to *mac */ | ||
| 74 | struct ether_addr *cc_macaddr(char *str_macaddr, unsigned char use_syslog) | ||
| 75 | { | ||
| 76 | struct ether_addr *lmac, *mac; | ||
| 77 | |||
| 78 | lmac = ether_aton(str_macaddr); | ||
| 79 | if (lmac == NULL) | ||
| 80 | serror(use_syslog, "cannot parse MAC %s", str_macaddr); | ||
| 81 | mac = xcalloc(1, ETH_ALEN); | ||
| 82 | memcpy(mac, lmac, ETH_ALEN); | ||
| 83 | |||
| 84 | return mac; | ||
| 85 | } | ||
| 86 | |||
| 74 | int nameif_main(int argc, char **argv) | 87 | int nameif_main(int argc, char **argv) |
| 75 | { | 88 | { |
| 76 | mactable_t *clist = NULL; | 89 | mactable_t *clist = NULL; |
| 77 | FILE *ifh; | 90 | FILE *ifh; |
| 78 | char *fname = "/etc/mactab"; | 91 | char *fname = "/etc/mactab"; |
| 79 | char *line; | 92 | char *line; |
| 80 | unsigned short linenum = 0; | ||
| 81 | unsigned char use_syslog = 0; | 93 | unsigned char use_syslog = 0; |
| 82 | int ctl_sk = -1; | 94 | int ctl_sk = -1; |
| 83 | int opt; | 95 | int opt; |
| 96 | int if_index = 1; | ||
| 97 | mactable_t *ch = NULL; | ||
| 84 | 98 | ||
| 85 | static struct option opts[] = { | 99 | static struct option opts[] = { |
| 86 | {"syslog", 0, NULL, 's'}, | 100 | {"syslog", 0, NULL, 's'}, |
| @@ -101,40 +115,33 @@ int nameif_main(int argc, char **argv) | |||
| 101 | } | 115 | } |
| 102 | } | 116 | } |
| 103 | 117 | ||
| 104 | if ((argc - optind) & 1) { | 118 | if ((argc - optind) & 1) |
| 105 | show_usage(); | 119 | show_usage(); |
| 106 | } | ||
| 107 | 120 | ||
| 108 | if (optind < argc) { | 121 | if (optind < argc) { |
| 109 | while (optind < argc) { | 122 | while (optind < argc) { |
| 110 | struct ether_addr *mac; | ||
| 111 | mactable_t *ch; | ||
| 112 | 123 | ||
| 113 | if (strlen(argv[optind]) > IF_NAMESIZE) { | 124 | if (strlen(argv[optind]) > IF_NAMESIZE) |
| 114 | serror_msg_and_die(use_syslog, "interface name `%s' too long", argv[optind]); | 125 | serror(use_syslog, "interface name `%s' too long", |
| 115 | } | 126 | argv[optind]); |
| 116 | optind++; | 127 | optind++; |
| 117 | mac = ether_aton(argv[optind]); | 128 | |
| 118 | if (mac == NULL) { | ||
| 119 | serror_msg_and_die(use_syslog, "cannot parse MAC %s", argv[optind]); | ||
| 120 | } | ||
| 121 | ch = xcalloc(1, sizeof(mactable_t)); | 129 | ch = xcalloc(1, sizeof(mactable_t)); |
| 130 | ch->next = NULL; | ||
| 131 | ch->prev = NULL; | ||
| 122 | ch->ifname = strdup(argv[optind - 1]); | 132 | ch->ifname = strdup(argv[optind - 1]); |
| 123 | ch->mac = xcalloc(1, ETH_ALEN); | 133 | ch->mac = cc_macaddr(argv[optind], use_syslog); |
| 124 | memcpy(ch->mac, mac, ETH_ALEN); | ||
| 125 | optind++; | 134 | optind++; |
| 126 | if (clist) | 135 | if (clist) |
| 127 | clist->pprev = &ch->next; | 136 | clist->prev = ch->next; |
| 128 | ch->next = clist; | 137 | ch->next = clist; |
| 129 | ch->pprev = &clist; | 138 | ch->prev = clist; |
| 130 | clist = ch; | 139 | clist = ch; |
| 131 | } | 140 | } |
| 132 | } else { | 141 | } else { |
| 133 | ifh = xfopen(fname, "r"); | 142 | ifh = xfopen(fname, "r"); |
| 134 | 143 | ||
| 135 | while ((line = get_line_from_file(ifh)) != NULL) { | 144 | while ((line = get_line_from_file(ifh)) != NULL) { |
| 136 | struct ether_addr *mac; | ||
| 137 | mactable_t *ch; | ||
| 138 | char *line_ptr; | 145 | char *line_ptr; |
| 139 | unsigned short name_length; | 146 | unsigned short name_length; |
| 140 | 147 | ||
| @@ -142,74 +149,71 @@ int nameif_main(int argc, char **argv) | |||
| 142 | if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) | 149 | if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) |
| 143 | continue; | 150 | continue; |
| 144 | name_length = strcspn(line_ptr, " \t"); | 151 | name_length = strcspn(line_ptr, " \t"); |
| 145 | if (name_length > IF_NAMESIZE) { | 152 | if (name_length > IF_NAMESIZE) |
| 146 | serror_msg_and_die(use_syslog, "interface name `%s' too long", argv[optind]); | 153 | serror(use_syslog, "interface name `%s' too long", |
| 147 | } | 154 | argv[optind]); |
| 148 | ch = xcalloc(1, sizeof(mactable_t)); | 155 | ch = xcalloc(1, sizeof(mactable_t)); |
| 156 | ch->next = NULL; | ||
| 157 | ch->prev = NULL; | ||
| 149 | ch->ifname = strndup(line_ptr, name_length); | 158 | ch->ifname = strndup(line_ptr, name_length); |
| 150 | line_ptr += name_length; | 159 | line_ptr += name_length; |
| 151 | line_ptr += strspn(line_ptr, " \t"); | 160 | line_ptr += strspn(line_ptr, " \t"); |
| 152 | name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:"); | 161 | name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:"); |
| 153 | line_ptr[name_length] = '\0'; | 162 | line_ptr[name_length] = '\0'; |
| 154 | mac = ether_aton(line_ptr); | 163 | ch->mac = cc_macaddr(line_ptr, use_syslog); |
| 155 | if (mac == NULL) { | ||
| 156 | serror_msg_and_die(use_syslog, "cannot parse MAC %s", argv[optind]); | ||
| 157 | } | ||
| 158 | ch->mac = xcalloc(1, ETH_ALEN); | ||
| 159 | memcpy(ch->mac, mac, ETH_ALEN); | ||
| 160 | if (clist) | 164 | if (clist) |
| 161 | clist->pprev = &ch->next; | 165 | clist->prev = ch; |
| 162 | ch->next = clist; | 166 | ch->next = clist; |
| 163 | ch->pprev = &clist; | ||
| 164 | clist = ch; | 167 | clist = ch; |
| 165 | free(line); | 168 | free(line); |
| 166 | } | 169 | } |
| 167 | fclose(ifh); | 170 | fclose(ifh); |
| 168 | } | 171 | } |
| 169 | 172 | ||
| 170 | ifh = xfopen("/proc/net/dev", "r"); | 173 | if ((ctl_sk = socket(PF_INET, SOCK_DGRAM, 0)) == -1) |
| 171 | while ((line = get_line_from_file(ifh)) != NULL) { | 174 | serror(use_syslog, "socket: %s", strerror(errno)); |
| 172 | char *line_ptr; | 175 | |
| 173 | unsigned short iface_name_length; | 176 | while (clist) { |
| 174 | struct ifreq ifr; | 177 | struct ifreq ifr; |
| 175 | mactable_t *ch = NULL; | ||
| 176 | 178 | ||
| 177 | linenum++; | 179 | bzero(&ifr, sizeof(struct ifreq)); |
| 178 | if (linenum < 3) | 180 | if_index++; |
| 179 | continue; | 181 | ifr.ifr_ifindex = if_index; |
| 180 | line_ptr = line + strspn(line, " \t"); | 182 | |
| 181 | if (line_ptr[0] == '\n') | 183 | /* Get ifname by index or die */ |
| 182 | continue; | 184 | if (ioctl(ctl_sk, SIOCGIFNAME, &ifr)) |
| 183 | iface_name_length = strcspn(line_ptr, ":"); | 185 | break; |
| 184 | if (ctl_sk < 0) | 186 | |
| 185 | ctl_sk = socket(PF_INET, SOCK_DGRAM, 0); | 187 | /* Has this device hwaddr? */ |
| 186 | memset(&ifr, 0, sizeof(struct ifreq)); | 188 | if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr)) |
| 187 | strncpy(ifr.ifr_name, line_ptr, iface_name_length); | ||
| 188 | if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr) < 0) { | ||
| 189 | // serror_msg(use_syslog, "cannot read hardware address of %s: %s", ifr.ifr_name, strerror(errno)); | ||
| 190 | continue; | 189 | continue; |
| 191 | } | 190 | |
| 191 | /* Search for mac like in ifr.ifr_hwaddr.sa_data */ | ||
| 192 | for (ch = clist; ch; ch = ch->next) | 192 | for (ch = clist; ch; ch = ch->next) |
| 193 | if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) | 193 | if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) |
| 194 | break; | 194 | break; |
| 195 | if (ch == NULL) { | 195 | |
| 196 | /* Nothing found for current ifr.ifr_hwaddr.sa_data */ | ||
| 197 | if (ch == NULL) | ||
| 196 | continue; | 198 | continue; |
| 197 | } | ||
| 198 | 199 | ||
| 199 | strcpy(ifr.ifr_newname, ch->ifname); | 200 | strcpy(ifr.ifr_newname, ch->ifname); |
| 200 | 201 | if (ioctl(ctl_sk, SIOCSIFNAME, &ifr) < 0) | |
| 201 | if (ioctl(ctl_sk, SIOCSIFNAME, &ifr) < 0) {; | 202 | serror(use_syslog, "cannot change ifname %s to %s: %s", |
| 202 | serror_msg_and_die(use_syslog, "cannot change name of %s to %s: %s", ifr.ifr_name, ch->ifname, strerror(errno)); | 203 | ifr.ifr_name, ch->ifname, strerror(errno)); |
| 204 | |||
| 205 | /* Remove list entry of renamed interface */ | ||
| 206 | if (ch->prev != NULL) { | ||
| 207 | (ch->prev)->next = ch->next; | ||
| 208 | } else { | ||
| 209 | clist = ch->next; | ||
| 203 | } | 210 | } |
| 204 | *ch->pprev = ch->next; | 211 | if (ch->next != NULL) |
| 212 | (ch->next)->prev = ch->prev; | ||
| 205 | free(ch); | 213 | free(ch); |
| 206 | free(line); | ||
| 207 | } | 214 | } |
| 208 | fclose(ifh); | ||
| 209 | 215 | ||
| 210 | while (clist) { | 216 | while (clist) { |
| 211 | mactable_t *ch; | ||
| 212 | |||
| 213 | ch = clist; | 217 | ch = clist; |
| 214 | clist = clist->next; | 218 | clist = clist->next; |
| 215 | free(ch); | 219 | free(ch); |
