diff options
Diffstat (limited to 'networking/libiproute/utils.c')
-rw-r--r-- | networking/libiproute/utils.c | 86 |
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 | ||
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; |