Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/libiproute/iproute.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/iproute.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * iproute.c "ip route".3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 * 5 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 6 * 7 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 8 * 5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 9 6 * 10 7 * Changes: 11 8 * 12 * Rani Assaf <rani@magic.metawire.com> 980929: 9 * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses 13 10 * Kunihiro Ishiguro <kunihiro@zebra.org> 001102: rtnh_ifindex was not initialized 14 11 */ 15 12 16 #include "ip_common.h" 13 #include "ip_common.h" /* #include "libbb.h" is inside */ 17 14 #include "rt_names.h" 18 15 #include "utils.h" … … 23 20 24 21 25 typedefstruct filter_t {22 struct filter_t { 26 23 int tb; 27 int flushed;24 smallint flushed; 28 25 char *flushb; 29 26 int flushp; 30 27 int flushe; 31 28 struct rtnl_handle *rth; 32 int protocol, protocolmask; 33 int scope, scopemask; 34 int type, typemask; 35 int tos, tosmask; 29 //int protocol, protocolmask; - write-only fields?! 30 //int scope, scopemask; - unused 31 //int type; - read-only 32 //int typemask; - unused 33 //int tos, tosmask; - unused 36 34 int iif, iifmask; 37 35 int oif, oifmask; 38 int realm, realmmask;39 inet_prefix rprefsrc;36 //int realm, realmmask; - unused 37 //inet_prefix rprefsrc; - read-only 40 38 inet_prefix rvia; 41 39 inet_prefix rdst; … … 43 41 inet_prefix rsrc; 44 42 inet_prefix msrc; 45 } filter_t; 46 47 #define filter (*(filter_t*)&bb_common_bufsiz1) 43 } FIX_ALIASING; 44 typedef struct filter_t filter_t; 45 46 #define G_filter (*(filter_t*)&bb_common_bufsiz1) 48 47 49 48 static int flush_update(void) 50 49 { 51 if (rtnl_send( filter.rth, filter.flushb,filter.flushp) < 0) {52 bb_perror_msg(" failed tosend flush request");50 if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { 51 bb_perror_msg("can't send flush request"); 53 52 return -1; 54 53 } 55 filter.flushp = 0;54 G_filter.flushp = 0; 56 55 return 0; 57 56 } … … 65 64 return hz_internal; 66 65 67 fp = fopen ("/proc/net/psched", "r");66 fp = fopen_for_read("/proc/net/psched"); 68 67 if (fp) { 69 68 unsigned nom, denom; … … 79 78 } 80 79 81 static int print_route(struct sockaddr_nl *who ATTRIBUTE_UNUSED,82 struct nlmsghdr *n, void *arg )80 static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, 81 struct nlmsghdr *n, void *arg UNUSED_PARAM) 83 82 { 84 FILE *fp = (FILE*)arg;85 83 struct rtmsg *r = NLMSG_DATA(n); 86 84 int len = n->nlmsg_len; … … 92 90 SPRINT_BUF(b1); 93 91 94 95 92 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) { 96 93 fprintf(stderr, "Not a route: %08x %08x %08x\n", … … 98 95 return 0; 99 96 } 100 if ( filter.flushb && n->nlmsg_type != RTM_NEWROUTE)97 if (G_filter.flushb && n->nlmsg_type != RTM_NEWROUTE) 101 98 return 0; 102 99 len -= NLMSG_LENGTH(sizeof(*r)); … … 110 107 111 108 if (r->rtm_family == AF_INET6) { 112 if ( filter.tb) {113 if ( filter.tb < 0) {114 if (!(r->rtm_flags &RTM_F_CLONED)) {109 if (G_filter.tb) { 110 if (G_filter.tb < 0) { 111 if (!(r->rtm_flags & RTM_F_CLONED)) { 115 112 return 0; 116 113 } 117 114 } else { 118 if (r->rtm_flags &RTM_F_CLONED) {115 if (r->rtm_flags & RTM_F_CLONED) { 119 116 return 0; 120 117 } 121 if ( filter.tb == RT_TABLE_LOCAL) {118 if (G_filter.tb == RT_TABLE_LOCAL) { 122 119 if (r->rtm_type != RTN_LOCAL) { 123 120 return 0; 124 121 } 125 } else if ( filter.tb == RT_TABLE_MAIN) {122 } else if (G_filter.tb == RT_TABLE_MAIN) { 126 123 if (r->rtm_type == RTN_LOCAL) { 127 124 return 0; … … 133 130 } 134 131 } else { 135 if ( filter.tb > 0 &&filter.tb != r->rtm_table) {132 if (G_filter.tb > 0 && G_filter.tb != r->rtm_table) { 136 133 return 0; 137 134 } 138 135 } 139 if (filter.rdst.family && 140 (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len)) { 141 return 0; 142 } 143 if (filter.mdst.family && 144 (r->rtm_family != filter.mdst.family || 145 (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len))) { 146 return 0; 147 } 148 if (filter.rsrc.family && 149 (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len)) { 150 return 0; 151 } 152 if (filter.msrc.family && 153 (r->rtm_family != filter.msrc.family || 154 (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len))) { 136 if (G_filter.rdst.family 137 && (r->rtm_family != G_filter.rdst.family || G_filter.rdst.bitlen > r->rtm_dst_len) 138 ) { 139 return 0; 140 } 141 if (G_filter.mdst.family 142 && (r->rtm_family != G_filter.mdst.family 143 || (G_filter.mdst.bitlen >= 0 && G_filter.mdst.bitlen < r->rtm_dst_len) 144 ) 145 ) { 146 return 0; 147 } 148 if (G_filter.rsrc.family 149 && (r->rtm_family != G_filter.rsrc.family || G_filter.rsrc.bitlen > r->rtm_src_len) 150 ) { 151 return 0; 152 } 153 if (G_filter.msrc.family 154 && (r->rtm_family != G_filter.msrc.family 155 || (G_filter.msrc.bitlen >= 0 && G_filter.msrc.bitlen < r->rtm_src_len) 156 ) 157 ) { 155 158 return 0; 156 159 } … … 159 162 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); 160 163 161 if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen)) 162 return 0; 163 if (filter.mdst.family && filter.mdst.bitlen >= 0 && 164 inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len)) 165 return 0; 166 167 if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen)) 168 return 0; 169 if (filter.msrc.family && filter.msrc.bitlen >= 0 && 170 inet_addr_match(&src, &filter.msrc, r->rtm_src_len)) 171 return 0; 172 173 if (filter.flushb && 174 r->rtm_family == AF_INET6 && 175 r->rtm_dst_len == 0 && 176 r->rtm_type == RTN_UNREACHABLE && 177 tb[RTA_PRIORITY] && 178 *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1) 179 return 0; 180 181 if (filter.flushb) { 164 if (G_filter.rdst.family 165 && inet_addr_match(&dst, &G_filter.rdst, G_filter.rdst.bitlen) 166 ) { 167 return 0; 168 } 169 if (G_filter.mdst.family 170 && G_filter.mdst.bitlen >= 0 171 && inet_addr_match(&dst, &G_filter.mdst, r->rtm_dst_len) 172 ) { 173 return 0; 174 } 175 if (G_filter.rsrc.family 176 && inet_addr_match(&src, &G_filter.rsrc, G_filter.rsrc.bitlen) 177 ) { 178 return 0; 179 } 180 if (G_filter.msrc.family && G_filter.msrc.bitlen >= 0 181 && inet_addr_match(&src, &G_filter.msrc, r->rtm_src_len) 182 ) { 183 return 0; 184 } 185 if (G_filter.flushb 186 && r->rtm_family == AF_INET6 187 && r->rtm_dst_len == 0 188 && r->rtm_type == RTN_UNREACHABLE 189 && tb[RTA_PRIORITY] 190 && *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1 191 ) { 192 return 0; 193 } 194 195 if (G_filter.flushb) { 182 196 struct nlmsghdr *fn; 183 if (NLMSG_ALIGN( filter.flushp) + n->nlmsg_len >filter.flushe) {197 if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) { 184 198 if (flush_update()) 185 199 bb_error_msg_and_die("flush"); 186 200 } 187 fn = (struct nlmsghdr*)( filter.flushb + NLMSG_ALIGN(filter.flushp));201 fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp)); 188 202 memcpy(fn, n, n->nlmsg_len); 189 203 fn->nlmsg_type = RTM_DELROUTE; 190 204 fn->nlmsg_flags = NLM_F_REQUEST; 191 fn->nlmsg_seq = ++ filter.rth->seq;192 filter.flushp = (((char*)fn) + n->nlmsg_len) -filter.flushb;193 filter.flushed++;205 fn->nlmsg_seq = ++G_filter.rth->seq; 206 G_filter.flushp = (((char*)fn) + n->nlmsg_len) - G_filter.flushb; 207 G_filter.flushed = 1; 194 208 return 0; 195 209 } 196 210 197 211 if (n->nlmsg_type == RTM_DELROUTE) { 198 fprintf(fp,"Deleted ");199 } 200 if (r->rtm_type != RTN_UNICAST && !filter.type) {201 fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));212 printf("Deleted "); 213 } 214 if (r->rtm_type != RTN_UNICAST /* && !G_filter.type - always 0 */) { 215 printf("%s ", rtnl_rtntype_n2a(r->rtm_type, b1)); 202 216 } 203 217 204 218 if (tb[RTA_DST]) { 205 219 if (r->rtm_dst_len != host_len) { 206 fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family, 207 RTA_PAYLOAD(tb[RTA_DST]), 208 RTA_DATA(tb[RTA_DST]), 209 abuf, sizeof(abuf)), 210 r->rtm_dst_len 211 ); 220 printf("%s/%u ", rt_addr_n2a(r->rtm_family, 221 RTA_DATA(tb[RTA_DST]), 222 abuf, sizeof(abuf)), 223 r->rtm_dst_len 224 ); 212 225 } else { 213 fprintf(fp,"%s ", format_host(r->rtm_family,214 215 216 217 );226 printf("%s ", format_host(r->rtm_family, 227 RTA_PAYLOAD(tb[RTA_DST]), 228 RTA_DATA(tb[RTA_DST]), 229 abuf, sizeof(abuf)) 230 ); 218 231 } 219 232 } else if (r->rtm_dst_len) { 220 fprintf(fp,"0/%d ", r->rtm_dst_len);233 printf("0/%d ", r->rtm_dst_len); 221 234 } else { 222 fprintf(fp,"default ");235 printf("default "); 223 236 } 224 237 if (tb[RTA_SRC]) { 225 238 if (r->rtm_src_len != host_len) { 226 fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family, 227 RTA_PAYLOAD(tb[RTA_SRC]), 228 RTA_DATA(tb[RTA_SRC]), 229 abuf, sizeof(abuf)), 230 r->rtm_src_len 231 ); 239 printf("from %s/%u ", rt_addr_n2a(r->rtm_family, 240 RTA_DATA(tb[RTA_SRC]), 241 abuf, sizeof(abuf)), 242 r->rtm_src_len 243 ); 232 244 } else { 233 fprintf(fp,"from %s ", format_host(r->rtm_family,234 235 236 237 );245 printf("from %s ", format_host(r->rtm_family, 246 RTA_PAYLOAD(tb[RTA_SRC]), 247 RTA_DATA(tb[RTA_SRC]), 248 abuf, sizeof(abuf)) 249 ); 238 250 } 239 251 } else if (r->rtm_src_len) { 240 fprintf(fp, "from 0/%u ", r->rtm_src_len); 241 } 242 if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) { 243 fprintf(fp, "via %s ", 244 format_host(r->rtm_family, 245 RTA_PAYLOAD(tb[RTA_GATEWAY]), 246 RTA_DATA(tb[RTA_GATEWAY]), 247 abuf, sizeof(abuf))); 248 } 249 if (tb[RTA_OIF] && filter.oifmask != -1) { 250 fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); 251 } 252 253 if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) { 252 printf("from 0/%u ", r->rtm_src_len); 253 } 254 if (tb[RTA_GATEWAY] && G_filter.rvia.bitlen != host_len) { 255 printf("via %s ", format_host(r->rtm_family, 256 RTA_PAYLOAD(tb[RTA_GATEWAY]), 257 RTA_DATA(tb[RTA_GATEWAY]), 258 abuf, sizeof(abuf))); 259 } 260 if (tb[RTA_OIF] && G_filter.oifmask != -1) { 261 printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); 262 } 263 264 if (tb[RTA_PREFSRC] && /*G_filter.rprefsrc.bitlen - always 0*/ 0 != host_len) { 254 265 /* Do not use format_host(). It is our local addr 255 266 and symbolic name will not be useful. 256 267 */ 257 fprintf(fp, " src %s ", 258 rt_addr_n2a(r->rtm_family, 259 RTA_PAYLOAD(tb[RTA_PREFSRC]), 260 RTA_DATA(tb[RTA_PREFSRC]), 261 abuf, sizeof(abuf))); 268 printf(" src %s ", rt_addr_n2a(r->rtm_family, 269 RTA_DATA(tb[RTA_PREFSRC]), 270 abuf, sizeof(abuf))); 262 271 } 263 272 if (tb[RTA_PRIORITY]) { 264 fprintf(fp," metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY]));273 printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY])); 265 274 } 266 275 if (r->rtm_family == AF_INET6) { … … 271 280 if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) { 272 281 if (r->rtm_flags & RTM_F_CLONED) { 273 fprintf(fp,"%c cache ", _SL_);282 printf("%c cache ", _SL_); 274 283 } 275 284 if (ci->rta_expires) { 276 fprintf(fp," expires %dsec", ci->rta_expires / get_hz());285 printf(" expires %dsec", ci->rta_expires / get_hz()); 277 286 } 278 287 if (ci->rta_error != 0) { 279 fprintf(fp," error %d", ci->rta_error);288 printf(" error %d", ci->rta_error); 280 289 } 281 290 } else if (ci) { 282 291 if (ci->rta_error != 0) 283 fprintf(fp, " error %d", ci->rta_error); 284 } 285 } 286 if (tb[RTA_IIF] && filter.iifmask != -1) { 287 fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF]))); 288 } 289 fputc('\n', fp); 290 fflush(fp); 292 printf(" error %d", ci->rta_error); 293 } 294 } 295 if (tb[RTA_IIF] && G_filter.iifmask != -1) { 296 printf(" iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF]))); 297 } 298 bb_putchar('\n'); 291 299 return 0; 292 300 } 293 301 294 302 /* Return value becomes exitcode. It's okay to not return at all */ 295 static int iproute_modify(int cmd, unsigned flags, int argc,char **argv)303 static int iproute_modify(int cmd, unsigned flags, char **argv) 296 304 { 297 305 static const char keywords[] ALIGN1 = 298 "src\0""via\0""mtu\0""lock\0""protocol\0" USE_FEATURE_IP_RULE("table\0")299 "dev\0""oif\0""to\0" ;306 "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0") 307 "dev\0""oif\0""to\0""metric\0"; 300 308 enum { 301 309 ARG_src, … … 303 311 ARG_mtu, PARM_lock, 304 312 ARG_protocol, 305 USE_FEATURE_IP_RULE(ARG_table,)313 IF_FEATURE_IP_RULE(ARG_table,) 306 314 ARG_dev, 307 315 ARG_oif, 308 ARG_to 316 ARG_to, 317 ARG_metric, 309 318 }; 310 319 enum { … … 316 325 struct rtnl_handle rth; 317 326 struct { 318 struct nlmsghdr 319 struct rtmsg 320 char 327 struct nlmsghdr n; 328 struct rtmsg r; 329 char buf[1024]; 321 330 } req; 322 331 char mxbuf[256]; … … 330 339 331 340 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 332 req.n.nlmsg_flags = NLM_F_REQUEST |flags;341 req.n.nlmsg_flags = NLM_F_REQUEST | flags; 333 342 req.n.nlmsg_type = cmd; 334 343 req.r.rtm_family = preferred_family; 335 req.r.rtm_table = RT_TABLE_MAIN; 336 req.r.rtm_scope = RT_SCOPE_NOWHERE; 344 if (RT_TABLE_MAIN) /* if it is zero, memset already did it */ 345 req.r.rtm_table = RT_TABLE_MAIN; 346 if (RT_SCOPE_NOWHERE) 347 req.r.rtm_scope = RT_SCOPE_NOWHERE; 337 348 338 349 if (cmd != RTM_DELROUTE) { … … 345 356 mxrta->rta_len = RTA_LENGTH(0); 346 357 347 while ( argc > 0) {358 while (*argv) { 348 359 arg = index_in_substrings(keywords, *argv); 349 360 if (arg == ARG_src) { … … 367 378 NEXT_ARG(); 368 379 if (index_in_strings(keywords, *argv) == PARM_lock) { 369 mxlock |= (1<<RTAX_MTU); 370 NEXT_ARG(); 371 } 372 if (get_unsigned(&mtu, *argv, 0)) 373 invarg(*argv, "mtu"); 380 mxlock |= (1 << RTAX_MTU); 381 NEXT_ARG(); 382 } 383 mtu = get_unsigned(*argv, "mtu"); 374 384 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); 375 385 } else if (arg == ARG_protocol) { … … 391 401 NEXT_ARG(); 392 402 d = *argv; 403 } else if (arg == ARG_metric) { 404 uint32_t metric; 405 NEXT_ARG(); 406 metric = get_u32(*argv, "metric"); 407 addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); 393 408 } else { 394 409 int type; … … 399 414 } 400 415 if ((**argv < '0' || **argv > '9') 401 416 && rtnl_rtntype_a2n(&type, *argv) == 0) { 402 417 NEXT_ARG(); 403 418 req.r.rtm_type = type; … … 418 433 } 419 434 } 420 arg c--; argv++;435 argv++; 421 436 } 422 437 … … 443 458 if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT) 444 459 req.r.rtm_scope = RT_SCOPE_HOST; 445 else if (req.r.rtm_type == RTN_BROADCAST || 446 req.r.rtm_type == RTN_MULTICAST || 447 req.r.rtm_type == RTN_ANYCAST) 460 else 461 if (req.r.rtm_type == RTN_BROADCAST 462 || req.r.rtm_type == RTN_MULTICAST 463 || req.r.rtm_type == RTN_ANYCAST 464 ) { 448 465 req.r.rtm_scope = RT_SCOPE_LINK; 466 } 449 467 else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) { 450 468 if (cmd == RTM_DELROUTE) … … 478 496 479 497 req.nlh.nlmsg_len = sizeof(req); 480 req.nlh.nlmsg_type = RTM_GETROUTE; 481 req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST; 482 req.nlh.nlmsg_pid = 0; 498 if (RTM_GETROUTE) 499 req.nlh.nlmsg_type = RTM_GETROUTE; 500 if (NLM_F_ROOT | NLM_F_REQUEST) 501 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST; 502 /*req.nlh.nlmsg_pid = 0; - memset did it already */ 483 503 req.nlh.nlmsg_seq = rth->dump = ++rth->seq; 484 504 req.rtm.rtm_family = family; 485 req.rtm.rtm_flags |= RTM_F_CLONED; 505 if (RTM_F_CLONED) 506 req.rtm.rtm_flags = RTM_F_CLONED; 486 507 487 508 return xsendto(rth->fd, (void*)&req, sizeof(req), (struct sockaddr*)&nladdr, sizeof(nladdr)); … … 498 519 499 520 if (write(flush_fd, "-1", 2) < 2) { 500 bb_perror_msg("can not flush routing cache");521 bb_perror_msg("can't flush routing cache"); 501 522 return; 502 523 } … … 506 527 static void iproute_reset_filter(void) 507 528 { 508 memset(& filter, 0, sizeof(filter));509 filter.mdst.bitlen = -1;510 filter.msrc.bitlen = -1;529 memset(&G_filter, 0, sizeof(G_filter)); 530 G_filter.mdst.bitlen = -1; 531 G_filter.msrc.bitlen = -1; 511 532 } 512 533 513 534 /* Return value becomes exitcode. It's okay to not return at all */ 514 static int iproute_list_or_flush( int argc,char **argv, int flush)535 static int iproute_list_or_flush(char **argv, int flush) 515 536 { 516 537 int do_ipv6 = preferred_family; … … 519 540 char *od = NULL; 520 541 static const char keywords[] ALIGN1 = 521 "protocol\0""all\0""dev\0""oif\0""iif\0""via\0""table\0""cache\0" /*all*/ 522 "from\0""root\0""match\0""exact\0""to\0"/*root match exact*/; 542 /* "ip route list/flush" parameters: */ 543 "protocol\0" "dev\0" "oif\0" "iif\0" 544 "via\0" "table\0" "cache\0" 545 "from\0" "to\0" 546 /* and possible further keywords */ 547 "all\0" 548 "root\0" 549 "match\0" 550 "exact\0" 551 "main\0" 552 ; 523 553 enum { 524 ARG_proto, PARM_all, 525 ARG_dev, 526 ARG_oif, 527 ARG_iif, 528 ARG_via, 529 ARG_table, PARM_cache, /*PARM_all,*/ 530 ARG_from, PARM_root, PARM_match, PARM_exact, 531 ARG_to /*PARM_root, PARM_match, PARM_exact*/ 554 KW_proto, KW_dev, KW_oif, KW_iif, 555 KW_via, KW_table, KW_cache, 556 KW_from, KW_to, 557 /* */ 558 KW_all, 559 KW_root, 560 KW_match, 561 KW_exact, 562 KW_main, 532 563 }; 533 564 int arg, parm; 565 534 566 iproute_reset_filter(); 535 filter.tb = RT_TABLE_MAIN;536 537 if (flush && argc <= 0)567 G_filter.tb = RT_TABLE_MAIN; 568 569 if (flush && !*argv) 538 570 bb_error_msg_and_die(bb_msg_requires_arg, "\"ip route flush\""); 539 571 540 while ( argc > 0) {572 while (*argv) { 541 573 arg = index_in_substrings(keywords, *argv); 542 if (arg == ARG_proto) {574 if (arg == KW_proto) { 543 575 uint32_t prot = 0; 544 576 NEXT_ARG(); 545 filter.protocolmask = -1;577 //G_filter.protocolmask = -1; 546 578 if (rtnl_rtprot_a2n(&prot, *argv)) { 547 if (index_in_strings(keywords, *argv) != PARM_all)579 if (index_in_strings(keywords, *argv) != KW_all) 548 580 invarg(*argv, "protocol"); 549 581 prot = 0; 550 filter.protocolmask = 0;551 } 552 filter.protocol = prot;553 } else if (arg == ARG_dev || arg == ARG_oif) {582 //G_filter.protocolmask = 0; 583 } 584 //G_filter.protocol = prot; 585 } else if (arg == KW_dev || arg == KW_oif) { 554 586 NEXT_ARG(); 555 587 od = *argv; 556 } else if (arg == ARG_iif) {588 } else if (arg == KW_iif) { 557 589 NEXT_ARG(); 558 590 id = *argv; 559 } else if (arg == ARG_via) {560 NEXT_ARG(); 561 get_prefix(& filter.rvia, *argv, do_ipv6);562 } else if (arg == ARG_table) {591 } else if (arg == KW_via) { 592 NEXT_ARG(); 593 get_prefix(&G_filter.rvia, *argv, do_ipv6); 594 } else if (arg == KW_table) { /* table all/cache/main */ 563 595 NEXT_ARG(); 564 596 parm = index_in_substrings(keywords, *argv); 565 if (parm == PARM_cache) 566 filter.tb = -1; 567 else if (parm == PARM_all) 568 filter.tb = 0; 569 else 597 if (parm == KW_cache) 598 G_filter.tb = -1; 599 else if (parm == KW_all) 600 G_filter.tb = 0; 601 else if (parm != KW_main) { 602 #if ENABLE_FEATURE_IP_RULE 603 uint32_t tid; 604 if (rtnl_rttable_a2n(&tid, *argv)) 605 invarg(*argv, "table"); 606 G_filter.tb = tid; 607 #else 570 608 invarg(*argv, "table"); 571 } else if (arg == ARG_from) { 609 #endif 610 } 611 } else if (arg == KW_cache) { 612 /* The command 'ip route flush cache' is used by OpenSWAN. 613 * Assuming it's a synonym for 'ip route flush table cache' */ 614 G_filter.tb = -1; 615 } else if (arg == KW_from) { 572 616 NEXT_ARG(); 573 617 parm = index_in_substrings(keywords, *argv); 574 if (parm == PARM_root) {575 NEXT_ARG(); 576 get_prefix(& filter.rsrc, *argv, do_ipv6);577 } else if (parm == PARM_match) {578 NEXT_ARG(); 579 get_prefix(& filter.msrc, *argv, do_ipv6);618 if (parm == KW_root) { 619 NEXT_ARG(); 620 get_prefix(&G_filter.rsrc, *argv, do_ipv6); 621 } else if (parm == KW_match) { 622 NEXT_ARG(); 623 get_prefix(&G_filter.msrc, *argv, do_ipv6); 580 624 } else { 581 if (parm == PARM_exact)625 if (parm == KW_exact) 582 626 NEXT_ARG(); 583 get_prefix(&filter.msrc, *argv, do_ipv6); 584 filter.rsrc = filter.msrc; 585 } 586 } else { 587 /* parm = arg; // would be more plausible, we reuse arg here */ 588 if (arg == ARG_to) { 627 get_prefix(&G_filter.msrc, *argv, do_ipv6); 628 G_filter.rsrc = G_filter.msrc; 629 } 630 } else { /* "to" is the default parameter */ 631 if (arg == KW_to) { 589 632 NEXT_ARG(); 590 633 arg = index_in_substrings(keywords, *argv); 591 634 } 592 if (arg == PARM_root) { 593 NEXT_ARG(); 594 get_prefix(&filter.rdst, *argv, do_ipv6); 595 } else if (arg == PARM_match) { 596 NEXT_ARG(); 597 get_prefix(&filter.mdst, *argv, do_ipv6); 598 } else { 599 if (arg == PARM_exact) 635 /* parm = arg; - would be more plausible, but we reuse 'arg' here */ 636 if (arg == KW_root) { 637 NEXT_ARG(); 638 get_prefix(&G_filter.rdst, *argv, do_ipv6); 639 } else if (arg == KW_match) { 640 NEXT_ARG(); 641 get_prefix(&G_filter.mdst, *argv, do_ipv6); 642 } else { /* "to exact" is the default */ 643 if (arg == KW_exact) 600 644 NEXT_ARG(); 601 get_prefix(&filter.mdst, *argv, do_ipv6); 602 filter.rdst = filter.mdst; 603 } 604 } 605 argc--; 645 get_prefix(&G_filter.mdst, *argv, do_ipv6); 646 G_filter.rdst = G_filter.mdst; 647 } 648 } 606 649 argv++; 607 650 } 608 651 609 if (do_ipv6 == AF_UNSPEC && filter.tb) {652 if (do_ipv6 == AF_UNSPEC && G_filter.tb) { 610 653 do_ipv6 = AF_INET; 611 654 } 612 655 613 656 xrtnl_open(&rth); 614 615 657 ll_init_map(&rth); 616 658 … … 620 662 if (id) { 621 663 idx = xll_name_to_index(id); 622 filter.iif = idx;623 filter.iifmask = -1;664 G_filter.iif = idx; 665 G_filter.iifmask = -1; 624 666 } 625 667 if (od) { 626 668 idx = xll_name_to_index(od); 627 filter.oif = idx;628 filter.oifmask = -1;669 G_filter.oif = idx; 670 G_filter.oifmask = -1; 629 671 } 630 672 } … … 633 675 char flushb[4096-512]; 634 676 635 if ( filter.tb == -1) {677 if (G_filter.tb == -1) { /* "flush table cache" */ 636 678 if (do_ipv6 != AF_INET6) 637 679 iproute_flush_cache(); … … 640 682 } 641 683 642 filter.flushb = flushb;643 filter.flushp = 0;644 filter.flushe = sizeof(flushb);645 filter.rth = &rth;684 G_filter.flushb = flushb; 685 G_filter.flushp = 0; 686 G_filter.flushe = sizeof(flushb); 687 G_filter.rth = &rth; 646 688 647 689 for (;;) { 648 690 xrtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE); 649 filter.flushed = 0;650 xrtnl_dump_filter(&rth, print_route, stdout);651 if ( filter.flushed == 0)691 G_filter.flushed = 0; 692 xrtnl_dump_filter(&rth, print_route, NULL); 693 if (G_filter.flushed == 0) 652 694 return 0; 653 695 if (flush_update()) … … 656 698 } 657 699 658 if ( filter.tb != -1) {700 if (G_filter.tb != -1) { 659 701 xrtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE); 660 702 } else if (rtnl_rtcache_request(&rth, do_ipv6) < 0) { 661 bb_perror_msg_and_die("can not send dump request");662 } 663 xrtnl_dump_filter(&rth, print_route, stdout);703 bb_perror_msg_and_die("can't send dump request"); 704 } 705 xrtnl_dump_filter(&rth, print_route, NULL); 664 706 665 707 return 0; … … 668 710 669 711 /* Return value becomes exitcode. It's okay to not return at all */ 670 static int iproute_get( int argc,char **argv)712 static int iproute_get(char **argv) 671 713 { 672 714 struct rtnl_handle rth; … … 688 730 689 731 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 690 req.n.nlmsg_flags = NLM_F_REQUEST; 691 req.n.nlmsg_type = RTM_GETROUTE; 732 if (NLM_F_REQUEST) 733 req.n.nlmsg_flags = NLM_F_REQUEST; 734 if (RTM_GETROUTE) 735 req.n.nlmsg_type = RTM_GETROUTE; 692 736 req.r.rtm_family = preferred_family; 693 req.r.rtm_table = 0;694 req.r.rtm_protocol = 0;695 req.r.rtm_scope = 0;696 req.r.rtm_type = 0;697 req.r.rtm_src_len = 0;698 req.r.rtm_dst_len = 0;699 req.r.rtm_tos = 0;700 701 while ( argc > 0) {737 /*req.r.rtm_table = 0; - memset did this already */ 738 /*req.r.rtm_protocol = 0;*/ 739 /*req.r.rtm_scope = 0;*/ 740 /*req.r.rtm_type = 0;*/ 741 /*req.r.rtm_src_len = 0;*/ 742 /*req.r.rtm_dst_len = 0;*/ 743 /*req.r.rtm_tos = 0;*/ 744 745 while (*argv) { 702 746 switch (index_in_strings(options, *argv)) { 703 747 case 0: /* from */ … … 745 789 req.r.rtm_dst_len = addr.bitlen; 746 790 } 747 argc--; argv++;748 }791 } 792 argv++; 749 793 } 750 794 … … 783 827 struct rtattr * tb[RTA_MAX+1]; 784 828 785 print_route(NULL, &req.n, (void*)stdout);829 print_route(NULL, &req.n, NULL); 786 830 787 831 if (req.n.nlmsg_type != RTM_NEWROUTE) { … … 800 844 r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]); 801 845 } else if (!tb[RTA_SRC]) { 802 bb_error_msg_and_die(" failed toconnect the route");846 bb_error_msg_and_die("can't connect the route"); 803 847 } 804 848 if (!odev && tb[RTA_OIF]) { … … 818 862 } 819 863 } 820 print_route(NULL, &req.n, (void*)stdout);864 print_route(NULL, &req.n, NULL); 821 865 return 0; 822 866 } 823 867 824 868 /* Return value becomes exitcode. It's okay to not return at all */ 825 int do_iproute(int argc,char **argv)869 int FAST_FUNC do_iproute(char **argv) 826 870 { 827 871 static const char ip_route_commands[] ALIGN1 = … … 829 873 /*4-7*/ "delete\0""get\0""list\0""show\0" 830 874 /*8..*/ "prepend\0""replace\0""test\0""flush\0"; 831 int command_num = 6;875 int command_num; 832 876 unsigned flags = 0; 833 877 int cmd = RTM_NEWROUTE; 834 878 879 if (!*argv) 880 return iproute_list_or_flush(argv, 0); 881 835 882 /* "Standard" 'ip r a' treats 'a' as 'add', not 'append' */ 836 883 /* It probably means that it is using "first match" rule */ 837 if (*argv) { 838 command_num = index_in_substrings(ip_route_commands, *argv); 839 } 884 command_num = index_in_substrings(ip_route_commands, *argv); 885 840 886 switch (command_num) { 841 887 case 0: /* add */ … … 853 899 break; 854 900 case 5: /* get */ 855 return iproute_get(arg c-1, argv+1);901 return iproute_get(argv+1); 856 902 case 6: /* list */ 857 903 case 7: /* show */ 858 return iproute_list_or_flush(arg c-1, argv+1, 0);904 return iproute_list_or_flush(argv+1, 0); 859 905 case 8: /* prepend */ 860 906 flags = NLM_F_CREATE; 907 break; 861 908 case 9: /* replace */ 862 909 flags = NLM_F_CREATE|NLM_F_REPLACE; 910 break; 863 911 case 10: /* test */ 864 912 flags = NLM_F_EXCL; 913 break; 865 914 case 11: /* flush */ 866 return iproute_list_or_flush(arg c-1, argv+1, 1);915 return iproute_list_or_flush(argv+1, 1); 867 916 default: 868 917 bb_error_msg_and_die("unknown command %s", *argv); 869 918 } 870 919 871 return iproute_modify(cmd, flags, arg c-1, argv+1);920 return iproute_modify(cmd, flags, argv+1); 872 921 }
Note:
See TracChangeset
for help on using the changeset viewer.