Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/libiproute/iplink.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/networking/libiproute/iplink.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * iplink.c "ip link".4 *5 3 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 6 4 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 6 */ 9 10 //#include <sys/ioctl.h>11 //#include <sys/socket.h>12 7 #include <net/if.h> 13 8 #include <net/if_packet.h> … … 19 14 #include "utils.h" 20 15 16 #ifndef IFLA_LINKINFO 17 # define IFLA_LINKINFO 18 18 # define IFLA_INFO_KIND 1 19 #endif 20 21 21 /* taken from linux/sockios.h */ 22 #define SIOCSIFNAME 0x8923 /* set interface name */ 23 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 } 22 #define SIOCSIFNAME 0x8923 /* set interface name */ 29 23 30 24 /* Exits on error */ … … 48 42 int fd; 49 43 50 strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));44 strncpy_IFNAMSIZ(ifr.ifr_name, dev); 51 45 fd = get_ctl_fd(); 52 46 xioctl(fd, SIOCGIFFLAGS, &ifr); … … 65 59 int fd; 66 60 67 strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));68 strncpy (ifr.ifr_newname, newdev, sizeof(ifr.ifr_newname));61 strncpy_IFNAMSIZ(ifr.ifr_name, dev); 62 strncpy_IFNAMSIZ(ifr.ifr_newname, newdev); 69 63 fd = get_ctl_fd(); 70 64 xioctl(fd, SIOCSIFNAME, &ifr); … … 80 74 s = get_ctl_fd(); 81 75 memset(&ifr, 0, sizeof(ifr)); 82 strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));76 strncpy_IFNAMSIZ(ifr.ifr_name, dev); 83 77 ifr.ifr_qlen = qlen; 84 78 xioctl(s, SIOCSIFTXQLEN, &ifr); … … 94 88 s = get_ctl_fd(); 95 89 memset(&ifr, 0, sizeof(ifr)); 96 strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));90 strncpy_IFNAMSIZ(ifr.ifr_name, dev); 97 91 ifr.ifr_mtu = mtu; 98 92 xioctl(s, SIOCSIFMTU, &ifr); … … 111 105 112 106 memset(&ifr, 0, sizeof(ifr)); 113 strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));107 strncpy_IFNAMSIZ(ifr.ifr_name, dev); 114 108 xioctl(s, SIOCGIFINDEX, &ifr); 115 109 … … 119 113 me.sll_protocol = htons(ETH_P_LOOP); 120 114 xbind(s, (struct sockaddr*)&me, sizeof(me)); 121 122 115 alen = sizeof(me); 123 if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) { 124 bb_perror_msg_and_die("getsockname"); 125 } 116 getsockname(s, (struct sockaddr*)&me, &alen); 117 //never happens: 118 //if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) 119 // bb_perror_msg_and_die("getsockname"); 126 120 close(s); 127 121 *htype = me.sll_hatype; … … 135 129 136 130 memset(ifr, 0, sizeof(*ifr)); 137 strncpy (ifr->ifr_name, dev, sizeof(ifr->ifr_name));131 strncpy_IFNAMSIZ(ifr->ifr_name, dev); 138 132 ifr->ifr_hwaddr.sa_family = hatype; 139 alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), 14, lla); 133 134 alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/; 135 alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla); 140 136 if (alen < 0) 141 exit( 1);137 exit(EXIT_FAILURE); 142 138 if (alen != halen) { 143 139 bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen); … … 159 155 160 156 157 static void die_must_be_on_off(const char *msg) NORETURN; 158 static void die_must_be_on_off(const char *msg) 159 { 160 bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg); 161 } 162 161 163 /* Return value becomes exitcode. It's okay to not return at all */ 162 static int do_set( int argc,char **argv)164 static int do_set(char **argv) 163 165 { 164 166 char *dev = NULL; … … 173 175 int htype, halen; 174 176 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 }; 177 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" 178 "arp\0""address\0""dev\0"; 179 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, 180 ARG_arp, ARG_addr, ARG_dev }; 181 static const char str_on_off[] ALIGN1 = "on\0""off\0"; 182 enum { PARM_on = 0, PARM_off }; 179 183 smalluint key; 180 184 181 while (argc > 0) { 182 key = index_in_strings(keywords, *argv) + 1; 185 while (*argv) { 186 /* substring search ensures that e.g. "addr" and "address" 187 * are both accepted */ 188 key = index_in_substrings(keywords, *argv); 183 189 if (key == ARG_up) { 184 190 mask |= IFF_UP; … … 194 200 if (mtu != -1) 195 201 duparg("mtu", *argv); 196 if (get_integer(&mtu, *argv, 0)) 197 invarg(*argv, "mtu"); 198 } else if (key == ARG_multicast) { 199 NEXT_ARG(); 200 mask |= IFF_MULTICAST; 201 key = index_in_strings(keywords, *argv) + 1; 202 if (key == PARM_on) { 203 flags |= IFF_MULTICAST; 204 } else if (key == PARM_off) { 205 flags &= ~IFF_MULTICAST; 206 } else 207 on_off("multicast"); 208 } else if (key == ARG_arp) { 209 NEXT_ARG(); 210 mask |= IFF_NOARP; 211 key = index_in_strings(keywords, *argv) + 1; 212 if (key == PARM_on) { 213 flags &= ~IFF_NOARP; 214 } else if (key == PARM_off) { 215 flags |= IFF_NOARP; 216 } else 217 on_off("arp"); 202 mtu = get_unsigned(*argv, "mtu"); 203 } else if (key == ARG_qlen) { 204 NEXT_ARG(); 205 if (qlen != -1) 206 duparg("qlen", *argv); 207 qlen = get_unsigned(*argv, "qlen"); 218 208 } else if (key == ARG_addr) { 219 209 NEXT_ARG(); 220 210 newaddr = *argv; 221 } else {211 } else if (key >= ARG_dev) { 222 212 if (key == ARG_dev) { 223 213 NEXT_ARG(); … … 226 216 duparg2("dev", *argv); 227 217 dev = *argv; 228 } 229 argc--; argv++; 218 } else { 219 int param; 220 NEXT_ARG(); 221 param = index_in_strings(str_on_off, *argv); 222 if (key == ARG_multicast) { 223 if (param < 0) 224 die_must_be_on_off("multicast"); 225 mask |= IFF_MULTICAST; 226 if (param == PARM_on) 227 flags |= IFF_MULTICAST; 228 else 229 flags &= ~IFF_MULTICAST; 230 } else if (key == ARG_arp) { 231 if (param < 0) 232 die_must_be_on_off("arp"); 233 mask |= IFF_NOARP; 234 if (param == PARM_on) 235 flags &= ~IFF_NOARP; 236 else 237 flags |= IFF_NOARP; 238 } 239 } 240 argv++; 230 241 } 231 242 … … 238 249 if (newaddr) { 239 250 parse_address(dev, htype, halen, newaddr, &ifr0); 251 set_address(&ifr0, 0); 240 252 } 241 253 if (newbrd) { 242 254 parse_address(dev, htype, halen, newbrd, &ifr1); 255 set_address(&ifr1, 1); 243 256 } 244 257 } … … 254 267 set_mtu(dev, mtu); 255 268 } 256 if (newaddr || newbrd) {257 if (newbrd) {258 set_address(&ifr1, 1);259 }260 if (newaddr) {261 set_address(&ifr0, 0);262 }263 }264 269 if (mask) 265 270 do_chflags(dev, flags, mask); … … 267 272 } 268 273 269 static int ipaddr_list_link( int argc,char **argv)274 static int ipaddr_list_link(char **argv) 270 275 { 271 276 preferred_family = AF_PACKET; 272 return ipaddr_list_or_flush(argc, argv, 0); 273 } 274 277 return ipaddr_list_or_flush(argv, 0); 278 } 279 280 #ifndef NLMSG_TAIL 281 #define NLMSG_TAIL(nmsg) \ 282 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 283 #endif 275 284 /* Return value becomes exitcode. It's okay to not return at all */ 276 int do_iplink(int argc, char **argv)285 static int do_change(char **argv, const unsigned rtm) 277 286 { 278 287 static const char keywords[] ALIGN1 = 279 "set\0""show\0""lst\0""list\0"; 280 smalluint key; 281 if (argc <= 0) 282 return ipaddr_list_link(0, NULL); 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 } 288 "link\0""name\0""type\0""dev\0"; 289 enum { 290 ARG_link, 291 ARG_name, 292 ARG_type, 293 ARG_dev, 294 }; 295 struct rtnl_handle rth; 296 struct { 297 struct nlmsghdr n; 298 struct ifinfomsg i; 299 char buf[1024]; 300 } req; 301 smalluint arg; 302 char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL; 303 304 memset(&req, 0, sizeof(req)); 305 306 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); 307 req.n.nlmsg_flags = NLM_F_REQUEST; 308 req.n.nlmsg_type = rtm; 309 req.i.ifi_family = preferred_family; 310 if (rtm == RTM_NEWLINK) 311 req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; 312 313 while (*argv) { 314 arg = index_in_substrings(keywords, *argv); 315 if (arg == ARG_link) { 316 NEXT_ARG(); 317 link_str = *argv; 318 } else if (arg == ARG_name) { 319 NEXT_ARG(); 320 name_str = *argv; 321 } else if (arg == ARG_type) { 322 NEXT_ARG(); 323 type_str = *argv; 324 } else { 325 if (arg == ARG_dev) { 326 if (dev_str) 327 duparg(*argv, "dev"); 328 NEXT_ARG(); 329 } 330 dev_str = *argv; 331 } 332 argv++; 333 } 334 xrtnl_open(&rth); 335 ll_init_map(&rth); 336 if (type_str) { 337 struct rtattr *linkinfo = NLMSG_TAIL(&req.n); 338 339 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); 340 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str, 341 strlen(type_str)); 342 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; 343 } 344 if (rtm != RTM_NEWLINK) { 345 if (!dev_str) 346 return 1; /* Need a device to delete */ 347 req.i.ifi_index = xll_name_to_index(dev_str); 348 } else { 349 if (!name_str) 350 name_str = dev_str; 351 if (link_str) { 352 int idx = xll_name_to_index(link_str); 353 addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4); 354 } 355 } 356 if (name_str) { 357 const size_t name_len = strlen(name_str) + 1; 358 if (name_len < 2 || name_len > IFNAMSIZ) 359 invarg(name_str, "name"); 360 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len); 361 } 362 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) 363 return 2; 364 return 0; 365 } 366 367 /* Return value becomes exitcode. It's okay to not return at all */ 368 int FAST_FUNC do_iplink(char **argv) 369 { 370 static const char keywords[] ALIGN1 = 371 "add\0""delete\0""set\0""show\0""lst\0""list\0"; 372 if (*argv) { 373 smalluint key = index_in_substrings(keywords, *argv); 374 if (key > 5) /* invalid argument */ 375 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 376 argv++; 377 if (key <= 1) /* add/delete */ 378 return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK); 379 else if (key == 2) /* set */ 380 return do_set(argv); 381 } 382 /* show, lst, list */ 383 return ipaddr_list_link(argv); 384 }
Note:
See TracChangeset
for help on using the changeset viewer.