aboutsummaryrefslogtreecommitdiff
path: root/networking/libiproute/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/libiproute/utils.c')
-rw-r--r--networking/libiproute/utils.c86
1 files changed, 54 insertions, 32 deletions
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;