Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/libiproute/ipaddress.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/ipaddress.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * ipaddress.c "ip address".3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 * 5 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 6 * 7 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 8 6 * 9 7 * Changes: 10 * 8 * Laszlo Valko <valko@linux.karinthy.hu> 990223: address label must be zero terminated 11 9 */ 12 10 13 //#include <sys/socket.h>14 //#include <sys/ioctl.h>15 11 #include <fnmatch.h> 16 12 #include <net/if.h> … … 21 17 #include "utils.h" 22 18 23 24 typedef struct filter_t { 25 int ifindex; 26 int family; 27 int oneline; 28 int showqueue; 29 inet_prefix pfx; 19 #ifndef IFF_LOWER_UP 20 /* from linux/if.h */ 21 #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ 22 #endif 23 24 struct filter_t { 25 char *label; 26 char *flushb; 27 struct rtnl_handle *rth; 30 28 int scope, scopemask; 31 29 int flags, flagmask; 32 int up;33 char *label;34 int flushed;35 char *flushb;36 30 int flushp; 37 31 int flushe; 38 struct rtnl_handle *rth; 39 } filter_t; 40 41 #define filter (*(filter_t*)&bb_common_bufsiz1) 42 43 44 static void print_link_flags(FILE *fp, unsigned flags, unsigned mdown) 45 { 46 fprintf(fp, "<"); 32 int ifindex; 33 family_t family; 34 smallint showqueue; 35 smallint oneline; 36 smallint up; 37 smallint flushed; 38 inet_prefix pfx; 39 } FIX_ALIASING; 40 typedef struct filter_t filter_t; 41 42 #define G_filter (*(filter_t*)&bb_common_bufsiz1) 43 44 45 static void print_link_flags(unsigned flags, unsigned mdown) 46 { 47 static const int flag_masks[] = { 48 IFF_LOOPBACK, IFF_BROADCAST, IFF_POINTOPOINT, 49 IFF_MULTICAST, IFF_NOARP, IFF_UP, IFF_LOWER_UP }; 50 static const char flag_labels[] ALIGN1 = 51 "LOOPBACK\0""BROADCAST\0""POINTOPOINT\0" 52 "MULTICAST\0""NOARP\0""UP\0""LOWER_UP\0"; 53 54 bb_putchar('<'); 55 if (flags & IFF_UP && !(flags & IFF_RUNNING)) 56 printf("NO-CARRIER,"); 47 57 flags &= ~IFF_RUNNING; 48 #define _PF(f) if (flags&IFF_##f) { \49 flags &= ~IFF_##f; \50 fprintf(fp, #f "%s", flags ? "," : ""); }51 _PF(LOOPBACK);52 _PF(BROADCAST);53 _PF(POINTOPOINT);54 _PF(MULTICAST);55 _PF(NOARP);56 58 #if 0 57 59 _PF(ALLMULTI); … … 65 67 _PF(NOTRAILERS); 66 68 #endif 67 _PF(UP); 68 #undef _PF 69 flags = print_flags_separated(flag_masks, flag_labels, flags, ","); 69 70 if (flags) 70 fprintf(fp,"%x", flags);71 printf("%x", flags); 71 72 if (mdown) 72 fprintf(fp,",M-DOWN");73 fprintf(fp,"> ");73 printf(",M-DOWN"); 74 printf("> "); 74 75 } 75 76 … … 84 85 85 86 memset(&ifr, 0, sizeof(ifr)); 86 strncpy (ifr.ifr_name, name, sizeof(ifr.ifr_name));87 strncpy_IFNAMSIZ(ifr.ifr_name, name); 87 88 if (ioctl_or_warn(s, SIOCGIFTXQLEN, &ifr) < 0) { 88 89 close(s); … … 95 96 } 96 97 97 static int print_linkinfo(struct sockaddr_nl ATTRIBUTE_UNUSED *who, 98 const struct nlmsghdr *n, void ATTRIBUTE_UNUSED *arg) 99 { 100 FILE *fp = (FILE*)arg; 98 static NOINLINE int print_linkinfo(const struct nlmsghdr *n) 99 { 101 100 struct ifinfomsg *ifi = NLMSG_DATA(n); 102 struct rtattr * 101 struct rtattr *tb[IFLA_MAX+1]; 103 102 int len = n->nlmsg_len; 104 unsigned m_flag = 0;105 103 106 104 if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) … … 111 109 return -1; 112 110 113 if ( filter.ifindex && ifi->ifi_index !=filter.ifindex)114 return 0; 115 if ( filter.up && !(ifi->ifi_flags&IFF_UP))111 if (G_filter.ifindex && ifi->ifi_index != G_filter.ifindex) 112 return 0; 113 if (G_filter.up && !(ifi->ifi_flags & IFF_UP)) 116 114 return 0; 117 115 … … 122 120 return -1; 123 121 } 124 if ( filter.label125 && (! filter.family ||filter.family == AF_PACKET)126 && fnmatch( filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)122 if (G_filter.label 123 && (!G_filter.family || G_filter.family == AF_PACKET) 124 && fnmatch(G_filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0) 127 125 ) { 128 126 return 0; … … 130 128 131 129 if (n->nlmsg_type == RTM_DELLINK) 132 fprintf(fp, "Deleted "); 133 134 fprintf(fp, "%d: %s", ifi->ifi_index, 135 tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>"); 136 137 if (tb[IFLA_LINK]) { 138 SPRINT_BUF(b1); 139 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); 140 if (iflink == 0) 141 fprintf(fp, "@NONE: "); 142 else { 143 fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); 144 m_flag = ll_index_to_flags(iflink); 145 m_flag = !(m_flag & IFF_UP); 146 } 147 } else { 148 fprintf(fp, ": "); 149 } 150 print_link_flags(fp, ifi->ifi_flags, m_flag); 130 printf("Deleted "); 131 132 printf("%d: %s", ifi->ifi_index, 133 /*tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>" - we checked tb[IFLA_IFNAME] above*/ 134 (char*)RTA_DATA(tb[IFLA_IFNAME]) 135 ); 136 137 { 138 unsigned m_flag = 0; 139 if (tb[IFLA_LINK]) { 140 SPRINT_BUF(b1); 141 int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); 142 if (iflink == 0) 143 printf("@NONE: "); 144 else { 145 printf("@%s: ", ll_idx_n2a(iflink, b1)); 146 m_flag = ll_index_to_flags(iflink); 147 m_flag = !(m_flag & IFF_UP); 148 } 149 } else { 150 printf(": "); 151 } 152 print_link_flags(ifi->ifi_flags, m_flag); 153 } 151 154 152 155 if (tb[IFLA_MTU]) 153 fprintf(fp,"mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));156 printf("mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); 154 157 if (tb[IFLA_QDISC]) 155 fprintf(fp,"qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));158 printf("qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC])); 156 159 #ifdef IFLA_MASTER 157 160 if (tb[IFLA_MASTER]) { 158 161 SPRINT_BUF(b1); 159 fprintf(fp,"master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));162 printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); 160 163 } 161 164 #endif 162 if (filter.showqueue) 165 if (tb[IFLA_OPERSTATE]) { 166 static const char operstate_labels[] ALIGN1 = 167 "UNKNOWN\0""NOTPRESENT\0""DOWN\0""LOWERLAYERDOWN\0" 168 "TESTING\0""DORMANT\0""UP\0"; 169 printf("state %s ", nth_string(operstate_labels, 170 *(uint8_t *)RTA_DATA(tb[IFLA_OPERSTATE]))); 171 } 172 if (G_filter.showqueue) 163 173 print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME])); 164 174 165 if (! filter.family ||filter.family == AF_PACKET) {175 if (!G_filter.family || G_filter.family == AF_PACKET) { 166 176 SPRINT_BUF(b1); 167 fprintf(fp, "%c link/%s ", _SL_, ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));177 printf("%c link/%s ", _SL_, ll_type_n2a(ifi->ifi_type, b1)); 168 178 169 179 if (tb[IFLA_ADDRESS]) { 170 fp rintf(fp, "%s",ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),180 fputs(ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), 171 181 RTA_PAYLOAD(tb[IFLA_ADDRESS]), 172 182 ifi->ifi_type, 173 b1, sizeof(b1)) );183 b1, sizeof(b1)), stdout); 174 184 } 175 185 if (tb[IFLA_BROADCAST]) { 176 if (ifi->ifi_flags &IFF_POINTOPOINT)177 fprintf(fp," peer ");186 if (ifi->ifi_flags & IFF_POINTOPOINT) 187 printf(" peer "); 178 188 else 179 fprintf(fp," brd ");180 fp rintf(fp, "%s",ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),189 printf(" brd "); 190 fputs(ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]), 181 191 RTA_PAYLOAD(tb[IFLA_BROADCAST]), 182 192 ifi->ifi_type, 183 b1, sizeof(b1)) );184 } 185 } 186 fputc('\n', fp);187 fflush(fp);193 b1, sizeof(b1)), stdout); 194 } 195 } 196 bb_putchar('\n'); 197 /*fflush_all();*/ 188 198 return 0; 189 199 } … … 191 201 static int flush_update(void) 192 202 { 193 if (rtnl_send( filter.rth, filter.flushb,filter.flushp) < 0) {194 bb_perror_msg(" failed tosend flush request");203 if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { 204 bb_perror_msg("can't send flush request"); 195 205 return -1; 196 206 } 197 filter.flushp = 0;207 G_filter.flushp = 0; 198 208 return 0; 199 209 } 200 210 201 static int print_addrinfo(struct sockaddr_nl ATTRIBUTE_UNUSED *who, 202 struct nlmsghdr *n, void ATTRIBUTE_UNUSED *arg) 203 { 204 FILE *fp = (FILE*)arg; 211 static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM, 212 struct nlmsghdr *n, void *arg UNUSED_PARAM) 213 { 205 214 struct ifaddrmsg *ifa = NLMSG_DATA(n); 206 215 int len = n->nlmsg_len; … … 217 226 } 218 227 219 if ( filter.flushb && n->nlmsg_type != RTM_NEWADDR)228 if (G_filter.flushb && n->nlmsg_type != RTM_NEWADDR) 220 229 return 0; 221 230 … … 228 237 rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; 229 238 230 if ( filter.ifindex &&filter.ifindex != ifa->ifa_index)231 return 0; 232 if (( filter.scope^ifa->ifa_scope)&filter.scopemask)233 return 0; 234 if (( filter.flags^ifa->ifa_flags)&filter.flagmask)235 return 0; 236 if ( filter.label) {239 if (G_filter.ifindex && G_filter.ifindex != ifa->ifa_index) 240 return 0; 241 if ((G_filter.scope ^ ifa->ifa_scope) & G_filter.scopemask) 242 return 0; 243 if ((G_filter.flags ^ ifa->ifa_flags) & G_filter.flagmask) 244 return 0; 245 if (G_filter.label) { 237 246 const char *label; 238 247 if (rta_tb[IFA_LABEL]) … … 240 249 else 241 250 label = ll_idx_n2a(ifa->ifa_index, b1); 242 if (fnmatch( filter.label, label, 0) != 0)251 if (fnmatch(G_filter.label, label, 0) != 0) 243 252 return 0; 244 253 } 245 if ( filter.pfx.family) {254 if (G_filter.pfx.family) { 246 255 if (rta_tb[IFA_LOCAL]) { 247 256 inet_prefix dst; … … 249 258 dst.family = ifa->ifa_family; 250 259 memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL])); 251 if (inet_addr_match(&dst, & filter.pfx,filter.pfx.bitlen))260 if (inet_addr_match(&dst, &G_filter.pfx, G_filter.pfx.bitlen)) 252 261 return 0; 253 262 } 254 263 } 255 264 256 if ( filter.flushb) {265 if (G_filter.flushb) { 257 266 struct nlmsghdr *fn; 258 if (NLMSG_ALIGN( filter.flushp) + n->nlmsg_len >filter.flushe) {267 if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) { 259 268 if (flush_update()) 260 269 return -1; 261 270 } 262 fn = (struct nlmsghdr*)( filter.flushb + NLMSG_ALIGN(filter.flushp));271 fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp)); 263 272 memcpy(fn, n, n->nlmsg_len); 264 273 fn->nlmsg_type = RTM_DELADDR; 265 274 fn->nlmsg_flags = NLM_F_REQUEST; 266 fn->nlmsg_seq = ++ filter.rth->seq;267 filter.flushp = (((char*)fn) + n->nlmsg_len) -filter.flushb;268 filter.flushed++;275 fn->nlmsg_seq = ++G_filter.rth->seq; 276 G_filter.flushp = (((char*)fn) + n->nlmsg_len) - G_filter.flushb; 277 G_filter.flushed = 1; 269 278 return 0; 270 279 } 271 280 272 281 if (n->nlmsg_type == RTM_DELADDR) 273 fprintf(fp,"Deleted ");274 275 if ( filter.oneline)276 fprintf(fp,"%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));282 printf("Deleted "); 283 284 if (G_filter.oneline) 285 printf("%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index)); 277 286 if (ifa->ifa_family == AF_INET) 278 fprintf(fp," inet ");287 printf(" inet "); 279 288 else if (ifa->ifa_family == AF_INET6) 280 fprintf(fp," inet6 ");289 printf(" inet6 "); 281 290 else 282 fprintf(fp," family %d ", ifa->ifa_family);291 printf(" family %d ", ifa->ifa_family); 283 292 284 293 if (rta_tb[IFA_LOCAL]) { 285 fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family, 286 RTA_PAYLOAD(rta_tb[IFA_LOCAL]), 294 fputs(rt_addr_n2a(ifa->ifa_family, 287 295 RTA_DATA(rta_tb[IFA_LOCAL]), 288 abuf, sizeof(abuf))); 289 290 if (rta_tb[IFA_ADDRESS] == NULL || 291 memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) { 292 fprintf(fp, "/%d ", ifa->ifa_prefixlen); 296 abuf, sizeof(abuf)), stdout); 297 298 if (rta_tb[IFA_ADDRESS] == NULL 299 || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0 300 ) { 301 printf("/%d ", ifa->ifa_prefixlen); 293 302 } else { 294 fprintf(fp," peer %s/%d ",303 printf(" peer %s/%d ", 295 304 rt_addr_n2a(ifa->ifa_family, 296 RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),297 305 RTA_DATA(rta_tb[IFA_ADDRESS]), 298 306 abuf, sizeof(abuf)), … … 302 310 303 311 if (rta_tb[IFA_BROADCAST]) { 304 fprintf(fp,"brd %s ",312 printf("brd %s ", 305 313 rt_addr_n2a(ifa->ifa_family, 306 RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),307 314 RTA_DATA(rta_tb[IFA_BROADCAST]), 308 315 abuf, sizeof(abuf))); 309 316 } 310 317 if (rta_tb[IFA_ANYCAST]) { 311 fprintf(fp,"any %s ",318 printf("any %s ", 312 319 rt_addr_n2a(ifa->ifa_family, 313 RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),314 320 RTA_DATA(rta_tb[IFA_ANYCAST]), 315 321 abuf, sizeof(abuf))); 316 322 } 317 fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));318 if (ifa->ifa_flags &IFA_F_SECONDARY) {323 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1)); 324 if (ifa->ifa_flags & IFA_F_SECONDARY) { 319 325 ifa->ifa_flags &= ~IFA_F_SECONDARY; 320 fprintf(fp,"secondary ");321 } 322 if (ifa->ifa_flags &IFA_F_TENTATIVE) {326 printf("secondary "); 327 } 328 if (ifa->ifa_flags & IFA_F_TENTATIVE) { 323 329 ifa->ifa_flags &= ~IFA_F_TENTATIVE; 324 fprintf(fp,"tentative ");325 } 326 if (ifa->ifa_flags &IFA_F_DEPRECATED) {330 printf("tentative "); 331 } 332 if (ifa->ifa_flags & IFA_F_DEPRECATED) { 327 333 ifa->ifa_flags &= ~IFA_F_DEPRECATED; 328 fprintf(fp,"deprecated ");329 } 330 if (!(ifa->ifa_flags &IFA_F_PERMANENT)) {331 fprintf(fp,"dynamic ");334 printf("deprecated "); 335 } 336 if (!(ifa->ifa_flags & IFA_F_PERMANENT)) { 337 printf("dynamic "); 332 338 } else 333 339 ifa->ifa_flags &= ~IFA_F_PERMANENT; 334 340 if (ifa->ifa_flags) 335 fprintf(fp,"flags %02x ", ifa->ifa_flags);341 printf("flags %02x ", ifa->ifa_flags); 336 342 if (rta_tb[IFA_LABEL]) 337 fp rintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));343 fputs((char*)RTA_DATA(rta_tb[IFA_LABEL]), stdout); 338 344 if (rta_tb[IFA_CACHEINFO]) { 339 345 struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); 340 346 char buf[128]; 341 fputc(_SL_, fp);347 bb_putchar(_SL_); 342 348 if (ci->ifa_valid == 0xFFFFFFFFU) 343 349 sprintf(buf, "valid_lft forever"); … … 348 354 else 349 355 sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered); 350 fprintf(fp," %s", buf);351 } 352 fputc('\n', fp);353 fflush(fp);356 printf(" %s", buf); 357 } 358 bb_putchar('\n'); 359 /*fflush_all();*/ 354 360 return 0; 355 361 } 356 362 357 363 358 struct nlmsg_list 359 { 364 struct nlmsg_list { 360 365 struct nlmsg_list *next; 361 struct nlmsghdr 366 struct nlmsghdr h; 362 367 }; 363 368 364 static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo , FILE *fp)369 static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo) 365 370 { 366 371 for (; ainfo; ainfo = ainfo->next) { … … 370 375 if (n->nlmsg_type != RTM_NEWADDR) 371 376 continue; 372 373 377 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa))) 374 378 return -1; 375 376 if (ifa->ifa_index != ifindex ||377 (filter.family && filter.family != ifa->ifa_family))379 if (ifa->ifa_index != ifindex 380 || (G_filter.family && G_filter.family != ifa->ifa_family) 381 ) { 378 382 continue; 379 380 print_addrinfo(NULL, n, fp);383 } 384 print_addrinfo(NULL, n, NULL); 381 385 } 382 386 return 0; … … 384 388 385 389 386 static int store_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)390 static int FAST_FUNC store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) 387 391 { 388 392 struct nlmsg_list **linfo = (struct nlmsg_list**)arg; … … 390 394 struct nlmsg_list **lp; 391 395 392 h = malloc(n->nlmsg_len+sizeof(void*)); 393 if (h == NULL) 394 return -1; 396 h = xzalloc(n->nlmsg_len + sizeof(void*)); 395 397 396 398 memcpy(&h->h, n, n->nlmsg_len); 397 h->next = NULL; 398 399 for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */; 399 /*h->next = NULL; - xzalloc did it */ 400 401 for (lp = linfo; *lp; lp = &(*lp)->next) 402 continue; 400 403 *lp = h; 401 404 … … 406 409 static void ipaddr_reset_filter(int _oneline) 407 410 { 408 memset(& filter, 0, sizeof(filter));409 filter.oneline = _oneline;411 memset(&G_filter, 0, sizeof(G_filter)); 412 G_filter.oneline = _oneline; 410 413 } 411 414 412 415 /* Return value becomes exitcode. It's okay to not return at all */ 413 int ipaddr_list_or_flush(int argc,char **argv, int flush)416 int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) 414 417 { 415 418 static const char option[] ALIGN1 = "to\0""scope\0""up\0""label\0""dev\0"; … … 423 426 424 427 ipaddr_reset_filter(oneline); 425 filter.showqueue = 1;426 427 if ( filter.family == AF_UNSPEC)428 filter.family = preferred_family;428 G_filter.showqueue = 1; 429 430 if (G_filter.family == AF_UNSPEC) 431 G_filter.family = preferred_family; 429 432 430 433 if (flush) { 431 if ( argc <= 0) {434 if (!*argv) { 432 435 bb_error_msg_and_die(bb_msg_requires_arg, "flush"); 433 436 } 434 if (filter.family == AF_PACKET) { 435 bb_error_msg_and_die("cannot flush link addresses"); 436 } 437 } 438 439 while (argc > 0) { 440 const int option_num = index_in_strings(option, *argv); 441 switch (option_num) { 442 case 0: /* to */ 437 if (G_filter.family == AF_PACKET) { 438 bb_error_msg_and_die("can't flush link addresses"); 439 } 440 } 441 442 while (*argv) { 443 const smalluint key = index_in_strings(option, *argv); 444 if (key == 0) { /* to */ 445 NEXT_ARG(); 446 get_prefix(&G_filter.pfx, *argv, G_filter.family); 447 if (G_filter.family == AF_UNSPEC) { 448 G_filter.family = G_filter.pfx.family; 449 } 450 } else if (key == 1) { /* scope */ 451 uint32_t scope = 0; 452 NEXT_ARG(); 453 G_filter.scopemask = -1; 454 if (rtnl_rtscope_a2n(&scope, *argv)) { 455 if (strcmp(*argv, "all") != 0) { 456 invarg(*argv, "scope"); 457 } 458 scope = RT_SCOPE_NOWHERE; 459 G_filter.scopemask = 0; 460 } 461 G_filter.scope = scope; 462 } else if (key == 2) { /* up */ 463 G_filter.up = 1; 464 } else if (key == 3) { /* label */ 465 NEXT_ARG(); 466 G_filter.label = *argv; 467 } else { 468 if (key == 4) /* dev */ 443 469 NEXT_ARG(); 444 get_prefix(&filter.pfx, *argv, filter.family); 445 if (filter.family == AF_UNSPEC) { 446 filter.family = filter.pfx.family; 447 } 448 break; 449 case 1: /* scope */ 450 { 451 uint32_t scope = 0; 452 NEXT_ARG(); 453 filter.scopemask = -1; 454 if (rtnl_rtscope_a2n(&scope, *argv)) { 455 if (strcmp(*argv, "all") != 0) { 456 invarg(*argv, "scope"); 457 } 458 scope = RT_SCOPE_NOWHERE; 459 filter.scopemask = 0; 460 } 461 filter.scope = scope; 462 break; 463 } 464 case 2: /* up */ 465 filter.up = 1; 466 break; 467 case 3: /* label */ 468 NEXT_ARG(); 469 filter.label = *argv; 470 break; 471 case 4: /* dev */ 472 NEXT_ARG(); 473 default: 474 if (filter_dev) { 475 duparg2("dev", *argv); 476 } 477 filter_dev = *argv; 470 if (filter_dev) 471 duparg2("dev", *argv); 472 filter_dev = *argv; 478 473 } 479 474 argv++; 480 argc--;481 475 } 482 476 … … 487 481 488 482 if (filter_dev) { 489 filter.ifindex = xll_name_to_index(filter_dev);483 G_filter.ifindex = xll_name_to_index(filter_dev); 490 484 } 491 485 … … 493 487 char flushb[4096-512]; 494 488 495 filter.flushb = flushb;496 filter.flushp = 0;497 filter.flushe = sizeof(flushb);498 filter.rth = &rth;489 G_filter.flushb = flushb; 490 G_filter.flushp = 0; 491 G_filter.flushe = sizeof(flushb); 492 G_filter.rth = &rth; 499 493 500 494 for (;;) { 501 xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR);502 filter.flushed = 0;503 xrtnl_dump_filter(&rth, print_addrinfo, stdout);504 if ( filter.flushed == 0) {495 xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETADDR); 496 G_filter.flushed = 0; 497 xrtnl_dump_filter(&rth, print_addrinfo, NULL); 498 if (G_filter.flushed == 0) { 505 499 return 0; 506 500 } 507 if (flush_update() < 0) 501 if (flush_update() < 0) { 508 502 return 1; 509 } 510 } 511 512 if (filter.family != AF_PACKET) { 513 xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR); 503 } 504 } 505 } 506 507 if (G_filter.family != AF_PACKET) { 508 xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETADDR); 514 509 xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); 515 510 } 516 511 517 512 518 if ( filter.family &&filter.family != AF_PACKET) {513 if (G_filter.family && G_filter.family != AF_PACKET) { 519 514 struct nlmsg_list **lp; 520 lp =&linfo;521 522 if ( filter.oneline)515 lp = &linfo; 516 517 if (G_filter.oneline) 523 518 no_link = 1; 524 519 525 while ((l =*lp)!=NULL) {520 while ((l = *lp) != NULL) { 526 521 int ok = 0; 527 522 struct ifinfomsg *ifi = NLMSG_DATA(&l->h); 528 523 struct nlmsg_list *a; 529 524 530 for (a =ainfo; a; a=a->next) {525 for (a = ainfo; a; a = a->next) { 531 526 struct nlmsghdr *n = &a->h; 532 527 struct ifaddrmsg *ifa = NLMSG_DATA(n); 533 528 534 if (ifa->ifa_index != ifi->ifi_index || 535 (filter.family && filter.family != ifa->ifa_family)) 529 if (ifa->ifa_index != ifi->ifi_index 530 || (G_filter.family && G_filter.family != ifa->ifa_family) 531 ) { 536 532 continue; 537 if ((filter.scope^ifa->ifa_scope)&filter.scopemask) 533 } 534 if ((G_filter.scope ^ ifa->ifa_scope) & G_filter.scopemask) 538 535 continue; 539 if (( filter.flags^ifa->ifa_flags)&filter.flagmask)536 if ((G_filter.flags ^ ifa->ifa_flags) & G_filter.flagmask) 540 537 continue; 541 if ( filter.pfx.family ||filter.label) {538 if (G_filter.pfx.family || G_filter.label) { 542 539 struct rtattr *tb[IFA_MAX+1]; 543 540 memset(tb, 0, sizeof(tb)); … … 546 543 tb[IFA_LOCAL] = tb[IFA_ADDRESS]; 547 544 548 if ( filter.pfx.family && tb[IFA_LOCAL]) {545 if (G_filter.pfx.family && tb[IFA_LOCAL]) { 549 546 inet_prefix dst; 550 547 memset(&dst, 0, sizeof(dst)); 551 548 dst.family = ifa->ifa_family; 552 549 memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); 553 if (inet_addr_match(&dst, & filter.pfx,filter.pfx.bitlen))550 if (inet_addr_match(&dst, &G_filter.pfx, G_filter.pfx.bitlen)) 554 551 continue; 555 552 } 556 if ( filter.label) {553 if (G_filter.label) { 557 554 SPRINT_BUF(b1); 558 555 const char *label; … … 561 558 else 562 559 label = ll_idx_n2a(ifa->ifa_index, b1); 563 if (fnmatch( filter.label, label, 0) != 0)560 if (fnmatch(G_filter.label, label, 0) != 0) 564 561 continue; 565 562 } … … 577 574 578 575 for (l = linfo; l; l = l->next) { 579 if (no_link || print_linkinfo( NULL, &l->h, stdout) == 0) {576 if (no_link || print_linkinfo(&l->h) == 0) { 580 577 struct ifinfomsg *ifi = NLMSG_DATA(&l->h); 581 if (filter.family != AF_PACKET) 582 print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); 583 } 584 fflush(stdout); /* why? */ 578 if (G_filter.family != AF_PACKET) 579 print_selected_addrinfo(ifi->ifi_index, ainfo); 580 } 585 581 } 586 582 … … 598 594 599 595 /* Return value becomes exitcode. It's okay to not return at all */ 600 static int ipaddr_modify(int cmd, int argc,char **argv)596 static int ipaddr_modify(int cmd, char **argv) 601 597 { 602 598 static const char option[] ALIGN1 = … … 626 622 req.ifa.ifa_family = preferred_family; 627 623 628 while (argc > 0) { 629 const int option_num = index_in_strings(option, *argv); 630 switch (option_num) { 631 case 0: /* peer */ 632 case 1: /* remote */ 624 while (*argv) { 625 const smalluint arg = index_in_strings(option, *argv); 626 if (arg <= 1) { /* peer, remote */ 627 NEXT_ARG(); 628 629 if (peer_len) { 630 duparg("peer", *argv); 631 } 632 get_prefix(&peer, *argv, req.ifa.ifa_family); 633 peer_len = peer.bytelen; 634 if (req.ifa.ifa_family == AF_UNSPEC) { 635 req.ifa.ifa_family = peer.family; 636 } 637 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen); 638 req.ifa.ifa_prefixlen = peer.bitlen; 639 } else if (arg <= 3) { /* broadcast, brd */ 640 inet_prefix addr; 641 NEXT_ARG(); 642 if (brd_len) { 643 duparg("broadcast", *argv); 644 } 645 if (LONE_CHAR(*argv, '+')) { 646 brd_len = -1; 647 } else if (LONE_DASH(*argv)) { 648 brd_len = -2; 649 } else { 650 get_addr(&addr, *argv, req.ifa.ifa_family); 651 if (req.ifa.ifa_family == AF_UNSPEC) 652 req.ifa.ifa_family = addr.family; 653 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); 654 brd_len = addr.bytelen; 655 } 656 } else if (arg == 4) { /* anycast */ 657 inet_prefix addr; 658 NEXT_ARG(); 659 if (any_len) { 660 duparg("anycast", *argv); 661 } 662 get_addr(&addr, *argv, req.ifa.ifa_family); 663 if (req.ifa.ifa_family == AF_UNSPEC) { 664 req.ifa.ifa_family = addr.family; 665 } 666 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); 667 any_len = addr.bytelen; 668 } else if (arg == 5) { /* scope */ 669 uint32_t scope = 0; 670 NEXT_ARG(); 671 if (rtnl_rtscope_a2n(&scope, *argv)) { 672 invarg(*argv, "scope"); 673 } 674 req.ifa.ifa_scope = scope; 675 scoped = 1; 676 } else if (arg == 6) { /* dev */ 677 NEXT_ARG(); 678 d = *argv; 679 } else if (arg == 7) { /* label */ 680 NEXT_ARG(); 681 l = *argv; 682 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1); 683 } else { 684 if (arg == 8) /* local */ 633 685 NEXT_ARG(); 634 635 if (peer_len) { 636 duparg("peer", *argv); 637 } 638 get_prefix(&peer, *argv, req.ifa.ifa_family); 639 peer_len = peer.bytelen; 640 if (req.ifa.ifa_family == AF_UNSPEC) { 641 req.ifa.ifa_family = peer.family; 642 } 643 addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen); 644 req.ifa.ifa_prefixlen = peer.bitlen; 645 break; 646 case 2: /* broadcast */ 647 case 3: /* brd */ 648 { 649 inet_prefix addr; 650 NEXT_ARG(); 651 if (brd_len) { 652 duparg("broadcast", *argv); 653 } 654 if (LONE_CHAR(*argv, '+')) { 655 brd_len = -1; 656 } 657 else if (LONE_DASH(*argv)) { 658 brd_len = -2; 659 } else { 660 get_addr(&addr, *argv, req.ifa.ifa_family); 661 if (req.ifa.ifa_family == AF_UNSPEC) 662 req.ifa.ifa_family = addr.family; 663 addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); 664 brd_len = addr.bytelen; 665 } 666 break; 667 } 668 case 4: /* anycast */ 669 { 670 inet_prefix addr; 671 NEXT_ARG(); 672 if (any_len) { 673 duparg("anycast", *argv); 674 } 675 get_addr(&addr, *argv, req.ifa.ifa_family); 676 if (req.ifa.ifa_family == AF_UNSPEC) { 677 req.ifa.ifa_family = addr.family; 678 } 679 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); 680 any_len = addr.bytelen; 681 break; 682 } 683 case 5: /* scope */ 684 { 685 uint32_t scope = 0; 686 NEXT_ARG(); 687 if (rtnl_rtscope_a2n(&scope, *argv)) { 688 invarg(*argv, "scope"); 689 } 690 req.ifa.ifa_scope = scope; 691 scoped = 1; 692 break; 693 } 694 case 6: /* dev */ 695 NEXT_ARG(); 696 d = *argv; 697 break; 698 case 7: /* label */ 699 NEXT_ARG(); 700 l = *argv; 701 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1); 702 break; 703 case 8: /* local */ 704 NEXT_ARG(); 705 default: 706 if (local_len) { 707 duparg2("local", *argv); 708 } 709 get_prefix(&lcl, *argv, req.ifa.ifa_family); 710 if (req.ifa.ifa_family == AF_UNSPEC) { 711 req.ifa.ifa_family = lcl.family; 712 } 713 addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); 714 local_len = lcl.bytelen; 715 } 716 argc--; 686 if (local_len) { 687 duparg2("local", *argv); 688 } 689 get_prefix(&lcl, *argv, req.ifa.ifa_family); 690 if (req.ifa.ifa_family == AF_UNSPEC) { 691 req.ifa.ifa_family = lcl.family; 692 } 693 addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); 694 local_len = lcl.bytelen; 695 } 717 696 argv++; 718 697 } 719 698 720 if ( d == NULL) {721 bb_error_msg(bb_msg_requires_arg,"\"dev\"");722 return -1;699 if (!d) { 700 /* There was no "dev IFACE", but we need that */ 701 bb_error_msg_and_die("need \"dev IFACE\""); 723 702 } 724 703 if (l && strncmp(d, l, strlen(d)) != 0) { … … 767 746 768 747 /* Return value becomes exitcode. It's okay to not return at all */ 769 int do_ipaddr(int argc,char **argv)748 int FAST_FUNC do_ipaddr(char **argv) 770 749 { 771 750 static const char commands[] ALIGN1 = 772 751 "add\0""delete\0""list\0""show\0""lst\0""flush\0"; 773 774 int command_num = 2; /* default command is list */ 775 752 smalluint cmd = 2; 776 753 if (*argv) { 777 command_num = index_in_substrings(commands, *argv); 778 } 779 if (command_num < 0 || command_num > 5) 780 bb_error_msg_and_die("unknown command %s", *argv); 781 --argc; 782 ++argv; 783 if (command_num == 0) /* add */ 784 return ipaddr_modify(RTM_NEWADDR, argc, argv); 785 else if (command_num == 1) /* delete */ 786 return ipaddr_modify(RTM_DELADDR, argc, argv); 787 else if (command_num == 5) /* flush */ 788 return ipaddr_list_or_flush(argc, argv, 1); 789 else /* 2 == list, 3 == show, 4 == lst */ 790 return ipaddr_list_or_flush(argc, argv, 0); 791 } 754 cmd = index_in_substrings(commands, *argv); 755 if (cmd > 5) 756 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 757 argv++; 758 if (cmd <= 1) 759 return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv); 760 } 761 /* 2 == list, 3 == show, 4 == lst */ 762 return ipaddr_list_or_flush(argv, cmd == 5); 763 }
Note:
See TracChangeset
for help on using the changeset viewer.