diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-02-23 01:20:44 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-02-23 01:20:44 +0100 |
commit | 3bb235c3b50ca072e8bcfc20d5030f5460439c07 (patch) | |
tree | 8704db0e2526381902606da0c5ba5f7a91fc8e1e | |
parent | bac0a25f72cdf59f34638aa3fd95bb14b103c286 (diff) | |
download | busybox-w32-3bb235c3b50ca072e8bcfc20d5030f5460439c07.tar.gz busybox-w32-3bb235c3b50ca072e8bcfc20d5030f5460439c07.tar.bz2 busybox-w32-3bb235c3b50ca072e8bcfc20d5030f5460439c07.zip |
iproute: fix parsing and matching of of "short" IP addrs like 10/8
function old new delta
print_route 1613 1813 +200
get_addr_1 209 258 +49
get_prefix 393 356 -37
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 249/-37) Total: 212 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/libiproute/iproute.c | 18 | ||||
-rw-r--r-- | networking/libiproute/libnetlink.c | 2 | ||||
-rw-r--r-- | networking/libiproute/utils.c | 86 | ||||
-rw-r--r-- | networking/libiproute/utils.h | 6 |
4 files changed, 74 insertions, 38 deletions
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 393a376ac..f8a67d9ee 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -82,7 +82,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, | |||
82 | { | 82 | { |
83 | struct rtmsg *r = NLMSG_DATA(n); | 83 | struct rtmsg *r = NLMSG_DATA(n); |
84 | int len = n->nlmsg_len; | 84 | int len = n->nlmsg_len; |
85 | struct rtattr * tb[RTA_MAX+1]; | 85 | struct rtattr *tb[RTA_MAX+1]; |
86 | char abuf[256]; | 86 | char abuf[256]; |
87 | inet_prefix dst; | 87 | inet_prefix dst; |
88 | inet_prefix src; | 88 | inet_prefix src; |
@@ -159,8 +159,21 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, | |||
159 | } | 159 | } |
160 | 160 | ||
161 | memset(tb, 0, sizeof(tb)); | 161 | memset(tb, 0, sizeof(tb)); |
162 | memset(&src, 0, sizeof(src)); | ||
163 | memset(&dst, 0, sizeof(dst)); | ||
162 | parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); | 164 | parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); |
163 | 165 | ||
166 | if (tb[RTA_SRC]) { | ||
167 | src.bitlen = r->rtm_src_len; | ||
168 | src.bytelen = (r->rtm_family == AF_INET6 ? 16 : 4); | ||
169 | memcpy(src.data, RTA_DATA(tb[RTA_SRC]), src.bytelen); | ||
170 | } | ||
171 | if (tb[RTA_DST]) { | ||
172 | dst.bitlen = r->rtm_dst_len; | ||
173 | dst.bytelen = (r->rtm_family == AF_INET6 ? 16 : 4); | ||
174 | memcpy(dst.data, RTA_DATA(tb[RTA_DST]), dst.bytelen); | ||
175 | } | ||
176 | |||
164 | if (G_filter.rdst.family | 177 | if (G_filter.rdst.family |
165 | && inet_addr_match(&dst, &G_filter.rdst, G_filter.rdst.bitlen) | 178 | && inet_addr_match(&dst, &G_filter.rdst, G_filter.rdst.bitlen) |
166 | ) { | 179 | ) { |
@@ -426,7 +439,8 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
426 | NEXT_ARG(); | 439 | NEXT_ARG(); |
427 | } | 440 | } |
428 | if ((**argv < '0' || **argv > '9') | 441 | if ((**argv < '0' || **argv > '9') |
429 | && rtnl_rtntype_a2n(&type, *argv) == 0) { | 442 | && rtnl_rtntype_a2n(&type, *argv) == 0 |
443 | ) { | ||
430 | NEXT_ARG(); | 444 | NEXT_ARG(); |
431 | req.r.rtm_type = type; | 445 | req.r.rtm_type = type; |
432 | ok |= type_ok; | 446 | ok |= type_ok; |
diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c index 547013ff6..c7533a4a7 100644 --- a/networking/libiproute/libnetlink.c +++ b/networking/libiproute/libnetlink.c | |||
@@ -393,7 +393,7 @@ void FAST_FUNC parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, in | |||
393 | if (rta->rta_type <= max) { | 393 | if (rta->rta_type <= max) { |
394 | tb[rta->rta_type] = rta; | 394 | tb[rta->rta_type] = rta; |
395 | } | 395 | } |
396 | rta = RTA_NEXT(rta,len); | 396 | rta = RTA_NEXT(rta, len); |
397 | } | 397 | } |
398 | if (len) { | 398 | if (len) { |
399 | bb_error_msg("deficit %d, rta_len=%d!", len, rta->rta_len); | 399 | bb_error_msg("deficit %d, rta_len=%d!", len, rta->rta_len); |
diff --git a/networking/libiproute/utils.c b/networking/libiproute/utils.c index d32db8de5..d0fe30605 100644 --- a/networking/libiproute/utils.c +++ b/networking/libiproute/utils.c | |||
@@ -83,20 +83,43 @@ int get_addr_1(inet_prefix *addr, char *name, int family) | |||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | addr->family = AF_INET; | ||
87 | if (family != AF_UNSPEC && family != AF_INET) | 86 | if (family != AF_UNSPEC && family != AF_INET) |
88 | return -1; | 87 | return -1; |
88 | |||
89 | /* Try to parse it as IPv4 */ | ||
90 | addr->family = AF_INET; | ||
91 | #if 0 /* Doesn't handle e.g. "10.10", for example, "ip r l root 10.10/16" */ | ||
89 | if (inet_pton(AF_INET, name, addr->data) <= 0) | 92 | if (inet_pton(AF_INET, name, addr->data) <= 0) |
90 | return -1; | 93 | return -1; |
94 | #else | ||
95 | { | ||
96 | unsigned i = 0; | ||
97 | unsigned n = 0; | ||
98 | const char *cp = name - 1; | ||
99 | while (*++cp) { | ||
100 | if ((unsigned char)(*cp - '0') <= 9) { | ||
101 | n = 10 * n + (unsigned char)(*cp - '0'); | ||
102 | if (n >= 256) | ||
103 | return -1; | ||
104 | ((uint8_t*)addr->data)[i] = n; | ||
105 | continue; | ||
106 | } | ||
107 | if (*cp == '.' && ++i <= 3) { | ||
108 | n = 0; | ||
109 | continue; | ||
110 | } | ||
111 | return -1; | ||
112 | } | ||
113 | } | ||
114 | #endif | ||
91 | addr->bytelen = 4; | 115 | addr->bytelen = 4; |
92 | addr->bitlen = -1; | 116 | addr->bitlen = -1; |
117 | |||
93 | return 0; | 118 | return 0; |
94 | } | 119 | } |
95 | 120 | ||
96 | static int get_prefix_1(inet_prefix *dst, char *arg, int family) | 121 | static void get_prefix_1(inet_prefix *dst, char *arg, int family) |
97 | { | 122 | { |
98 | int err; | ||
99 | unsigned plen; | ||
100 | char *slash; | 123 | char *slash; |
101 | 124 | ||
102 | memset(dst, 0, sizeof(*dst)); | 125 | memset(dst, 0, sizeof(*dst)); |
@@ -108,48 +131,50 @@ static int get_prefix_1(inet_prefix *dst, char *arg, int family) | |||
108 | dst->family = family; | 131 | dst->family = family; |
109 | /*dst->bytelen = 0; - done by memset */ | 132 | /*dst->bytelen = 0; - done by memset */ |
110 | /*dst->bitlen = 0;*/ | 133 | /*dst->bitlen = 0;*/ |
111 | return 0; | 134 | return; |
112 | } | 135 | } |
113 | 136 | ||
114 | slash = strchr(arg, '/'); | 137 | slash = strchr(arg, '/'); |
115 | if (slash) | 138 | if (slash) |
116 | *slash = '\0'; | 139 | *slash = '\0'; |
117 | err = get_addr_1(dst, arg, family); | 140 | |
118 | if (err == 0) { | 141 | if (get_addr_1(dst, arg, family) == 0) { |
119 | dst->bitlen = (dst->family == AF_INET6) ? 128 : 32; | 142 | dst->bitlen = (dst->family == AF_INET6) ? 128 : 32; |
120 | if (slash) { | 143 | if (slash) { |
144 | unsigned plen; | ||
121 | inet_prefix netmask_pfx; | 145 | inet_prefix netmask_pfx; |
122 | 146 | ||
123 | netmask_pfx.family = AF_UNSPEC; | 147 | netmask_pfx.family = AF_UNSPEC; |
124 | plen = bb_strtou(slash + 1, NULL, 0); | 148 | plen = bb_strtou(slash + 1, NULL, 0); |
125 | if ((errno || plen > dst->bitlen) | 149 | if ((errno || plen > dst->bitlen) |
126 | && (get_addr_1(&netmask_pfx, slash + 1, family))) | 150 | && get_addr_1(&netmask_pfx, slash + 1, family) != 0 |
127 | err = -1; | 151 | ) { |
128 | else if (netmask_pfx.family == AF_INET) { | 152 | goto bad; |
153 | } | ||
154 | if (netmask_pfx.family == AF_INET) { | ||
129 | /* fill in prefix length of dotted quad */ | 155 | /* fill in prefix length of dotted quad */ |
130 | uint32_t mask = ntohl(netmask_pfx.data[0]); | 156 | uint32_t mask = ntohl(netmask_pfx.data[0]); |
131 | uint32_t host = ~mask; | 157 | uint32_t host = ~mask; |
132 | 158 | ||
133 | /* a valid netmask must be 2^n - 1 */ | 159 | /* a valid netmask must be 2^n - 1 */ |
134 | if (!(host & (host + 1))) { | 160 | if (host & (host + 1)) |
135 | for (plen = 0; mask; mask <<= 1) | 161 | goto bad; |
136 | ++plen; | 162 | |
137 | if (plen <= dst->bitlen) { | 163 | for (plen = 0; mask; mask <<= 1) |
138 | dst->bitlen = plen; | 164 | ++plen; |
139 | /* dst->flags |= PREFIXLEN_SPECIFIED; */ | 165 | if (plen > dst->bitlen) |
140 | } else | 166 | goto bad; |
141 | err = -1; | 167 | /* dst->flags |= PREFIXLEN_SPECIFIED; */ |
142 | } else | ||
143 | err = -1; | ||
144 | } else { | ||
145 | /* plain prefix */ | ||
146 | dst->bitlen = plen; | ||
147 | } | 168 | } |
169 | dst->bitlen = plen; | ||
148 | } | 170 | } |
149 | } | 171 | } |
172 | |||
150 | if (slash) | 173 | if (slash) |
151 | *slash = '/'; | 174 | *slash = '/'; |
152 | return err; | 175 | return; |
176 | bad: | ||
177 | bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg); | ||
153 | } | 178 | } |
154 | 179 | ||
155 | int get_addr(inet_prefix *dst, char *arg, int family) | 180 | int get_addr(inet_prefix *dst, char *arg, int family) |
@@ -163,15 +188,12 @@ int get_addr(inet_prefix *dst, char *arg, int family) | |||
163 | return 0; | 188 | return 0; |
164 | } | 189 | } |
165 | 190 | ||
166 | int get_prefix(inet_prefix *dst, char *arg, int family) | 191 | void get_prefix(inet_prefix *dst, char *arg, int family) |
167 | { | 192 | { |
168 | if (family == AF_PACKET) { | 193 | if (family == AF_PACKET) { |
169 | bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix"); | 194 | bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix"); |
170 | } | 195 | } |
171 | if (get_prefix_1(dst, arg, family)) { | 196 | get_prefix_1(dst, arg, family); |
172 | bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg); | ||
173 | } | ||
174 | return 0; | ||
175 | } | 197 | } |
176 | 198 | ||
177 | uint32_t get_addr32(char *name) | 199 | uint32_t get_addr32(char *name) |
@@ -204,10 +226,10 @@ void duparg2(const char *key, const char *arg) | |||
204 | bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg); | 226 | bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg); |
205 | } | 227 | } |
206 | 228 | ||
207 | int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits) | 229 | int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits) |
208 | { | 230 | { |
209 | uint32_t *a1 = a->data; | 231 | const uint32_t *a1 = a->data; |
210 | uint32_t *a2 = b->data; | 232 | const uint32_t *a2 = b->data; |
211 | int words = bits >> 5; | 233 | int words = bits >> 5; |
212 | 234 | ||
213 | bits &= 0x1f; | 235 | bits &= 0x1f; |
diff --git a/networking/libiproute/utils.h b/networking/libiproute/utils.h index 93c9d25d6..5fb4a862c 100644 --- a/networking/libiproute/utils.h +++ b/networking/libiproute/utils.h | |||
@@ -58,9 +58,9 @@ struct ipx_addr { | |||
58 | 58 | ||
59 | extern uint32_t get_addr32(char *name); | 59 | extern uint32_t get_addr32(char *name); |
60 | extern int get_addr_1(inet_prefix *dst, char *arg, int family); | 60 | extern int get_addr_1(inet_prefix *dst, char *arg, int family); |
61 | /*extern int get_prefix_1(inet_prefix *dst, char *arg, int family);*/ | 61 | /*extern void get_prefix_1(inet_prefix *dst, char *arg, int family);*/ |
62 | extern int get_addr(inet_prefix *dst, char *arg, int family); | 62 | extern int get_addr(inet_prefix *dst, char *arg, int family); |
63 | extern int get_prefix(inet_prefix *dst, char *arg, int family); | 63 | extern void get_prefix(inet_prefix *dst, char *arg, int family); |
64 | 64 | ||
65 | extern unsigned get_unsigned(char *arg, const char *errmsg); | 65 | extern unsigned get_unsigned(char *arg, const char *errmsg); |
66 | extern uint32_t get_u32(char *arg, const char *errmsg); | 66 | extern uint32_t get_u32(char *arg, const char *errmsg); |
@@ -77,7 +77,7 @@ extern const char *format_host(int af, int len, void *addr, char *buf, int bufle | |||
77 | void invarg(const char *, const char *) NORETURN; | 77 | void invarg(const char *, const char *) NORETURN; |
78 | void duparg(const char *, const char *) NORETURN; | 78 | void duparg(const char *, const char *) NORETURN; |
79 | void duparg2(const char *, const char *) NORETURN; | 79 | void duparg2(const char *, const char *) NORETURN; |
80 | int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits); | 80 | int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits); |
81 | 81 | ||
82 | const char *dnet_ntop(int af, const void *addr, char *str, size_t len); | 82 | const char *dnet_ntop(int af, const void *addr, char *str, size_t len); |
83 | int dnet_pton(int af, const char *src, void *addr); | 83 | int dnet_pton(int af, const char *src, void *addr); |