aboutsummaryrefslogtreecommitdiff
path: root/networking/libiproute/iptunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/libiproute/iptunnel.c')
-rw-r--r--networking/libiproute/iptunnel.c117
1 files changed, 75 insertions, 42 deletions
diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c
index 3327b27a3..b12bceb45 100644
--- a/networking/libiproute/iptunnel.c
+++ b/networking/libiproute/iptunnel.c
@@ -137,6 +137,23 @@ static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
137{ 137{
138 int count = 0; 138 int count = 0;
139 char medium[IFNAMSIZ]; 139 char medium[IFNAMSIZ];
140 static const char * const keywords[] = {
141 "mode", "ipip", "ip/ip", "gre", "gre/ip", "sit", "ipv6/ip",
142 "key", "ikey", "okey", "seq", "iseq", "oseq",
143 "csum", "icsum", "ocsum", "nopmtudisc", "pmtudisc",
144 "remote", "any", "local", "dev",
145 "ttl", "inherit", "tos", "dsfield",
146 "name", NULL
147 };
148 enum {
149 ARG_mode, ARG_ipip, ARG_ip_ip, ARG_gre, ARG_gre_ip, ARG_sit, ARG_ip6_ip,
150 ARG_key, ARG_ikey, ARG_okey, ARG_seq, ARG_iseq, ARG_oseq,
151 ARG_csum, ARG_icsum, ARG_ocsum, ARG_nopmtudisc, ARG_pmtudisc,
152 ARG_remote, ARG_any, ARG_local, ARG_dev,
153 ARG_ttl, ARG_inherit, ARG_tos, ARG_dsfield,
154 ARG_name
155 };
156 int key;
140 memset(p, 0, sizeof(*p)); 157 memset(p, 0, sizeof(*p));
141 memset(&medium, 0, sizeof(medium)); 158 memset(&medium, 0, sizeof(medium));
142 159
@@ -148,22 +165,24 @@ static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
148 p->iph.frag_off = htons(IP_DF); 165 p->iph.frag_off = htons(IP_DF);
149 166
150 while (argc > 0) { 167 while (argc > 0) {
151 if (strcmp(*argv, "mode") == 0) { 168 key = index_in_str_array(keywords, *argv);
169 if (key == ARG_mode) {
152 NEXT_ARG(); 170 NEXT_ARG();
153 if (strcmp(*argv, "ipip") == 0 || 171 key = index_in_str_array(keywords, *argv);
154 strcmp(*argv, "ip/ip") == 0) { 172 if (key == ARG_ipip ||
173 key == ARG_ip_ip) {
155 if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { 174 if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) {
156 bb_error_msg_and_die("you managed to ask for more than one tunnel mode"); 175 bb_error_msg_and_die("you managed to ask for more than one tunnel mode");
157 } 176 }
158 p->iph.protocol = IPPROTO_IPIP; 177 p->iph.protocol = IPPROTO_IPIP;
159 } else if (strcmp(*argv, "gre") == 0 || 178 } else if (key == ARG_gre ||
160 strcmp(*argv, "gre/ip") == 0) { 179 key == ARG_gre_ip) {
161 if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { 180 if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) {
162 bb_error_msg_and_die("you managed to ask for more than one tunnel mode"); 181 bb_error_msg_and_die("you managed to ask for more than one tunnel mode");
163 } 182 }
164 p->iph.protocol = IPPROTO_GRE; 183 p->iph.protocol = IPPROTO_GRE;
165 } else if (strcmp(*argv, "sit") == 0 || 184 } else if (key == ARG_sit ||
166 strcmp(*argv, "ipv6/ip") == 0) { 185 key == ARG_ip6_ip) {
167 if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { 186 if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) {
168 bb_error_msg_and_die("you managed to ask for more than one tunnel mode"); 187 bb_error_msg_and_die("you managed to ask for more than one tunnel mode");
169 } 188 }
@@ -171,7 +190,7 @@ static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
171 } else { 190 } else {
172 bb_error_msg_and_die("cannot guess tunnel mode"); 191 bb_error_msg_and_die("cannot guess tunnel mode");
173 } 192 }
174 } else if (strcmp(*argv, "key") == 0) { 193 } else if (key == ARG_key) {
175 unsigned uval; 194 unsigned uval;
176 NEXT_ARG(); 195 NEXT_ARG();
177 p->i_flags |= GRE_KEY; 196 p->i_flags |= GRE_KEY;
@@ -184,7 +203,7 @@ static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
184 } 203 }
185 p->i_key = p->o_key = htonl(uval); 204 p->i_key = p->o_key = htonl(uval);
186 } 205 }
187 } else if (strcmp(*argv, "ikey") == 0) { 206 } else if (key == ARG_ikey) {
188 unsigned uval; 207 unsigned uval;
189 NEXT_ARG(); 208 NEXT_ARG();
190 p->i_flags |= GRE_KEY; 209 p->i_flags |= GRE_KEY;
@@ -196,7 +215,7 @@ static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
196 } 215 }
197 p->i_key = htonl(uval); 216 p->i_key = htonl(uval);
198 } 217 }
199 } else if (strcmp(*argv, "okey") == 0) { 218 } else if (key == ARG_okey) {
200 unsigned uval; 219 unsigned uval;
201 NEXT_ARG(); 220 NEXT_ARG();
202 p->o_flags |= GRE_KEY; 221 p->o_flags |= GRE_KEY;
@@ -208,57 +227,61 @@ static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
208 } 227 }
209 p->o_key = htonl(uval); 228 p->o_key = htonl(uval);
210 } 229 }
211 } else if (strcmp(*argv, "seq") == 0) { 230 } else if (key == ARG_seq) {
212 p->i_flags |= GRE_SEQ; 231 p->i_flags |= GRE_SEQ;
213 p->o_flags |= GRE_SEQ; 232 p->o_flags |= GRE_SEQ;
214 } else if (strcmp(*argv, "iseq") == 0) { 233 } else if (key == ARG_iseq) {
215 p->i_flags |= GRE_SEQ; 234 p->i_flags |= GRE_SEQ;
216 } else if (strcmp(*argv, "oseq") == 0) { 235 } else if (key == ARG_oseq) {
217 p->o_flags |= GRE_SEQ; 236 p->o_flags |= GRE_SEQ;
218 } else if (strcmp(*argv, "csum") == 0) { 237 } else if (key == ARG_csum) {
219 p->i_flags |= GRE_CSUM; 238 p->i_flags |= GRE_CSUM;
220 p->o_flags |= GRE_CSUM; 239 p->o_flags |= GRE_CSUM;
221 } else if (strcmp(*argv, "icsum") == 0) { 240 } else if (key == ARG_icsum) {
222 p->i_flags |= GRE_CSUM; 241 p->i_flags |= GRE_CSUM;
223 } else if (strcmp(*argv, "ocsum") == 0) { 242 } else if (key == ARG_ocsum) {
224 p->o_flags |= GRE_CSUM; 243 p->o_flags |= GRE_CSUM;
225 } else if (strcmp(*argv, "nopmtudisc") == 0) { 244 } else if (key == ARG_nopmtudisc) {
226 p->iph.frag_off = 0; 245 p->iph.frag_off = 0;
227 } else if (strcmp(*argv, "pmtudisc") == 0) { 246 } else if (key == ARG_pmtudisc) {
228 p->iph.frag_off = htons(IP_DF); 247 p->iph.frag_off = htons(IP_DF);
229 } else if (strcmp(*argv, "remote") == 0) { 248 } else if (key == ARG_remote) {
230 NEXT_ARG(); 249 NEXT_ARG();
231 if (strcmp(*argv, "any")) 250 key = index_in_str_array(keywords, *argv);
251 if (key == ARG_any)
232 p->iph.daddr = get_addr32(*argv); 252 p->iph.daddr = get_addr32(*argv);
233 } else if (strcmp(*argv, "local") == 0) { 253 } else if (key == ARG_local) {
234 NEXT_ARG(); 254 NEXT_ARG();
235 if (strcmp(*argv, "any")) 255 key = index_in_str_array(keywords, *argv);
256 if (key == ARG_any)
236 p->iph.saddr = get_addr32(*argv); 257 p->iph.saddr = get_addr32(*argv);
237 } else if (strcmp(*argv, "dev") == 0) { 258 } else if (key == ARG_dev) {
238 NEXT_ARG(); 259 NEXT_ARG();
239 strncpy(medium, *argv, IFNAMSIZ-1); 260 strncpy(medium, *argv, IFNAMSIZ-1);
240 } else if (strcmp(*argv, "ttl") == 0) { 261 } else if (key == ARG_ttl) {
241 unsigned uval; 262 unsigned uval;
242 NEXT_ARG(); 263 NEXT_ARG();
243 if (strcmp(*argv, "inherit") != 0) { 264 key = index_in_str_array(keywords, *argv);
265 if (key != ARG_inherit) {
244 if (get_unsigned(&uval, *argv, 0)) 266 if (get_unsigned(&uval, *argv, 0))
245 invarg(*argv, "TTL"); 267 invarg(*argv, "TTL");
246 if (uval > 255) 268 if (uval > 255)
247 invarg(*argv, "TTL must be <=255"); 269 invarg(*argv, "TTL must be <=255");
248 p->iph.ttl = uval; 270 p->iph.ttl = uval;
249 } 271 }
250 } else if (strcmp(*argv, "tos") == 0 || 272 } else if (key == ARG_tos ||
251 matches(*argv, "dsfield") == 0) { 273 key == ARG_dsfield) {
252 uint32_t uval; 274 uint32_t uval;
253 NEXT_ARG(); 275 NEXT_ARG();
254 if (strcmp(*argv, "inherit") != 0) { 276 key = index_in_str_array(keywords, *argv);
277 if (key != ARG_inherit) {
255 if (rtnl_dsfield_a2n(&uval, *argv)) 278 if (rtnl_dsfield_a2n(&uval, *argv))
256 invarg(*argv, "TOS"); 279 invarg(*argv, "TOS");
257 p->iph.tos = uval; 280 p->iph.tos = uval;
258 } else 281 } else
259 p->iph.tos = 1; 282 p->iph.tos = 1;
260 } else { 283 } else {
261 if (strcmp(*argv, "name") == 0) { 284 if (key == ARG_name) {
262 NEXT_ARG(); 285 NEXT_ARG();
263 } 286 }
264 if (p->name[0]) 287 if (p->name[0])
@@ -438,7 +461,7 @@ static void do_tunnels_list(struct ip_tunnel_parm *p)
438 ptr = strchr(buf, ':'); 461 ptr = strchr(buf, ':');
439 if (ptr == NULL || 462 if (ptr == NULL ||
440 (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) { 463 (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
441 bb_error_msg("wrong format of /proc/net/dev. Sorry"); 464 bb_error_msg("wrong format of /proc/net/dev");
442 return; 465 return;
443 } 466 }
444 if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu", 467 if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu",
@@ -503,19 +526,29 @@ static int do_show(int argc, char **argv)
503/* Return value becomes exitcode. It's okay to not return at all */ 526/* Return value becomes exitcode. It's okay to not return at all */
504int do_iptunnel(int argc, char **argv) 527int do_iptunnel(int argc, char **argv)
505{ 528{
529 static const char * const keywords[] = {
530 "add", "change", "delete", "show", "list", "lst", NULL
531 };
532 enum {ARG_add = 1, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst};
533 smalluint key = 4; /* show */
506 if (argc > 0) { 534 if (argc > 0) {
507 if (matches(*argv, "add") == 0) 535 key = index_in_substr_array(keywords, *argv) +1;
508 return do_add(SIOCADDTUNNEL, argc-1, argv+1); 536 --argc;
509 if (matches(*argv, "change") == 0) 537 ++argv;
510 return do_add(SIOCCHGTUNNEL, argc-1, argv+1);
511 if (matches(*argv, "del") == 0)
512 return do_del(argc-1, argv+1);
513 if (matches(*argv, "show") == 0 ||
514 matches(*argv, "lst") == 0 ||
515 matches(*argv, "list") == 0)
516 return do_show(argc-1, argv+1);
517 } else 538 } else
518 return do_show(0, NULL); 539 return do_show(0, NULL);
519 540 if (key < ARG_add)
520 bb_error_msg_and_die("command \"%s\" is unknown", *argv); 541 bail:
542 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
543
544 if (key == ARG_add)
545 return do_add(SIOCADDTUNNEL, argc, argv);
546 if (key == ARG_change)
547 return do_add(SIOCCHGTUNNEL, argc, argv);
548 if (key == ARG_del)
549 return do_del(argc, argv);
550 if (key == ARG_show || key == ARG_list || key == ARG_lst)
551 return do_show(argc, argv);
552 /* be gentle to gcc; avoid warning about non returning */
553 goto bail; /* never reached */
521} 554}