aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-02-23 01:20:44 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-02-23 01:20:44 +0100
commit3bb235c3b50ca072e8bcfc20d5030f5460439c07 (patch)
tree8704db0e2526381902606da0c5ba5f7a91fc8e1e
parentbac0a25f72cdf59f34638aa3fd95bb14b103c286 (diff)
downloadbusybox-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.c18
-rw-r--r--networking/libiproute/libnetlink.c2
-rw-r--r--networking/libiproute/utils.c86
-rw-r--r--networking/libiproute/utils.h6
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
96static int get_prefix_1(inet_prefix *dst, char *arg, int family) 121static 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
155int get_addr(inet_prefix *dst, char *arg, int family) 180int 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
166int get_prefix(inet_prefix *dst, char *arg, int family) 191void 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
177uint32_t get_addr32(char *name) 199uint32_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
207int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits) 229int 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
59extern uint32_t get_addr32(char *name); 59extern uint32_t get_addr32(char *name);
60extern int get_addr_1(inet_prefix *dst, char *arg, int family); 60extern 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);*/
62extern int get_addr(inet_prefix *dst, char *arg, int family); 62extern int get_addr(inet_prefix *dst, char *arg, int family);
63extern int get_prefix(inet_prefix *dst, char *arg, int family); 63extern void get_prefix(inet_prefix *dst, char *arg, int family);
64 64
65extern unsigned get_unsigned(char *arg, const char *errmsg); 65extern unsigned get_unsigned(char *arg, const char *errmsg);
66extern uint32_t get_u32(char *arg, const char *errmsg); 66extern 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
77void invarg(const char *, const char *) NORETURN; 77void invarg(const char *, const char *) NORETURN;
78void duparg(const char *, const char *) NORETURN; 78void duparg(const char *, const char *) NORETURN;
79void duparg2(const char *, const char *) NORETURN; 79void duparg2(const char *, const char *) NORETURN;
80int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits); 80int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
81 81
82const char *dnet_ntop(int af, const void *addr, char *str, size_t len); 82const char *dnet_ntop(int af, const void *addr, char *str, size_t len);
83int dnet_pton(int af, const char *src, void *addr); 83int dnet_pton(int af, const char *src, void *addr);