53
58
static void usage(void)
55
60
fprintf(stderr, "Usage: ip route { list | flush } SELECTOR\n");
61
fprintf(stderr, " ip route save SELECTOR\n");
62
fprintf(stderr, " ip route restore\n");
56
63
fprintf(stderr, " ip route get ADDRESS [ from ADDRESS iif STRING ]\n");
57
64
fprintf(stderr, " [ oif STRING ] [ tos TOS ]\n");
65
fprintf(stderr, " [ mark NUMBER ]\n");
58
66
fprintf(stderr, " ip route { add | del | change | append | replace | monitor } ROUTE\n");
59
67
fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n");
60
68
fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n");
77
85
fprintf(stderr, "MP_ALGO := { rr | drr | random | wrandom }\n");
78
86
fprintf(stderr, "NHFLAGS := [ onlink | pervasive ]\n");
79
87
fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n");
80
fprintf(stderr, "TIME := NUMBER[s|ms|us|ns|j]\n");
88
fprintf(stderr, "TIME := NUMBER[s|ms]\n");
118
int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
127
int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
120
FILE *fp = (FILE*)arg;
121
129
struct rtmsg *r = NLMSG_DATA(n);
122
int len = n->nlmsg_len;
123
struct rtattr * tb[RTA_MAX+1];
127
133
inet_prefix prefsrc;
130
135
static int ip6_multiple_tables;
135
if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
136
fprintf(stderr, "Not a route: %08x %08x %08x\n",
137
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
140
if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE)
142
len -= NLMSG_LENGTH(sizeof(*r));
144
fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
148
if (r->rtm_family == AF_INET6)
150
else if (r->rtm_family == AF_INET)
152
else if (r->rtm_family == AF_DECnet)
154
else if (r->rtm_family == AF_IPX)
157
parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
158
137
table = rtm_get_table(r, tb);
160
139
if (r->rtm_family == AF_INET6 && table != RT_TABLE_MAIN)
161
140
ip6_multiple_tables = 1;
142
if (filter.cloned == !(r->rtm_flags&RTM_F_CLONED))
163
145
if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) {
165
if (!(r->rtm_flags&RTM_F_CLONED))
169
if (!filter.cloned && r->rtm_flags&RTM_F_CLONED)
171
147
if (filter.tb == RT_TABLE_LOCAL) {
172
148
if (r->rtm_type != RTN_LOCAL)
281
260
*(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1)
266
int calc_host_len(struct rtmsg *r)
268
if (r->rtm_family == AF_INET6)
270
else if (r->rtm_family == AF_INET)
272
else if (r->rtm_family == AF_DECnet)
274
else if (r->rtm_family == AF_IPX)
280
int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
282
FILE *fp = (FILE*)arg;
283
struct rtmsg *r = NLMSG_DATA(n);
284
int len = n->nlmsg_len;
285
struct rtattr * tb[RTA_MAX+1];
292
if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
293
fprintf(stderr, "Not a route: %08x %08x %08x\n",
294
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
297
if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE)
299
len -= NLMSG_LENGTH(sizeof(*r));
301
fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
305
host_len = calc_host_len(r);
307
parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
308
table = rtm_get_table(r, tb);
310
if (!filter_nlmsg(n, tb, host_len))
284
313
if (filter.flushb) {
285
314
struct nlmsghdr *fn;
286
315
if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
384
413
fprintf(fp, "pervasive ");
385
414
if (r->rtm_flags & RTM_F_NOTIFY)
386
415
fprintf(fp, "notify ");
417
unsigned int mark = *(unsigned int*)RTA_DATA(tb[RTA_MARK]);
420
fprintf(fp, " mark 0x%x", mark);
422
fprintf(fp, " mark %u", mark);
388
426
if (tb[RTA_FLOW] && filter.realmmask != ~0U) {
389
427
__u32 to = *(__u32*)RTA_DATA(tb[RTA_FLOW]);
512
548
case RTAX_RTTVAR:
513
549
case RTAX_RTO_MIN:
515
550
if (i == RTAX_RTT)
517
552
else if (i == RTAX_RTTVAR)
521
fprintf(fp, " %llums",
522
(unsigned long long) val / hz);
556
fprintf(fp, " %gs", val/1e3);
524
fprintf(fp, " %.2fms",
558
fprintf(fp, " %ums", val);
802
835
mxlock |= (1<<RTAX_RTT);
805
if (get_jiffies(&rtt, *argv, 0, &raw))
838
if (get_time_rtt(&rtt, *argv, &raw))
806
839
invarg("\"rtt\" value is invalid\n", *argv);
807
840
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT,
808
841
(raw) ? rtt : rtt * 8);
810
843
unsigned rto_min;
812
845
mxlock |= (1<<RTAX_RTO_MIN);
813
if (get_jiffies(&rto_min, *argv, 0, &raw))
846
if (get_time_rtt(&rto_min, *argv, &raw))
814
847
invarg("\"rto_min\" value is invalid\n",
816
849
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN,
862
895
mxlock |= (1<<RTAX_RTTVAR);
865
if (get_jiffies(&win, *argv, 0, &raw))
898
if (get_time_rtt(&win, *argv, &raw))
866
899
invarg("\"rttvar\" value is invalid\n", *argv);
867
900
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR,
868
901
(raw) ? win : win * 4);
1045
static int iproute_list_or_flush(int argc, char **argv, int flush)
1077
int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
1080
int len = n->nlmsg_len;
1081
struct rtmsg *r = NLMSG_DATA(n);
1082
struct rtattr *tb[RTA_MAX+1];
1085
if (isatty(STDOUT_FILENO)) {
1086
fprintf(stderr, "Not sending binary stream to stdout\n");
1090
host_len = calc_host_len(r);
1091
len -= NLMSG_LENGTH(sizeof(*r));
1092
parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
1094
if (!filter_nlmsg(n, tb, host_len))
1097
ret = write(STDOUT_FILENO, n, n->nlmsg_len);
1098
if ((ret > 0) && (ret != n->nlmsg_len)) {
1099
fprintf(stderr, "Short write while saving nlmsg\n");
1103
return ret == n->nlmsg_len ? 0 : ret;
1106
static int iproute_list_flush_or_save(int argc, char **argv, int action)
1047
1108
int do_ipv6 = preferred_family;
1048
1109
char *id = NULL;
1049
1110
char *od = NULL;
1111
unsigned int mark = 0;
1112
rtnl_filter_t filter_fn;
1114
if (action == IPROUTE_SAVE)
1115
filter_fn = save_route;
1117
filter_fn = print_route;
1051
1119
iproute_reset_filter();
1052
1120
filter.tb = RT_TABLE_MAIN;
1054
if (flush && argc <= 0) {
1122
if ((action == IPROUTE_FLUSH) && argc <= 0) {
1055
1123
fprintf(stderr, "\"ip route flush\" requires arguments.\n");
1119
1187
} else if (strcmp(*argv, "iif") == 0) {
1190
} else if (strcmp(*argv, "mark") == 0) {
1192
get_unsigned(&mark, *argv, 0);
1193
filter.markmask = -1;
1122
1194
} else if (strcmp(*argv, "via") == 0) {
1124
1196
get_prefix(&filter.rvia, *argv, do_ipv6);
1228
1301
filter.flushed = 0;
1229
if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
1302
if (rtnl_dump_filter(&rth, filter_fn, stdout, NULL, NULL) < 0) {
1230
1303
fprintf(stderr, "Flush terminated\n");
1272
if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
1345
if (rtnl_dump_filter(&rth, filter_fn, stdout, NULL, NULL) < 0) {
1273
1346
fprintf(stderr, "Dump terminated\n");
1329
1404
} else if (matches(*argv, "iif") == 0) {
1407
} else if (matches(*argv, "mark") == 0) {
1409
get_unsigned(&mark, *argv, 0);
1332
1410
} else if (matches(*argv, "oif") == 0 ||
1333
1411
strcmp(*argv, "dev") == 0) {
1379
1457
addattr32(&req.n, sizeof(req), RTA_OIF, idx);
1461
addattr32(&req.n, sizeof(req), RTA_MARK, mark);
1383
1463
if (req.r.rtm_family == AF_UNSPEC)
1384
1464
req.r.rtm_family = AF_INET;
1519
int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
1523
n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
1527
ret = rtnl_talk(&rth, n, 0, 0, n, NULL, NULL);
1528
if ((ret < 0) && (errno == EEXIST))
1534
int iproute_restore(void)
1536
exit(rtnl_from_file(stdin, &restore_handler, NULL));
1439
1539
void iproute_reset_filter()
1441
1541
memset(&filter, 0, sizeof(filter));
1446
1546
int do_iproute(int argc, char **argv)
1449
return iproute_list_or_flush(0, NULL, 0);
1549
return iproute_list_flush_or_save(0, NULL, IPROUTE_LIST);
1451
1551
if (matches(*argv, "add") == 0)
1452
1552
return iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL,
1471
1571
argc-1, argv+1);
1472
1572
if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
1473
1573
|| matches(*argv, "lst") == 0)
1474
return iproute_list_or_flush(argc-1, argv+1, 0);
1574
return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_LIST);
1475
1575
if (matches(*argv, "get") == 0)
1476
1576
return iproute_get(argc-1, argv+1);
1477
1577
if (matches(*argv, "flush") == 0)
1478
return iproute_list_or_flush(argc-1, argv+1, 1);
1578
return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_FLUSH);
1579
if (matches(*argv, "save") == 0)
1580
return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_SAVE);
1581
if (matches(*argv, "restore") == 0)
1582
return iproute_restore();
1479
1583
if (matches(*argv, "help") == 0)
1481
1585
fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv);