]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/ifconfig/ifvxlan.c
sys/{x86,amd64}: remove one of doubled ;s
[FreeBSD/FreeBSD.git] / sbin / ifconfig / ifvxlan.c
1 /*-
2  * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org>
3  * All rights reserved.
4  *
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.
14  *
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.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <sys/sockio.h>
34
35 #include <stdlib.h>
36 #include <stdint.h>
37 #include <unistd.h>
38 #include <netdb.h>
39
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>
45
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>
53
54 #include "ifconfig.h"
55
56 static struct ifvxlanparam params = {
57         .vxlp_vni       = VXLAN_VNI_MAX,
58 };
59
60 static int
61 get_val(const char *cp, u_long *valp)
62 {
63         char *endptr;
64         u_long val;
65
66         errno = 0;
67         val = strtoul(cp, &endptr, 0);
68         if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
69                 return (-1);
70
71         *valp = val;
72         return (0);
73 }
74
75 static int
76 do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
77 {
78         struct ifdrv ifd;
79
80         bzero(&ifd, sizeof(ifd));
81
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;
86
87         return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
88 }
89
90 static int
91 vxlan_exists(int sock)
92 {
93         struct ifvxlancfg cfg;
94
95         bzero(&cfg, sizeof(cfg));
96
97         return (do_cmd(sock, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
98 }
99
100 static void
101 vxlan_status(int s)
102 {
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;
108
109         bzero(&cfg, sizeof(cfg));
110
111         if (do_cmd(s, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0)
112                 return;
113
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;
118
119         /* Just report nothing if the network identity isn't set yet. */
120         if (vni >= VXLAN_VNI_MAX)
121                 return;
122
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';
129
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);
136         }
137
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);
143
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);
153         }
154
155         putchar('\n');
156 }
157
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)
162
163 static void
164 vxlan_check_params(void)
165 {
166
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");
176 }
177
178 #undef _LOCAL_ADDR46
179 #undef _REMOTE_ADDR46
180
181 static void
182 vxlan_cb(int s, void *arg)
183 {
184
185 }
186
187 static void
188 vxlan_create(int s, struct ifreq *ifr)
189 {
190
191         vxlan_check_params();
192
193         ifr->ifr_data = (caddr_t) &params;
194         if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
195                 err(1, "SIOCIFCREATE2");
196 }
197
198 static
199 DECL_CMD_FUNC(setvxlan_vni, arg, d)
200 {
201         struct ifvxlancmd cmd;
202         u_long val;
203
204         if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
205                 errx(1, "invalid network identifier: %s", arg);
206
207         if (!vxlan_exists(s)) {
208                 params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
209                 params.vxlp_vni = val;
210                 return;
211         }
212
213         bzero(&cmd, sizeof(cmd));
214         cmd.vxlcmd_vni = val;
215
216         if (do_cmd(s, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
217                 err(1, "VXLAN_CMD_SET_VNI");
218 }
219
220 static
221 DECL_CMD_FUNC(setvxlan_local, addr, d)
222 {
223         struct ifvxlancmd cmd;
224         struct addrinfo *ai;
225         struct sockaddr *sa;
226         int error;
227
228         bzero(&cmd, sizeof(cmd));
229
230         if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
231                 errx(1, "error in parsing local address string: %s",
232                     gai_strerror(error));
233
234         sa = ai->ai_addr;
235
236         switch (ai->ai_family) {
237 #ifdef INET
238         case AF_INET: {
239                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
240
241                 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
242                         errx(1, "local address cannot be multicast");
243
244                 cmd.vxlcmd_sa.in4 = *sin;
245                 break;
246         }
247 #endif
248 #ifdef INET6
249         case AF_INET6: {
250                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
251
252                 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
253                         errx(1, "local address cannot be multicast");
254
255                 cmd.vxlcmd_sa.in6 = *sin6;
256                 break;
257         }
258 #endif
259         default:
260                 errx(1, "local address %s not supported", addr);
261         }
262
263         freeaddrinfo(ai);
264
265         if (!vxlan_exists(s)) {
266                 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
267                         params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
268                         params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4;
269                 } else {
270                         params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
271                         params.vxlp_local_sa.in6 = cmd.vxlcmd_sa.in6;
272                 }
273                 return;
274         }
275
276         if (do_cmd(s, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
277                 err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
278 }
279
280 static
281 DECL_CMD_FUNC(setvxlan_remote, addr, d)
282 {
283         struct ifvxlancmd cmd;
284         struct addrinfo *ai;
285         struct sockaddr *sa;
286         int error;
287
288         bzero(&cmd, sizeof(cmd));
289
290         if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
291                 errx(1, "error in parsing remote address string: %s",
292                     gai_strerror(error));
293
294         sa = ai->ai_addr;
295
296         switch (ai->ai_family) {
297 #ifdef INET
298         case AF_INET: {
299                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
300
301                 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
302                         errx(1, "remote address cannot be multicast");
303
304                 cmd.vxlcmd_sa.in4 = *sin;
305                 break;
306         }
307 #endif
308 #ifdef INET6
309         case AF_INET6: {
310                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
311
312                 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
313                         errx(1, "remote address cannot be multicast");
314
315                 cmd.vxlcmd_sa.in6 = *sin6;
316                 break;
317         }
318 #endif
319         default:
320                 errx(1, "remote address %s not supported", addr);
321         }
322
323         freeaddrinfo(ai);
324
325         if (!vxlan_exists(s)) {
326                 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
327                         params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
328                         params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
329                 } else {
330                         params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
331                         params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
332                 }
333                 return;
334         }
335
336         if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
337                 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
338 }
339
340 static
341 DECL_CMD_FUNC(setvxlan_group, addr, d)
342 {
343         struct ifvxlancmd cmd;
344         struct addrinfo *ai;
345         struct sockaddr *sa;
346         int error;
347
348         bzero(&cmd, sizeof(cmd));
349
350         if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
351                 errx(1, "error in parsing group address string: %s",
352                     gai_strerror(error));
353
354         sa = ai->ai_addr;
355
356         switch (ai->ai_family) {
357 #ifdef INET
358         case AF_INET: {
359                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
360
361                 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
362                         errx(1, "group address must be multicast");
363
364                 cmd.vxlcmd_sa.in4 = *sin;
365                 break;
366         }
367 #endif
368 #ifdef INET6
369         case AF_INET6: {
370                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
371
372                 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
373                         errx(1, "group address must be multicast");
374
375                 cmd.vxlcmd_sa.in6 = *sin6;
376                 break;
377         }
378 #endif
379         default:
380                 errx(1, "group address %s not supported", addr);
381         }
382
383         freeaddrinfo(ai);
384
385         if (!vxlan_exists(s)) {
386                 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
387                         params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
388                         params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
389                 } else {
390                         params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
391                         params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
392                 }
393                 return;
394         }
395
396         if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
397                 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
398 }
399
400 static
401 DECL_CMD_FUNC(setvxlan_local_port, arg, d)
402 {
403         struct ifvxlancmd cmd;
404         u_long val;
405
406         if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
407                 errx(1, "invalid local port: %s", arg);
408
409         if (!vxlan_exists(s)) {
410                 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
411                 params.vxlp_local_port = val;
412                 return;
413         }
414
415         bzero(&cmd, sizeof(cmd));
416         cmd.vxlcmd_port = val;
417
418         if (do_cmd(s, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
419                 err(1, "VXLAN_CMD_SET_LOCAL_PORT");
420 }
421
422 static
423 DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
424 {
425         struct ifvxlancmd cmd;
426         u_long val;
427
428         if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
429                 errx(1, "invalid remote port: %s", arg);
430
431         if (!vxlan_exists(s)) {
432                 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
433                 params.vxlp_remote_port = val;
434                 return;
435         }
436
437         bzero(&cmd, sizeof(cmd));
438         cmd.vxlcmd_port = val;
439
440         if (do_cmd(s, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
441                 err(1, "VXLAN_CMD_SET_REMOTE_PORT");
442 }
443
444 static
445 DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
446 {
447         struct ifvxlancmd cmd;
448         u_long min, max;
449
450         if (get_val(arg1, &min) < 0 || min >= UINT16_MAX)
451                 errx(1, "invalid port range minimum: %s", arg1);
452         if (get_val(arg2, &max) < 0 || max >= UINT16_MAX)
453                 errx(1, "invalid port range maximum: %s", arg2);
454         if (max < min)
455                 errx(1, "invalid port range");
456
457         if (!vxlan_exists(s)) {
458                 params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
459                 params.vxlp_min_port = min;
460                 params.vxlp_max_port = max;
461                 return;
462         }
463
464         bzero(&cmd, sizeof(cmd));
465         cmd.vxlcmd_port_min = min;
466         cmd.vxlcmd_port_max = max;
467
468         if (do_cmd(s, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
469                 err(1, "VXLAN_CMD_SET_PORT_RANGE");
470 }
471
472 static
473 DECL_CMD_FUNC(setvxlan_timeout, arg, d)
474 {
475         struct ifvxlancmd cmd;
476         u_long val;
477
478         if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
479                 errx(1, "invalid timeout value: %s", arg);
480
481         if (!vxlan_exists(s)) {
482                 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
483                 params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
484                 return;
485         }
486
487         bzero(&cmd, sizeof(cmd));
488         cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
489
490         if (do_cmd(s, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
491                 err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
492 }
493
494 static
495 DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
496 {
497         struct ifvxlancmd cmd;
498         u_long val;
499
500         if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
501                 errx(1, "invalid maxaddr value: %s",  arg);
502
503         if (!vxlan_exists(s)) {
504                 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
505                 params.vxlp_ftable_max = val & 0xFFFFFFFF;
506                 return;
507         }
508
509         bzero(&cmd, sizeof(cmd));
510         cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
511
512         if (do_cmd(s, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
513                 err(1, "VXLAN_CMD_SET_FTABLE_MAX");
514 }
515
516 static
517 DECL_CMD_FUNC(setvxlan_dev, arg, d)
518 {
519         struct ifvxlancmd cmd;
520
521         if (!vxlan_exists(s)) {
522                 params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF;
523                 strlcpy(params.vxlp_mc_ifname, arg,
524                     sizeof(params.vxlp_mc_ifname));
525                 return;
526         }
527
528         bzero(&cmd, sizeof(cmd));
529         strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname));
530
531         if (do_cmd(s, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
532                 err(1, "VXLAN_CMD_SET_MULTICAST_IF");
533 }
534
535 static
536 DECL_CMD_FUNC(setvxlan_ttl, arg, d)
537 {
538         struct ifvxlancmd cmd;
539         u_long val;
540
541         if (get_val(arg, &val) < 0 || val > 256)
542                 errx(1, "invalid TTL value: %s", arg);
543
544         if (!vxlan_exists(s)) {
545                 params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
546                 params.vxlp_ttl = val;
547                 return;
548         }
549
550         bzero(&cmd, sizeof(cmd));
551         cmd.vxlcmd_ttl = val;
552
553         if (do_cmd(s, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
554                 err(1, "VXLAN_CMD_SET_TTL");
555 }
556
557 static
558 DECL_CMD_FUNC(setvxlan_learn, arg, d)
559 {
560         struct ifvxlancmd cmd;
561
562         if (!vxlan_exists(s)) {
563                 params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
564                 params.vxlp_learn = d;
565                 return;
566         }
567
568         bzero(&cmd, sizeof(cmd));
569         if (d != 0)
570                 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
571
572         if (do_cmd(s, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
573                 err(1, "VXLAN_CMD_SET_LEARN");
574 }
575
576 static void
577 setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp)
578 {
579         struct ifvxlancmd cmd;
580
581         bzero(&cmd, sizeof(cmd));
582         if (d != 0)
583                 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL;
584
585         if (do_cmd(s, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
586                 err(1, "VXLAN_CMD_FLUSH");
587 }
588
589 static struct cmd vxlan_cmds[] = {
590
591         DEF_CLONE_CMD_ARG("vni",                setvxlan_vni),
592         DEF_CLONE_CMD_ARG("vxlanid",            setvxlan_vni),
593         DEF_CLONE_CMD_ARG("vxlanlocal",         setvxlan_local),
594         DEF_CLONE_CMD_ARG("vxlanremote",        setvxlan_remote),
595         DEF_CLONE_CMD_ARG("vxlangroup",         setvxlan_group),
596         DEF_CLONE_CMD_ARG("vxlanlocalport",     setvxlan_local_port),
597         DEF_CLONE_CMD_ARG("vxlanremoteport",    setvxlan_remote_port),
598         DEF_CLONE_CMD_ARG2("vxlanportrange",    setvxlan_port_range),
599         DEF_CLONE_CMD_ARG("vxlantimeout",       setvxlan_timeout),
600         DEF_CLONE_CMD_ARG("vxlanmaxaddr",       setvxlan_maxaddr),
601         DEF_CLONE_CMD_ARG("vxlandev",           setvxlan_dev),
602         DEF_CLONE_CMD_ARG("vxlanttl",           setvxlan_ttl),
603         DEF_CLONE_CMD("vxlanlearn", 1,          setvxlan_learn),
604         DEF_CLONE_CMD("-vxlanlearn", 0,         setvxlan_learn),
605
606         DEF_CMD_ARG("vni",                      setvxlan_vni),
607         DEF_CMD_ARG("vxlanid",                  setvxlan_vni),
608         DEF_CMD_ARG("vxlanlocal",               setvxlan_local),
609         DEF_CMD_ARG("vxlanremote",              setvxlan_remote),
610         DEF_CMD_ARG("vxlangroup",               setvxlan_group),
611         DEF_CMD_ARG("vxlanlocalport",           setvxlan_local_port),
612         DEF_CMD_ARG("vxlanremoteport",          setvxlan_remote_port),
613         DEF_CMD_ARG2("vxlanportrange",          setvxlan_port_range),
614         DEF_CMD_ARG("vxlantimeout",             setvxlan_timeout),
615         DEF_CMD_ARG("vxlanmaxaddr",             setvxlan_maxaddr),
616         DEF_CMD_ARG("vxlandev",                 setvxlan_dev),
617         DEF_CMD_ARG("vxlanttl",                 setvxlan_ttl),
618         DEF_CMD("vxlanlearn", 1,                setvxlan_learn),
619         DEF_CMD("-vxlanlearn", 0,               setvxlan_learn),
620
621         DEF_CMD("vxlanflush", 0,                setvxlan_flush),
622         DEF_CMD("vxlanflushall", 1,             setvxlan_flush),
623 };
624
625 static struct afswtch af_vxlan = {
626         .af_name                = "af_vxlan",
627         .af_af                  = AF_UNSPEC,
628         .af_other_status        = vxlan_status,
629 };
630
631 static __constructor void
632 vxlan_ctor(void)
633 {
634         size_t i;
635
636         for (i = 0; i < nitems(vxlan_cmds); i++)
637                 cmd_register(&vxlan_cmds[i]);
638         af_register(&af_vxlan);
639         callback_register(vxlan_cb, NULL);
640         clone_setdefcallback("vxlan", vxlan_create);
641 }