libc/regex: fix two buffer underruns.
[freebsd-src.git] / sbin / ifconfig / ifvxlan.c
blob91c25386ae2ecdbf0b88a27e5bca4a606129e534
1 /*-
2 * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <sys/sockio.h>
35 #include <stdlib.h>
36 #include <stdint.h>
37 #include <unistd.h>
38 #include <netdb.h>
40 #include <net/ethernet.h>
41 #include <net/if.h>
42 #include <net/if_vxlan.h>
43 #include <net/route.h>
44 #include <netinet/in.h>
46 #include <ctype.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <err.h>
52 #include <errno.h>
54 #include "ifconfig.h"
56 static struct ifvxlanparam params = {
57 .vxlp_vni = VXLAN_VNI_MAX,
60 static int
61 get_val(const char *cp, u_long *valp)
63 char *endptr;
64 u_long val;
66 errno = 0;
67 val = strtoul(cp, &endptr, 0);
68 if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
69 return (-1);
71 *valp = val;
72 return (0);
75 static int
76 do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
78 struct ifdrv ifd;
80 bzero(&ifd, sizeof(ifd));
82 strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
83 ifd.ifd_cmd = op;
84 ifd.ifd_len = argsize;
85 ifd.ifd_data = arg;
87 return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
90 static int
91 vxlan_exists(int sock)
93 struct ifvxlancfg cfg;
95 bzero(&cfg, sizeof(cfg));
97 return (do_cmd(sock, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
100 static void
101 vxlan_status(int s)
103 struct ifvxlancfg cfg;
104 char src[NI_MAXHOST], dst[NI_MAXHOST];
105 char srcport[NI_MAXSERV], dstport[NI_MAXSERV];
106 struct sockaddr *lsa, *rsa;
107 int vni, mc, ipv6;
109 bzero(&cfg, sizeof(cfg));
111 if (do_cmd(s, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0)
112 return;
114 vni = cfg.vxlc_vni;
115 lsa = &cfg.vxlc_local_sa.sa;
116 rsa = &cfg.vxlc_remote_sa.sa;
117 ipv6 = rsa->sa_family == AF_INET6;
119 /* Just report nothing if the network identity isn't set yet. */
120 if (vni >= VXLAN_VNI_MAX)
121 return;
123 if (getnameinfo(lsa, lsa->sa_len, src, sizeof(src),
124 srcport, sizeof(srcport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
125 src[0] = srcport[0] = '\0';
126 if (getnameinfo(rsa, rsa->sa_len, dst, sizeof(dst),
127 dstport, sizeof(dstport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
128 dst[0] = dstport[0] = '\0';
130 if (!ipv6) {
131 struct sockaddr_in *sin = (struct sockaddr_in *)rsa;
132 mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
133 } else {
134 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rsa;
135 mc = IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr);
138 printf("\tvxlan vni %d", vni);
139 printf(" local %s%s%s:%s", ipv6 ? "[" : "", src, ipv6 ? "]" : "",
140 srcport);
141 printf(" %s %s%s%s:%s", mc ? "group" : "remote", ipv6 ? "[" : "",
142 dst, ipv6 ? "]" : "", dstport);
144 if (verbose) {
145 printf("\n\t\tconfig: ");
146 printf("%slearning portrange %d-%d ttl %d",
147 cfg.vxlc_learn ? "" : "no", cfg.vxlc_port_min,
148 cfg.vxlc_port_max, cfg.vxlc_ttl);
149 printf("\n\t\tftable: ");
150 printf("cnt %d max %d timeout %d",
151 cfg.vxlc_ftable_cnt, cfg.vxlc_ftable_max,
152 cfg.vxlc_ftable_timeout);
155 putchar('\n');
158 #define _LOCAL_ADDR46 \
159 (VXLAN_PARAM_WITH_LOCAL_ADDR4 | VXLAN_PARAM_WITH_LOCAL_ADDR6)
160 #define _REMOTE_ADDR46 \
161 (VXLAN_PARAM_WITH_REMOTE_ADDR4 | VXLAN_PARAM_WITH_REMOTE_ADDR6)
163 static void
164 vxlan_check_params(void)
167 if ((params.vxlp_with & _LOCAL_ADDR46) == _LOCAL_ADDR46)
168 errx(1, "cannot specify both local IPv4 and IPv6 addresses");
169 if ((params.vxlp_with & _REMOTE_ADDR46) == _REMOTE_ADDR46)
170 errx(1, "cannot specify both remote IPv4 and IPv6 addresses");
171 if ((params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR4 &&
172 params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) ||
173 (params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6 &&
174 params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4))
175 errx(1, "cannot mix IPv4 and IPv6 addresses");
178 #undef _LOCAL_ADDR46
179 #undef _REMOTE_ADDR46
181 static void
182 vxlan_cb(int s, void *arg)
187 static void
188 vxlan_create(int s, struct ifreq *ifr)
191 vxlan_check_params();
193 ifr->ifr_data = (caddr_t) &params;
194 if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
195 err(1, "SIOCIFCREATE2");
198 static
199 DECL_CMD_FUNC(setvxlan_vni, arg, d)
201 struct ifvxlancmd cmd;
202 u_long val;
204 if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
205 errx(1, "invalid network identifier: %s", arg);
207 if (!vxlan_exists(s)) {
208 params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
209 params.vxlp_vni = val;
210 return;
213 bzero(&cmd, sizeof(cmd));
214 cmd.vxlcmd_vni = val;
216 if (do_cmd(s, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
217 err(1, "VXLAN_CMD_SET_VNI");
220 static
221 DECL_CMD_FUNC(setvxlan_local, addr, d)
223 struct ifvxlancmd cmd;
224 struct addrinfo *ai;
225 struct sockaddr *sa;
226 int error;
228 bzero(&cmd, sizeof(cmd));
230 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
231 errx(1, "error in parsing local address string: %s",
232 gai_strerror(error));
234 sa = ai->ai_addr;
236 switch (ai->ai_family) {
237 #ifdef INET
238 case AF_INET: {
239 struct in_addr addr = ((struct sockaddr_in *) sa)->sin_addr;
241 if (IN_MULTICAST(ntohl(addr.s_addr)))
242 errx(1, "local address cannot be multicast");
244 cmd.vxlcmd_sa.in4.sin_family = AF_INET;
245 cmd.vxlcmd_sa.in4.sin_addr = addr;
246 break;
248 #endif
249 #ifdef INET6
250 case AF_INET6: {
251 struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
253 if (IN6_IS_ADDR_MULTICAST(addr))
254 errx(1, "local address cannot be multicast");
256 cmd.vxlcmd_sa.in6.sin6_family = AF_INET6;
257 cmd.vxlcmd_sa.in6.sin6_addr = *addr;
258 break;
260 #endif
261 default:
262 errx(1, "local address %s not supported", addr);
265 freeaddrinfo(ai);
267 if (!vxlan_exists(s)) {
268 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
269 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
270 params.vxlp_local_in4 = cmd.vxlcmd_sa.in4.sin_addr;
271 } else {
272 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
273 params.vxlp_local_in6 = cmd.vxlcmd_sa.in6.sin6_addr;
275 return;
278 if (do_cmd(s, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
279 err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
282 static
283 DECL_CMD_FUNC(setvxlan_remote, addr, d)
285 struct ifvxlancmd cmd;
286 struct addrinfo *ai;
287 struct sockaddr *sa;
288 int error;
290 bzero(&cmd, sizeof(cmd));
292 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
293 errx(1, "error in parsing remote address string: %s",
294 gai_strerror(error));
296 sa = ai->ai_addr;
298 switch (ai->ai_family) {
299 #ifdef INET
300 case AF_INET: {
301 struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr;
303 if (IN_MULTICAST(ntohl(addr.s_addr)))
304 errx(1, "remote address cannot be multicast");
306 cmd.vxlcmd_sa.in4.sin_family = AF_INET;
307 cmd.vxlcmd_sa.in4.sin_addr = addr;
308 break;
310 #endif
311 #ifdef INET6
312 case AF_INET6: {
313 struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
315 if (IN6_IS_ADDR_MULTICAST(addr))
316 errx(1, "remote address cannot be multicast");
318 cmd.vxlcmd_sa.in6.sin6_family = AF_INET6;
319 cmd.vxlcmd_sa.in6.sin6_addr = *addr;
320 break;
322 #endif
323 default:
324 errx(1, "remote address %s not supported", addr);
327 freeaddrinfo(ai);
329 if (!vxlan_exists(s)) {
330 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
331 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
332 params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr;
333 } else {
334 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
335 params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr;
337 return;
340 if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
341 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
344 static
345 DECL_CMD_FUNC(setvxlan_group, addr, d)
347 struct ifvxlancmd cmd;
348 struct addrinfo *ai;
349 struct sockaddr *sa;
350 int error;
352 bzero(&cmd, sizeof(cmd));
354 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
355 errx(1, "error in parsing group address string: %s",
356 gai_strerror(error));
358 sa = ai->ai_addr;
360 switch (ai->ai_family) {
361 #ifdef INET
362 case AF_INET: {
363 struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr;
365 if (!IN_MULTICAST(ntohl(addr.s_addr)))
366 errx(1, "group address must be multicast");
368 cmd.vxlcmd_sa.in4.sin_family = AF_INET;
369 cmd.vxlcmd_sa.in4.sin_addr = addr;
370 break;
372 #endif
373 #ifdef INET6
374 case AF_INET6: {
375 struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
377 if (!IN6_IS_ADDR_MULTICAST(addr))
378 errx(1, "group address must be multicast");
380 cmd.vxlcmd_sa.in6.sin6_family = AF_INET6;
381 cmd.vxlcmd_sa.in6.sin6_addr = *addr;
382 break;
384 #endif
385 default:
386 errx(1, "group address %s not supported", addr);
389 freeaddrinfo(ai);
391 if (!vxlan_exists(s)) {
392 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
393 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
394 params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr;
395 } else {
396 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
397 params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr;
399 return;
402 if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
403 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
406 static
407 DECL_CMD_FUNC(setvxlan_local_port, arg, d)
409 struct ifvxlancmd cmd;
410 u_long val;
412 if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
413 errx(1, "invalid local port: %s", arg);
415 if (!vxlan_exists(s)) {
416 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
417 params.vxlp_local_port = val;
418 return;
421 bzero(&cmd, sizeof(cmd));
422 cmd.vxlcmd_port = val;
424 if (do_cmd(s, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
425 err(1, "VXLAN_CMD_SET_LOCAL_PORT");
428 static
429 DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
431 struct ifvxlancmd cmd;
432 u_long val;
434 if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
435 errx(1, "invalid remote port: %s", arg);
437 if (!vxlan_exists(s)) {
438 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
439 params.vxlp_remote_port = val;
440 return;
443 bzero(&cmd, sizeof(cmd));
444 cmd.vxlcmd_port = val;
446 if (do_cmd(s, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
447 err(1, "VXLAN_CMD_SET_REMOTE_PORT");
450 static
451 DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
453 struct ifvxlancmd cmd;
454 u_long min, max;
456 if (get_val(arg1, &min) < 0 || min >= UINT16_MAX)
457 errx(1, "invalid port range minimum: %s", arg1);
458 if (get_val(arg2, &max) < 0 || max >= UINT16_MAX)
459 errx(1, "invalid port range maximum: %s", arg2);
460 if (max < min)
461 errx(1, "invalid port range");
463 if (!vxlan_exists(s)) {
464 params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
465 params.vxlp_min_port = min;
466 params.vxlp_max_port = max;
467 return;
470 bzero(&cmd, sizeof(cmd));
471 cmd.vxlcmd_port_min = min;
472 cmd.vxlcmd_port_max = max;
474 if (do_cmd(s, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
475 err(1, "VXLAN_CMD_SET_PORT_RANGE");
478 static
479 DECL_CMD_FUNC(setvxlan_timeout, arg, d)
481 struct ifvxlancmd cmd;
482 u_long val;
484 if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
485 errx(1, "invalid timeout value: %s", arg);
487 if (!vxlan_exists(s)) {
488 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
489 params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
490 return;
493 bzero(&cmd, sizeof(cmd));
494 cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
496 if (do_cmd(s, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
497 err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
500 static
501 DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
503 struct ifvxlancmd cmd;
504 u_long val;
506 if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
507 errx(1, "invalid maxaddr value: %s", arg);
509 if (!vxlan_exists(s)) {
510 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
511 params.vxlp_ftable_max = val & 0xFFFFFFFF;
512 return;
515 bzero(&cmd, sizeof(cmd));
516 cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
518 if (do_cmd(s, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
519 err(1, "VXLAN_CMD_SET_FTABLE_MAX");
522 static
523 DECL_CMD_FUNC(setvxlan_dev, arg, d)
525 struct ifvxlancmd cmd;
527 if (!vxlan_exists(s)) {
528 params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF;
529 strlcpy(params.vxlp_mc_ifname, arg,
530 sizeof(params.vxlp_mc_ifname));
531 return;
534 bzero(&cmd, sizeof(cmd));
535 strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname));
537 if (do_cmd(s, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
538 err(1, "VXLAN_CMD_SET_MULTICAST_IF");
541 static
542 DECL_CMD_FUNC(setvxlan_ttl, arg, d)
544 struct ifvxlancmd cmd;
545 u_long val;
547 if (get_val(arg, &val) < 0 || val > 256)
548 errx(1, "invalid TTL value: %s", arg);
550 if (!vxlan_exists(s)) {
551 params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
552 params.vxlp_ttl = val;
553 return;
556 bzero(&cmd, sizeof(cmd));
557 cmd.vxlcmd_ttl = val;
559 if (do_cmd(s, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
560 err(1, "VXLAN_CMD_SET_TTL");
563 static
564 DECL_CMD_FUNC(setvxlan_learn, arg, d)
566 struct ifvxlancmd cmd;
568 if (!vxlan_exists(s)) {
569 params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
570 params.vxlp_learn = d;
571 return;
574 bzero(&cmd, sizeof(cmd));
575 if (d != 0)
576 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
578 if (do_cmd(s, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
579 err(1, "VXLAN_CMD_SET_LEARN");
582 static void
583 setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp)
585 struct ifvxlancmd cmd;
587 bzero(&cmd, sizeof(cmd));
588 if (d != 0)
589 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL;
591 if (do_cmd(s, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
592 err(1, "VXLAN_CMD_FLUSH");
595 static struct cmd vxlan_cmds[] = {
597 DEF_CLONE_CMD_ARG("vxlanid", setvxlan_vni),
598 DEF_CLONE_CMD_ARG("vxlanlocal", setvxlan_local),
599 DEF_CLONE_CMD_ARG("vxlanremote", setvxlan_remote),
600 DEF_CLONE_CMD_ARG("vxlangroup", setvxlan_group),
601 DEF_CLONE_CMD_ARG("vxlanlocalport", setvxlan_local_port),
602 DEF_CLONE_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
603 DEF_CLONE_CMD_ARG2("vxlanportrange", setvxlan_port_range),
604 DEF_CLONE_CMD_ARG("vxlantimeout", setvxlan_timeout),
605 DEF_CLONE_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr),
606 DEF_CLONE_CMD_ARG("vxlandev", setvxlan_dev),
607 DEF_CLONE_CMD_ARG("vxlanttl", setvxlan_ttl),
608 DEF_CLONE_CMD("vxlanlearn", 1, setvxlan_learn),
609 DEF_CLONE_CMD("-vxlanlearn", 0, setvxlan_learn),
611 DEF_CMD_ARG("vxlanvni", setvxlan_vni),
612 DEF_CMD_ARG("vxlanlocal", setvxlan_local),
613 DEF_CMD_ARG("vxlanremote", setvxlan_remote),
614 DEF_CMD_ARG("vxlangroup", setvxlan_group),
615 DEF_CMD_ARG("vxlanlocalport", setvxlan_local_port),
616 DEF_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
617 DEF_CMD_ARG2("vxlanportrange", setvxlan_port_range),
618 DEF_CMD_ARG("vxlantimeout", setvxlan_timeout),
619 DEF_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr),
620 DEF_CMD_ARG("vxlandev", setvxlan_dev),
621 DEF_CMD_ARG("vxlanttl", setvxlan_ttl),
622 DEF_CMD("vxlanlearn", 1, setvxlan_learn),
623 DEF_CMD("-vxlanlearn", 0, setvxlan_learn),
625 DEF_CMD("vxlanflush", 0, setvxlan_flush),
626 DEF_CMD("vxlanflushall", 1, setvxlan_flush),
629 static struct afswtch af_vxlan = {
630 .af_name = "af_vxlan",
631 .af_af = AF_UNSPEC,
632 .af_other_status = vxlan_status,
635 static __constructor void
636 vxlan_ctor(void)
638 size_t i;
640 for (i = 0; i < nitems(vxlan_cmds); i++)
641 cmd_register(&vxlan_cmds[i]);
642 af_register(&af_vxlan);
643 callback_register(vxlan_cb, NULL);
644 clone_setdefcallback("vxlan", vxlan_create);