Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/libiproute/iplink.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/libiproute/iplink.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 * iplink.c 3 * iplink.c "ip link". 3 4 * 4 * Authors: 5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 5 6 * 6 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 7 8 */ 8 9 9 #include "libbb.h" 10 11 #include <sys/ioctl.h> 12 #include <sys/socket.h> 13 14 #include <errno.h> 15 #include <string.h> 16 #include <unistd.h> 17 10 //#include <sys/ioctl.h> 11 //#include <sys/socket.h> 18 12 #include <net/if.h> 19 13 #include <net/if_packet.h> 20 14 #include <netpacket/packet.h> 21 22 15 #include <net/ethernet.h> 23 16 17 #include "ip_common.h" /* #include "libbb.h" is inside */ 24 18 #include "rt_names.h" 25 19 #include "utils.h" 26 #include "ip_common.h" 27 28 /* take from linux/sockios.h */ 20 21 /* taken from linux/sockios.h */ 29 22 #define SIOCSIFNAME 0x8923 /* set interface name */ 30 23 31 static int do_link; 32 33 static int on_off(char *msg) 34 { 35 bb_error_msg("Error: argument of \"%s\" must be \"on\" or \"off\"", msg); 36 return -1; 37 } 38 24 static void on_off(const char *msg) ATTRIBUTE_NORETURN; 25 static void on_off(const char *msg) 26 { 27 bb_error_msg_and_die("error: argument of \"%s\" must be \"on\" or \"off\"", msg); 28 } 29 30 /* Exits on error */ 39 31 static int get_ctl_fd(void) 40 32 { 41 int s_errno;42 33 int fd; 43 34 … … 45 36 if (fd >= 0) 46 37 return fd; 47 s_errno = errno;48 38 fd = socket(PF_PACKET, SOCK_DGRAM, 0); 49 39 if (fd >= 0) 50 40 return fd; 51 fd = socket(PF_INET6, SOCK_DGRAM, 0); 52 if (fd >= 0) 53 return fd; 54 errno = s_errno; 55 perror("Cannot create control socket"); 56 return -1; 57 } 58 59 static int do_chflags(char *dev, __u32 flags, __u32 mask) 41 return xsocket(PF_INET6, SOCK_DGRAM, 0); 42 } 43 44 /* Exits on error */ 45 static void do_chflags(char *dev, uint32_t flags, uint32_t mask) 60 46 { 61 47 struct ifreq ifr; 62 48 int fd; 63 int err; 64 65 strcpy(ifr.ifr_name, dev); 49 50 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); 66 51 fd = get_ctl_fd(); 67 if (fd < 0) 68 return -1; 69 err = ioctl(fd, SIOCGIFFLAGS, &ifr); 70 if (err) { 71 perror("SIOCGIFFLAGS"); 72 close(fd); 73 return -1; 74 } 75 if ((ifr.ifr_flags^flags)&mask) { 52 xioctl(fd, SIOCGIFFLAGS, &ifr); 53 if ((ifr.ifr_flags ^ flags) & mask) { 76 54 ifr.ifr_flags &= ~mask; 77 ifr.ifr_flags |= mask&flags; 78 err = ioctl(fd, SIOCSIFFLAGS, &ifr); 79 if (err) 80 perror("SIOCSIFFLAGS"); 55 ifr.ifr_flags |= mask & flags; 56 xioctl(fd, SIOCSIFFLAGS, &ifr); 81 57 } 82 58 close(fd); 83 return err; 84 } 85 86 static intdo_changename(char *dev, char *newdev)59 } 60 61 /* Exits on error */ 62 static void do_changename(char *dev, char *newdev) 87 63 { 88 64 struct ifreq ifr; 89 65 int fd; 90 int err; 91 92 strcpy(ifr.ifr_name, dev); 93 strcpy(ifr.ifr_newname, newdev); 66 67 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); 68 strncpy(ifr.ifr_newname, newdev, sizeof(ifr.ifr_newname)); 94 69 fd = get_ctl_fd(); 95 if (fd < 0) 96 return -1; 97 err = ioctl(fd, SIOCSIFNAME, &ifr); 98 if (err) { 99 perror("SIOCSIFNAME"); 100 close(fd); 101 return -1; 102 } 70 xioctl(fd, SIOCSIFNAME, &ifr); 103 71 close(fd); 104 return err; 105 } 106 107 static intset_qlen(char *dev, int qlen)72 } 73 74 /* Exits on error */ 75 static void set_qlen(char *dev, int qlen) 108 76 { 109 77 struct ifreq ifr; … … 111 79 112 80 s = get_ctl_fd(); 113 if (s < 0)114 return -1;115 116 81 memset(&ifr, 0, sizeof(ifr)); 117 str cpy(ifr.ifr_name, dev);82 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); 118 83 ifr.ifr_qlen = qlen; 119 if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) { 120 perror("SIOCSIFXQLEN"); 121 close(s); 122 return -1; 123 } 124 close(s); 125 126 return 0; 127 } 128 129 static int set_mtu(char *dev, int mtu) 84 xioctl(s, SIOCSIFTXQLEN, &ifr); 85 close(s); 86 } 87 88 /* Exits on error */ 89 static void set_mtu(char *dev, int mtu) 130 90 { 131 91 struct ifreq ifr; … … 133 93 134 94 s = get_ctl_fd(); 135 if (s < 0)136 return -1;137 138 95 memset(&ifr, 0, sizeof(ifr)); 139 str cpy(ifr.ifr_name, dev);96 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); 140 97 ifr.ifr_mtu = mtu; 141 if (ioctl(s, SIOCSIFMTU, &ifr) < 0) { 142 perror("SIOCSIFMTU"); 143 close(s); 144 return -1; 145 } 146 close(s); 147 148 return 0; 149 } 150 98 xioctl(s, SIOCSIFMTU, &ifr); 99 close(s); 100 } 101 102 /* Exits on error */ 151 103 static int get_address(char *dev, int *htype) 152 104 { … … 156 108 int s; 157 109 158 s = socket(PF_PACKET, SOCK_DGRAM, 0); 159 if (s < 0) { 160 perror("socket(PF_PACKET)"); 161 return -1; 162 } 110 s = xsocket(PF_PACKET, SOCK_DGRAM, 0); 163 111 164 112 memset(&ifr, 0, sizeof(ifr)); 165 strcpy(ifr.ifr_name, dev); 166 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 167 perror("SIOCGIFINDEX"); 168 close(s); 169 return -1; 170 } 113 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); 114 xioctl(s, SIOCGIFINDEX, &ifr); 171 115 172 116 memset(&me, 0, sizeof(me)); … … 174 118 me.sll_ifindex = ifr.ifr_ifindex; 175 119 me.sll_protocol = htons(ETH_P_LOOP); 176 if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) { 177 perror("bind"); 178 close(s); 179 return -1; 180 } 120 xbind(s, (struct sockaddr*)&me, sizeof(me)); 181 121 182 122 alen = sizeof(me); 183 123 if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) { 184 perror("getsockname"); 185 close(s); 186 return -1; 124 bb_perror_msg_and_die("getsockname"); 187 125 } 188 126 close(s); … … 191 129 } 192 130 193 static int parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr) 131 /* Exits on error */ 132 static void parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr) 194 133 { 195 134 int alen; 196 135 197 136 memset(ifr, 0, sizeof(*ifr)); 198 str cpy(ifr->ifr_name, dev);137 strncpy(ifr->ifr_name, dev, sizeof(ifr->ifr_name)); 199 138 ifr->ifr_hwaddr.sa_family = hatype; 200 139 alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), 14, lla); 201 140 if (alen < 0) 202 return -1;141 exit(1); 203 142 if (alen != halen) { 204 bb_error_msg("Wrong address (%s) length: expected %d bytes", lla, halen); 205 return -1; 206 } 207 return 0; 208 } 209 210 static int set_address(struct ifreq *ifr, int brd) 143 bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen); 144 } 145 } 146 147 /* Exits on error */ 148 static void set_address(struct ifreq *ifr, int brd) 211 149 { 212 150 int s; 213 151 214 152 s = get_ctl_fd(); 215 if (s < 0) 216 return -1; 217 if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) { 218 perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR"); 219 close(s); 220 return -1; 221 } 222 close(s); 223 return 0; 224 } 225 226 153 if (brd) 154 xioctl(s, SIOCSIFHWBROADCAST, ifr); 155 else 156 xioctl(s, SIOCSIFHWADDR, ifr); 157 close(s); 158 } 159 160 161 /* Return value becomes exitcode. It's okay to not return at all */ 227 162 static int do_set(int argc, char **argv) 228 163 { 229 164 char *dev = NULL; 230 __u32mask = 0;231 __u32flags = 0;165 uint32_t mask = 0; 166 uint32_t flags = 0; 232 167 int qlen = -1; 233 168 int mtu = -1; … … 237 172 char *newname = NULL; 238 173 int htype, halen; 174 static const char keywords[] ALIGN1 = 175 "up\0""down\0""name\0""mtu\0""multicast\0""arp\0""addr\0""dev\0" 176 "on\0""off\0"; 177 enum { ARG_up = 1, ARG_down, ARG_name, ARG_mtu, ARG_multicast, ARG_arp, 178 ARG_addr, ARG_dev, PARM_on, PARM_off }; 179 smalluint key; 239 180 240 181 while (argc > 0) { 241 if (strcmp(*argv, "up") == 0) { 182 key = index_in_strings(keywords, *argv) + 1; 183 if (key == ARG_up) { 242 184 mask |= IFF_UP; 243 185 flags |= IFF_UP; 244 } else if ( strcmp(*argv, "down") == 0) {186 } else if (key == ARG_down) { 245 187 mask |= IFF_UP; 246 188 flags &= ~IFF_UP; 247 } else if ( strcmp(*argv, "name") == 0) {189 } else if (key == ARG_name) { 248 190 NEXT_ARG(); 249 191 newname = *argv; 250 } else if ( strcmp(*argv, "mtu") == 0) {192 } else if (key == ARG_mtu) { 251 193 NEXT_ARG(); 252 194 if (mtu != -1) … … 254 196 if (get_integer(&mtu, *argv, 0)) 255 197 invarg(*argv, "mtu"); 256 } else if ( strcmp(*argv, "multicast") == 0) {198 } else if (key == ARG_multicast) { 257 199 NEXT_ARG(); 258 200 mask |= IFF_MULTICAST; 259 if (strcmp(*argv, "on") == 0) { 201 key = index_in_strings(keywords, *argv) + 1; 202 if (key == PARM_on) { 260 203 flags |= IFF_MULTICAST; 261 } else if ( strcmp(*argv, "off") == 0) {204 } else if (key == PARM_off) { 262 205 flags &= ~IFF_MULTICAST; 263 206 } else 264 returnon_off("multicast");265 } else if ( strcmp(*argv, "arp") == 0) {207 on_off("multicast"); 208 } else if (key == ARG_arp) { 266 209 NEXT_ARG(); 267 210 mask |= IFF_NOARP; 268 if (strcmp(*argv, "on") == 0) { 211 key = index_in_strings(keywords, *argv) + 1; 212 if (key == PARM_on) { 269 213 flags &= ~IFF_NOARP; 270 } else if ( strcmp(*argv, "off") == 0) {214 } else if (key == PARM_off) { 271 215 flags |= IFF_NOARP; 272 216 } else 273 return on_off("noarp");274 } else if ( strcmp(*argv, "addr") == 0) {217 on_off("arp"); 218 } else if (key == ARG_addr) { 275 219 NEXT_ARG(); 276 220 newaddr = *argv; 277 221 } else { 278 if ( strcmp(*argv, "dev") == 0) {222 if (key == ARG_dev) { 279 223 NEXT_ARG(); 280 224 } … … 287 231 288 232 if (!dev) { 289 bb_error_msg(bb_msg_requires_arg, "\"dev\""); 290 exit(-1); 233 bb_error_msg_and_die(bb_msg_requires_arg, "\"dev\""); 291 234 } 292 235 293 236 if (newaddr || newbrd) { 294 237 halen = get_address(dev, &htype); 295 if (halen < 0)296 return -1;297 238 if (newaddr) { 298 if (parse_address(dev, htype, halen, newaddr, &ifr0) < 0) 299 return -1; 239 parse_address(dev, htype, halen, newaddr, &ifr0); 300 240 } 301 241 if (newbrd) { 302 if (parse_address(dev, htype, halen, newbrd, &ifr1) < 0) 303 return -1; 242 parse_address(dev, htype, halen, newbrd, &ifr1); 304 243 } 305 244 } 306 245 307 246 if (newname && strcmp(dev, newname)) { 308 if (do_changename(dev, newname) < 0) 309 return -1; 247 do_changename(dev, newname); 310 248 dev = newname; 311 249 } 312 250 if (qlen != -1) { 313 if (set_qlen(dev, qlen) < 0) 314 return -1; 251 set_qlen(dev, qlen); 315 252 } 316 253 if (mtu != -1) { 317 if (set_mtu(dev, mtu) < 0) 318 return -1; 254 set_mtu(dev, mtu); 319 255 } 320 256 if (newaddr || newbrd) { 321 257 if (newbrd) { 322 if (set_address(&ifr1, 1) < 0) 323 return -1; 258 set_address(&ifr1, 1); 324 259 } 325 260 if (newaddr) { 326 if (set_address(&ifr0, 0) < 0) 327 return -1; 261 set_address(&ifr0, 0); 328 262 } 329 263 } 330 264 if (mask) 331 returndo_chflags(dev, flags, mask);265 do_chflags(dev, flags, mask); 332 266 return 0; 333 267 } … … 336 270 { 337 271 preferred_family = AF_PACKET; 338 do_link = 1;339 272 return ipaddr_list_or_flush(argc, argv, 0); 340 273 } 341 274 275 /* Return value becomes exitcode. It's okay to not return at all */ 342 276 int do_iplink(int argc, char **argv) 343 277 { 344 if (argc > 0) { 345 if (matches(*argv, "set") == 0) 346 return do_set(argc-1, argv+1); 347 if (matches(*argv, "show") == 0 || 348 matches(*argv, "lst") == 0 || 349 matches(*argv, "list") == 0) 350 return ipaddr_list_link(argc-1, argv+1); 351 } else 278 static const char keywords[] ALIGN1 = 279 "set\0""show\0""lst\0""list\0"; 280 smalluint key; 281 if (argc <= 0) 352 282 return ipaddr_list_link(0, NULL); 353 354 bb_error_msg("Command \"%s\" is unknown.", *argv); 355 exit(-1); 356 } 283 key = index_in_substrings(keywords, *argv) + 1; 284 if (key == 0) 285 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 286 argc--; argv++; 287 if (key == 1) /* set */ 288 return do_set(argc, argv); 289 else /* show, lst, list */ 290 return ipaddr_list_link(argc, argv); 291 }
Note:
See TracChangeset
for help on using the changeset viewer.