xref: /freebsd/sbin/ifconfig/ifpfsync.c (revision 1c95ec17cae22fb76d4e93c9eada78e03ca1bca6)
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