11de7b4b8SPedro F. Giffuni /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
4a9771948SGleb Smirnoff * Copyright (c) 2003 Ryan McBride. All rights reserved.
5a9771948SGleb Smirnoff * Copyright (c) 2004 Max Laier. All rights reserved.
6a9771948SGleb Smirnoff *
7a9771948SGleb Smirnoff * Redistribution and use in source and binary forms, with or without
8a9771948SGleb Smirnoff * modification, are permitted provided that the following conditions
9a9771948SGleb Smirnoff * are met:
10a9771948SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright
11a9771948SGleb Smirnoff * notice, this list of conditions and the following disclaimer.
12a9771948SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright
13a9771948SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the
14a9771948SGleb Smirnoff * documentation and/or other materials provided with the distribution.
15a9771948SGleb Smirnoff *
16a9771948SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17a9771948SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18a9771948SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19a9771948SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20a9771948SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21a9771948SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22a9771948SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23a9771948SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24a9771948SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25a9771948SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26a9771948SGleb Smirnoff * SUCH DAMAGE.
27a9771948SGleb Smirnoff */
28a9771948SGleb Smirnoff
29abd71050SEnji Cooper #include <sys/param.h>
30813c5b75SLuiz Amaral #include <sys/errno.h>
31a9771948SGleb Smirnoff #include <sys/ioctl.h>
32813c5b75SLuiz Amaral #include <sys/nv.h>
33a9771948SGleb Smirnoff #include <sys/socket.h>
34a9771948SGleb Smirnoff
35a9771948SGleb Smirnoff #include <net/if.h>
36a9771948SGleb Smirnoff #include <netinet/in.h>
37a9771948SGleb Smirnoff #include <net/pfvar.h>
38a9771948SGleb Smirnoff #include <net/if_pfsync.h>
39a9771948SGleb Smirnoff #include <net/route.h>
4010a51bf5SMax Laier #include <arpa/inet.h>
41a9771948SGleb Smirnoff
42a9771948SGleb Smirnoff #include <err.h>
4310a51bf5SMax Laier #include <netdb.h>
44a9771948SGleb Smirnoff #include <stdio.h>
45a9771948SGleb Smirnoff #include <stdlib.h>
46a9771948SGleb Smirnoff #include <string.h>
47a9771948SGleb Smirnoff #include <unistd.h>
48a9771948SGleb Smirnoff
49a9771948SGleb Smirnoff #include "ifconfig.h"
50a9771948SGleb Smirnoff
51813c5b75SLuiz Amaral static int
pfsync_do_ioctl(if_ctx * ctx,uint cmd,nvlist_t ** nvl)527fa282e6SAlexander V. Chernikov pfsync_do_ioctl(if_ctx *ctx, uint cmd, nvlist_t **nvl)
53813c5b75SLuiz Amaral {
54813c5b75SLuiz Amaral void *data;
55813c5b75SLuiz Amaral size_t nvlen;
567fa282e6SAlexander V. Chernikov struct ifreq ifr = {};
57813c5b75SLuiz Amaral
58813c5b75SLuiz Amaral data = nvlist_pack(*nvl, &nvlen);
59813c5b75SLuiz Amaral
60813c5b75SLuiz Amaral ifr.ifr_cap_nv.buffer = malloc(IFR_CAP_NV_MAXBUFSIZE);
61813c5b75SLuiz Amaral memcpy(ifr.ifr_cap_nv.buffer, data, nvlen);
62813c5b75SLuiz Amaral ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
63813c5b75SLuiz Amaral ifr.ifr_cap_nv.length = nvlen;
64813c5b75SLuiz Amaral free(data);
65813c5b75SLuiz Amaral
667fa282e6SAlexander V. Chernikov if (ioctl_ctx_ifr(ctx, cmd, &ifr) == -1) {
67813c5b75SLuiz Amaral free(ifr.ifr_cap_nv.buffer);
68813c5b75SLuiz Amaral return -1;
69813c5b75SLuiz Amaral }
70813c5b75SLuiz Amaral
71813c5b75SLuiz Amaral nvlist_destroy(*nvl);
72813c5b75SLuiz Amaral *nvl = NULL;
73813c5b75SLuiz Amaral
74813c5b75SLuiz Amaral *nvl = nvlist_unpack(ifr.ifr_cap_nv.buffer, ifr.ifr_cap_nv.length, 0);
75813c5b75SLuiz Amaral if (*nvl == NULL) {
76813c5b75SLuiz Amaral free(ifr.ifr_cap_nv.buffer);
77813c5b75SLuiz Amaral return (EIO);
78813c5b75SLuiz Amaral }
79813c5b75SLuiz Amaral
80813c5b75SLuiz Amaral free(ifr.ifr_cap_nv.buffer);
81813c5b75SLuiz Amaral return (errno);
82813c5b75SLuiz Amaral }
83813c5b75SLuiz Amaral
84813c5b75SLuiz Amaral static nvlist_t *
pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage * sa)85813c5b75SLuiz Amaral pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa)
86813c5b75SLuiz Amaral {
87813c5b75SLuiz Amaral nvlist_t *nvl;
88813c5b75SLuiz Amaral
89813c5b75SLuiz Amaral nvl = nvlist_create(0);
90813c5b75SLuiz Amaral if (nvl == NULL) {
91813c5b75SLuiz Amaral return (nvl);
92813c5b75SLuiz Amaral }
93813c5b75SLuiz Amaral
94813c5b75SLuiz Amaral switch (sa->ss_family) {
95813c5b75SLuiz Amaral #ifdef INET
96813c5b75SLuiz Amaral case AF_INET: {
97813c5b75SLuiz Amaral struct sockaddr_in *in = (struct sockaddr_in *)sa;
98813c5b75SLuiz Amaral nvlist_add_number(nvl, "af", in->sin_family);
99813c5b75SLuiz Amaral nvlist_add_binary(nvl, "address", in, sizeof(*in));
100813c5b75SLuiz Amaral break;
101813c5b75SLuiz Amaral }
102813c5b75SLuiz Amaral #endif
103813c5b75SLuiz Amaral #ifdef INET6
104813c5b75SLuiz Amaral case AF_INET6: {
105813c5b75SLuiz Amaral struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
106813c5b75SLuiz Amaral nvlist_add_number(nvl, "af", in6->sin6_family);
107813c5b75SLuiz Amaral nvlist_add_binary(nvl, "address", in6, sizeof(*in6));
108813c5b75SLuiz Amaral break;
109813c5b75SLuiz Amaral }
110813c5b75SLuiz Amaral #endif
111813c5b75SLuiz Amaral default:
112813c5b75SLuiz Amaral nvlist_add_number(nvl, "af", AF_UNSPEC);
113813c5b75SLuiz Amaral nvlist_add_binary(nvl, "address", sa, sizeof(*sa));
114813c5b75SLuiz Amaral break;
115813c5b75SLuiz Amaral }
116813c5b75SLuiz Amaral
117813c5b75SLuiz Amaral return (nvl);
118813c5b75SLuiz Amaral }
119813c5b75SLuiz Amaral
120813c5b75SLuiz Amaral static int
pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t * nvl,struct sockaddr_storage * sa)121813c5b75SLuiz Amaral pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl,
122813c5b75SLuiz Amaral struct sockaddr_storage *sa)
123813c5b75SLuiz Amaral {
124813c5b75SLuiz Amaral int af;
125813c5b75SLuiz Amaral
126cea9f49fSMateusz Guzik #if (!defined INET && !defined INET6)
127cea9f49fSMateusz Guzik (void)sa;
128cea9f49fSMateusz Guzik #endif
129cea9f49fSMateusz Guzik
130813c5b75SLuiz Amaral if (!nvlist_exists_number(nvl, "af"))
131813c5b75SLuiz Amaral return (EINVAL);
132813c5b75SLuiz Amaral if (!nvlist_exists_binary(nvl, "address"))
133813c5b75SLuiz Amaral return (EINVAL);
134813c5b75SLuiz Amaral
135813c5b75SLuiz Amaral af = nvlist_get_number(nvl, "af");
136813c5b75SLuiz Amaral
137813c5b75SLuiz Amaral switch (af) {
138813c5b75SLuiz Amaral #ifdef INET
139813c5b75SLuiz Amaral case AF_INET: {
140813c5b75SLuiz Amaral struct sockaddr_in *in = (struct sockaddr_in *)sa;
141813c5b75SLuiz Amaral size_t len;
142813c5b75SLuiz Amaral const void *addr = nvlist_get_binary(nvl, "address", &len);
143813c5b75SLuiz Amaral in->sin_family = af;
144813c5b75SLuiz Amaral if (len != sizeof(*in))
145813c5b75SLuiz Amaral return (EINVAL);
146813c5b75SLuiz Amaral
147813c5b75SLuiz Amaral memcpy(in, addr, sizeof(*in));
148813c5b75SLuiz Amaral break;
149813c5b75SLuiz Amaral }
150813c5b75SLuiz Amaral #endif
151813c5b75SLuiz Amaral #ifdef INET6
152813c5b75SLuiz Amaral case AF_INET6: {
153813c5b75SLuiz Amaral struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
154813c5b75SLuiz Amaral size_t len;
155813c5b75SLuiz Amaral const void *addr = nvlist_get_binary(nvl, "address", &len);
156813c5b75SLuiz Amaral if (len != sizeof(*in6))
157813c5b75SLuiz Amaral return (EINVAL);
158813c5b75SLuiz Amaral
159813c5b75SLuiz Amaral memcpy(in6, addr, sizeof(*in6));
160813c5b75SLuiz Amaral break;
161813c5b75SLuiz Amaral }
162813c5b75SLuiz Amaral #endif
163813c5b75SLuiz Amaral default:
164813c5b75SLuiz Amaral return (EINVAL);
165813c5b75SLuiz Amaral }
166813c5b75SLuiz Amaral
167813c5b75SLuiz Amaral return (0);
168813c5b75SLuiz Amaral }
169813c5b75SLuiz Amaral
1706e3a9d7fSAlexander V. Chernikov static void
setpfsync_syncdev(if_ctx * ctx,const char * val,int dummy __unused)1716e3a9d7fSAlexander V. Chernikov setpfsync_syncdev(if_ctx *ctx, const char *val, int dummy __unused)
172a9771948SGleb Smirnoff {
173813c5b75SLuiz Amaral nvlist_t *nvl = nvlist_create(0);
174a9771948SGleb Smirnoff
175813c5b75SLuiz Amaral if (strlen(val) > IFNAMSIZ)
176813c5b75SLuiz Amaral errx(1, "interface name %s is too long", val);
177a9771948SGleb Smirnoff
1787fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
179813c5b75SLuiz Amaral err(1, "SIOCGETPFSYNCNV");
180a9771948SGleb Smirnoff
181813c5b75SLuiz Amaral if (nvlist_exists_string(nvl, "syncdev"))
182813c5b75SLuiz Amaral nvlist_free_string(nvl, "syncdev");
183a9771948SGleb Smirnoff
184813c5b75SLuiz Amaral nvlist_add_string(nvl, "syncdev", val);
185813c5b75SLuiz Amaral
1867fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
187813c5b75SLuiz Amaral err(1, "SIOCSETPFSYNCNV");
188a9771948SGleb Smirnoff }
189a9771948SGleb Smirnoff
1906e3a9d7fSAlexander V. Chernikov static void
unsetpfsync_syncdev(if_ctx * ctx,const char * val __unused,int dummy __unused)1910c2beef7SAlexander V. Chernikov unsetpfsync_syncdev(if_ctx *ctx, const char *val __unused, int dummy __unused)
192a9771948SGleb Smirnoff {
193813c5b75SLuiz Amaral nvlist_t *nvl = nvlist_create(0);
194a9771948SGleb Smirnoff
1957fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
196813c5b75SLuiz Amaral err(1, "SIOCGETPFSYNCNV");
197a9771948SGleb Smirnoff
198813c5b75SLuiz Amaral if (nvlist_exists_string(nvl, "syncdev"))
199813c5b75SLuiz Amaral nvlist_free_string(nvl, "syncdev");
200a9771948SGleb Smirnoff
201813c5b75SLuiz Amaral nvlist_add_string(nvl, "syncdev", "");
202a9771948SGleb Smirnoff
2037fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
204813c5b75SLuiz Amaral err(1, "SIOCSETPFSYNCNV");
205a9771948SGleb Smirnoff }
206a9771948SGleb Smirnoff
2076e3a9d7fSAlexander V. Chernikov static void
setpfsync_syncpeer(if_ctx * ctx,const char * val,int dummy __unused)2086e3a9d7fSAlexander V. Chernikov setpfsync_syncpeer(if_ctx *ctx, const char *val, int dummy __unused)
20910a51bf5SMax Laier {
210813c5b75SLuiz Amaral struct addrinfo *peerres;
211813c5b75SLuiz Amaral struct sockaddr_storage addr;
21210a51bf5SMax Laier int ecode;
21310a51bf5SMax Laier
214813c5b75SLuiz Amaral nvlist_t *nvl = nvlist_create(0);
21510a51bf5SMax Laier
2167fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
217813c5b75SLuiz Amaral err(1, "SIOCGETPFSYNCNV");
21810a51bf5SMax Laier
219813c5b75SLuiz Amaral if ((ecode = getaddrinfo(val, NULL, NULL, &peerres)) != 0)
22010a51bf5SMax Laier errx(1, "error in parsing address string: %s",
22110a51bf5SMax Laier gai_strerror(ecode));
22210a51bf5SMax Laier
223813c5b75SLuiz Amaral switch (peerres->ai_family) {
224813c5b75SLuiz Amaral #ifdef INET
225813c5b75SLuiz Amaral case AF_INET: {
2260c2beef7SAlexander V. Chernikov struct sockaddr_in *sin = satosin(peerres->ai_addr);
22710a51bf5SMax Laier
228813c5b75SLuiz Amaral memcpy(&addr, sin, sizeof(*sin));
229813c5b75SLuiz Amaral break;
230813c5b75SLuiz Amaral }
231813c5b75SLuiz Amaral #endif
232*6fc7fc2dSLuiz Amaral #ifdef INET6
233*6fc7fc2dSLuiz Amaral case AF_INET6: {
234*6fc7fc2dSLuiz Amaral struct sockaddr_in6 *sin6 = satosin6(peerres->ai_addr);
235*6fc7fc2dSLuiz Amaral
236*6fc7fc2dSLuiz Amaral memcpy(&addr, sin6, sizeof(*sin6));
237*6fc7fc2dSLuiz Amaral break;
238*6fc7fc2dSLuiz Amaral }
239*6fc7fc2dSLuiz Amaral #endif
240813c5b75SLuiz Amaral default:
241813c5b75SLuiz Amaral errx(1, "syncpeer address %s not supported", val);
242813c5b75SLuiz Amaral }
243813c5b75SLuiz Amaral
244813c5b75SLuiz Amaral if (nvlist_exists_nvlist(nvl, "syncpeer"))
245813c5b75SLuiz Amaral nvlist_free_nvlist(nvl, "syncpeer");
246813c5b75SLuiz Amaral
247813c5b75SLuiz Amaral nvlist_add_nvlist(nvl, "syncpeer",
248813c5b75SLuiz Amaral pfsync_sockaddr_to_syncpeer_nvlist(&addr));
249813c5b75SLuiz Amaral
2507fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
251813c5b75SLuiz Amaral err(1, "SIOCSETPFSYNCNV");
252813c5b75SLuiz Amaral
253813c5b75SLuiz Amaral nvlist_destroy(nvl);
2546223cc33SAlan Somers freeaddrinfo(peerres);
25510a51bf5SMax Laier }
25610a51bf5SMax Laier
2576e3a9d7fSAlexander V. Chernikov static void
unsetpfsync_syncpeer(if_ctx * ctx,const char * val __unused,int dummy __unused)2580c2beef7SAlexander V. Chernikov unsetpfsync_syncpeer(if_ctx *ctx, const char *val __unused, int dummy __unused)
25910a51bf5SMax Laier {
260813c5b75SLuiz Amaral struct sockaddr_storage addr;
261813c5b75SLuiz Amaral memset(&addr, 0, sizeof(addr));
26210a51bf5SMax Laier
263813c5b75SLuiz Amaral nvlist_t *nvl = nvlist_create(0);
26410a51bf5SMax Laier
2657fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
266813c5b75SLuiz Amaral err(1, "SIOCGETPFSYNCNV");
26710a51bf5SMax Laier
268813c5b75SLuiz Amaral if (nvlist_exists_nvlist(nvl, "syncpeer"))
269813c5b75SLuiz Amaral nvlist_free_nvlist(nvl, "syncpeer");
27010a51bf5SMax Laier
271813c5b75SLuiz Amaral nvlist_add_nvlist(nvl, "syncpeer",
272813c5b75SLuiz Amaral pfsync_sockaddr_to_syncpeer_nvlist(&addr));
273813c5b75SLuiz Amaral
2747fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
275813c5b75SLuiz Amaral err(1, "SIOCSETPFSYNCNV");
276813c5b75SLuiz Amaral
277813c5b75SLuiz Amaral nvlist_destroy(nvl);
27810a51bf5SMax Laier }
27910a51bf5SMax Laier
2806e3a9d7fSAlexander V. Chernikov static void
setpfsync_maxupd(if_ctx * ctx,const char * val,int dummy __unused)2816e3a9d7fSAlexander V. Chernikov setpfsync_maxupd(if_ctx *ctx, const char *val, int dummy __unused)
282a9771948SGleb Smirnoff {
28310a51bf5SMax Laier int maxupdates;
284813c5b75SLuiz Amaral nvlist_t *nvl = nvlist_create(0);
285a9771948SGleb Smirnoff
286a9771948SGleb Smirnoff maxupdates = atoi(val);
28710a51bf5SMax Laier if ((maxupdates < 0) || (maxupdates > 255))
28810a51bf5SMax Laier errx(1, "maxupd %s: out of range", val);
289a9771948SGleb Smirnoff
2907fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
291813c5b75SLuiz Amaral err(1, "SIOCGETPFSYNCNV");
292a9771948SGleb Smirnoff
293813c5b75SLuiz Amaral nvlist_free_number(nvl, "maxupdates");
294813c5b75SLuiz Amaral nvlist_add_number(nvl, "maxupdates", maxupdates);
295a9771948SGleb Smirnoff
2967fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
297813c5b75SLuiz Amaral err(1, "SIOCSETPFSYNCNV");
298a9771948SGleb Smirnoff
299813c5b75SLuiz Amaral nvlist_destroy(nvl);
300a9771948SGleb Smirnoff }
301a9771948SGleb Smirnoff
3026e3a9d7fSAlexander V. Chernikov static void
setpfsync_defer(if_ctx * ctx,const char * val __unused,int d)3030c2beef7SAlexander V. Chernikov setpfsync_defer(if_ctx *ctx, const char *val __unused, int d)
30474e9ff65SGleb Smirnoff {
305813c5b75SLuiz Amaral nvlist_t *nvl = nvlist_create(0);
30674e9ff65SGleb Smirnoff
3077fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
308813c5b75SLuiz Amaral err(1, "SIOCGETPFSYNCNV");
30974e9ff65SGleb Smirnoff
310813c5b75SLuiz Amaral nvlist_free_number(nvl, "flags");
311813c5b75SLuiz Amaral nvlist_add_number(nvl, "flags", d ? PFSYNCF_DEFER : 0);
31274e9ff65SGleb Smirnoff
3137fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
314813c5b75SLuiz Amaral err(1, "SIOCSETPFSYNCNV");
315813c5b75SLuiz Amaral
316813c5b75SLuiz Amaral nvlist_destroy(nvl);
31774e9ff65SGleb Smirnoff }
31874e9ff65SGleb Smirnoff
3196e3a9d7fSAlexander V. Chernikov static void
setpfsync_version(if_ctx * ctx,const char * val,int dummy __unused)3204bf98559SKajetan Staszkiewicz setpfsync_version(if_ctx *ctx, const char *val, int dummy __unused)
3214bf98559SKajetan Staszkiewicz {
3224bf98559SKajetan Staszkiewicz int version;
3234bf98559SKajetan Staszkiewicz nvlist_t *nvl = nvlist_create(0);
3244bf98559SKajetan Staszkiewicz
3254bf98559SKajetan Staszkiewicz /* Don't verify, kernel knows which versions are supported.*/
3264bf98559SKajetan Staszkiewicz version = atoi(val);
3274bf98559SKajetan Staszkiewicz
3287fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
3294bf98559SKajetan Staszkiewicz err(1, "SIOCGETPFSYNCNV");
3304bf98559SKajetan Staszkiewicz
3314bf98559SKajetan Staszkiewicz nvlist_free_number(nvl, "version");
3324bf98559SKajetan Staszkiewicz nvlist_add_number(nvl, "version", version);
3334bf98559SKajetan Staszkiewicz
3347fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
3354bf98559SKajetan Staszkiewicz err(1, "SIOCSETPFSYNCNV");
3364bf98559SKajetan Staszkiewicz
3374bf98559SKajetan Staszkiewicz nvlist_destroy(nvl);
3384bf98559SKajetan Staszkiewicz }
3394bf98559SKajetan Staszkiewicz
3404bf98559SKajetan Staszkiewicz static void
pfsync_status(if_ctx * ctx)3416e3a9d7fSAlexander V. Chernikov pfsync_status(if_ctx *ctx)
342a9771948SGleb Smirnoff {
343813c5b75SLuiz Amaral nvlist_t *nvl;
344813c5b75SLuiz Amaral char syncdev[IFNAMSIZ];
345813c5b75SLuiz Amaral char syncpeer_str[NI_MAXHOST];
346813c5b75SLuiz Amaral struct sockaddr_storage syncpeer;
34744cd85d4SAlexander V. Chernikov int maxupdates = 0;
34844cd85d4SAlexander V. Chernikov int flags = 0;
3494bf98559SKajetan Staszkiewicz int version;
350813c5b75SLuiz Amaral int error;
351a9771948SGleb Smirnoff
352813c5b75SLuiz Amaral nvl = nvlist_create(0);
353a9771948SGleb Smirnoff
3547fa282e6SAlexander V. Chernikov if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) {
355813c5b75SLuiz Amaral nvlist_destroy(nvl);
356a9771948SGleb Smirnoff return;
357813c5b75SLuiz Amaral }
358a9771948SGleb Smirnoff
359813c5b75SLuiz Amaral memset((char *)&syncdev, 0, IFNAMSIZ);
360813c5b75SLuiz Amaral if (nvlist_exists_string(nvl, "syncdev"))
361813c5b75SLuiz Amaral strlcpy(syncdev, nvlist_get_string(nvl, "syncdev"),
362813c5b75SLuiz Amaral IFNAMSIZ);
363813c5b75SLuiz Amaral if (nvlist_exists_number(nvl, "maxupdates"))
364813c5b75SLuiz Amaral maxupdates = nvlist_get_number(nvl, "maxupdates");
3654bf98559SKajetan Staszkiewicz if (nvlist_exists_number(nvl, "version"))
3664bf98559SKajetan Staszkiewicz version = nvlist_get_number(nvl, "version");
367813c5b75SLuiz Amaral if (nvlist_exists_number(nvl, "flags"))
368813c5b75SLuiz Amaral flags = nvlist_get_number(nvl, "flags");
369813c5b75SLuiz Amaral if (nvlist_exists_nvlist(nvl, "syncpeer")) {
370813c5b75SLuiz Amaral pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl,
371813c5b75SLuiz Amaral "syncpeer"),
372813c5b75SLuiz Amaral &syncpeer);
373813c5b75SLuiz Amaral }
374813c5b75SLuiz Amaral
375813c5b75SLuiz Amaral nvlist_destroy(nvl);
376813c5b75SLuiz Amaral
37711c4984fSGleb Smirnoff printf("\t");
37811c4984fSGleb Smirnoff
379813c5b75SLuiz Amaral if (syncdev[0] != '\0')
380813c5b75SLuiz Amaral printf("syncdev: %s ", syncdev);
38111c4984fSGleb Smirnoff
382*6fc7fc2dSLuiz Amaral if ((syncpeer.ss_family == AF_INET &&
383813c5b75SLuiz Amaral ((struct sockaddr_in *)&syncpeer)->sin_addr.s_addr !=
384*6fc7fc2dSLuiz Amaral htonl(INADDR_PFSYNC_GROUP)) || syncpeer.ss_family == AF_INET6) {
385813c5b75SLuiz Amaral
386813c5b75SLuiz Amaral struct sockaddr *syncpeer_sa =
387813c5b75SLuiz Amaral (struct sockaddr *)&syncpeer;
388813c5b75SLuiz Amaral if ((error = getnameinfo(syncpeer_sa, syncpeer_sa->sa_len,
389813c5b75SLuiz Amaral syncpeer_str, sizeof(syncpeer_str), NULL, 0,
390813c5b75SLuiz Amaral NI_NUMERICHOST)) != 0)
391813c5b75SLuiz Amaral errx(1, "getnameinfo: %s", gai_strerror(error));
392813c5b75SLuiz Amaral printf("syncpeer: %s ", syncpeer_str);
39374e9ff65SGleb Smirnoff }
394813c5b75SLuiz Amaral
395813c5b75SLuiz Amaral printf("maxupd: %d ", maxupdates);
3964bf98559SKajetan Staszkiewicz printf("defer: %s ", (flags & PFSYNCF_DEFER) ? "on" : "off");
3974bf98559SKajetan Staszkiewicz printf("version: %d\n", version);
398813c5b75SLuiz Amaral printf("\tsyncok: %d\n", (flags & PFSYNCF_OK) ? 1 : 0);
399a9771948SGleb Smirnoff }
400a9771948SGleb Smirnoff
401a9771948SGleb Smirnoff static struct cmd pfsync_cmds[] = {
40210a51bf5SMax Laier DEF_CMD_ARG("syncdev", setpfsync_syncdev),
40310a51bf5SMax Laier DEF_CMD("-syncdev", 1, unsetpfsync_syncdev),
40410a51bf5SMax Laier DEF_CMD_ARG("syncif", setpfsync_syncdev),
40510a51bf5SMax Laier DEF_CMD("-syncif", 1, unsetpfsync_syncdev),
40610a51bf5SMax Laier DEF_CMD_ARG("syncpeer", setpfsync_syncpeer),
40710a51bf5SMax Laier DEF_CMD("-syncpeer", 1, unsetpfsync_syncpeer),
40874e9ff65SGleb Smirnoff DEF_CMD_ARG("maxupd", setpfsync_maxupd),
40974e9ff65SGleb Smirnoff DEF_CMD("defer", 1, setpfsync_defer),
41074e9ff65SGleb Smirnoff DEF_CMD("-defer", 0, setpfsync_defer),
4114bf98559SKajetan Staszkiewicz DEF_CMD_ARG("version", setpfsync_version),
412a9771948SGleb Smirnoff };
413a9771948SGleb Smirnoff static struct afswtch af_pfsync = {
414a9771948SGleb Smirnoff .af_name = "af_pfsync",
415a9771948SGleb Smirnoff .af_af = AF_UNSPEC,
416ef3abbe8SGleb Smirnoff .af_other_status = pfsync_status,
417a9771948SGleb Smirnoff };
418a9771948SGleb Smirnoff
419a9771948SGleb Smirnoff static __constructor void
pfsync_ctor(void)420a9771948SGleb Smirnoff pfsync_ctor(void)
421a9771948SGleb Smirnoff {
42244cd85d4SAlexander V. Chernikov for (size_t i = 0; i < nitems(pfsync_cmds); i++)
423a9771948SGleb Smirnoff cmd_register(&pfsync_cmds[i]);
424a9771948SGleb Smirnoff af_register(&af_pfsync);
425a9771948SGleb Smirnoff }
426