xref: /freebsd/sbin/ifconfig/ifpfsync.c (revision 44cd85d42e5ddb1d5811b388218e14582e078bf8)
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  * $FreeBSD$
29a9771948SGleb Smirnoff  */
30a9771948SGleb Smirnoff 
31abd71050SEnji Cooper #include <sys/param.h>
32813c5b75SLuiz Amaral #include <sys/errno.h>
33a9771948SGleb Smirnoff #include <sys/ioctl.h>
34813c5b75SLuiz Amaral #include <sys/nv.h>
35a9771948SGleb Smirnoff #include <sys/socket.h>
36a9771948SGleb Smirnoff 
37a9771948SGleb Smirnoff #include <net/if.h>
38a9771948SGleb Smirnoff #include <netinet/in.h>
39a9771948SGleb Smirnoff #include <net/pfvar.h>
40a9771948SGleb Smirnoff #include <net/if_pfsync.h>
41a9771948SGleb Smirnoff #include <net/route.h>
4210a51bf5SMax Laier #include <arpa/inet.h>
43a9771948SGleb Smirnoff 
44a9771948SGleb Smirnoff #include <err.h>
4510a51bf5SMax Laier #include <netdb.h>
46a9771948SGleb Smirnoff #include <stdio.h>
47a9771948SGleb Smirnoff #include <stdlib.h>
48a9771948SGleb Smirnoff #include <string.h>
49a9771948SGleb Smirnoff #include <unistd.h>
50a9771948SGleb Smirnoff 
51a9771948SGleb Smirnoff #include "ifconfig.h"
52a9771948SGleb Smirnoff 
5310a51bf5SMax Laier void setpfsync_syncdev(const char *, int, int, const struct afswtch *);
5410a51bf5SMax Laier void unsetpfsync_syncdev(const char *, int, int, const struct afswtch *);
5510a51bf5SMax Laier void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
5610a51bf5SMax Laier void unsetpfsync_syncpeer(const char *, int, int, const struct afswtch *);
5710a51bf5SMax Laier void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
5810a51bf5SMax Laier void setpfsync_maxupd(const char *, int, int, const struct afswtch *);
5974e9ff65SGleb Smirnoff void setpfsync_defer(const char *, int, int, const struct afswtch *);
60ef3abbe8SGleb Smirnoff void pfsync_status(int);
61a9771948SGleb Smirnoff 
62813c5b75SLuiz Amaral static int
63813c5b75SLuiz Amaral pfsync_do_ioctl(int s, uint cmd, nvlist_t **nvl)
64813c5b75SLuiz Amaral {
65813c5b75SLuiz Amaral 	void *data;
66813c5b75SLuiz Amaral 	size_t nvlen;
67813c5b75SLuiz Amaral 
68813c5b75SLuiz Amaral 	data = nvlist_pack(*nvl, &nvlen);
69813c5b75SLuiz Amaral 
70813c5b75SLuiz Amaral 	ifr.ifr_cap_nv.buffer = malloc(IFR_CAP_NV_MAXBUFSIZE);
71813c5b75SLuiz Amaral 	memcpy(ifr.ifr_cap_nv.buffer, data, nvlen);
72813c5b75SLuiz Amaral 	ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
73813c5b75SLuiz Amaral 	ifr.ifr_cap_nv.length = nvlen;
74813c5b75SLuiz Amaral 	free(data);
75813c5b75SLuiz Amaral 
76813c5b75SLuiz Amaral 	if (ioctl(s, cmd, (caddr_t)&ifr) == -1) {
77813c5b75SLuiz Amaral 		free(ifr.ifr_cap_nv.buffer);
78813c5b75SLuiz Amaral 		return -1;
79813c5b75SLuiz Amaral 	}
80813c5b75SLuiz Amaral 
81813c5b75SLuiz Amaral 	nvlist_destroy(*nvl);
82813c5b75SLuiz Amaral 	*nvl = NULL;
83813c5b75SLuiz Amaral 
84813c5b75SLuiz Amaral 	*nvl = nvlist_unpack(ifr.ifr_cap_nv.buffer, ifr.ifr_cap_nv.length, 0);
85813c5b75SLuiz Amaral 	if (*nvl == NULL) {
86813c5b75SLuiz Amaral 		free(ifr.ifr_cap_nv.buffer);
87813c5b75SLuiz Amaral 		return (EIO);
88813c5b75SLuiz Amaral 	}
89813c5b75SLuiz Amaral 
90813c5b75SLuiz Amaral 	free(ifr.ifr_cap_nv.buffer);
91813c5b75SLuiz Amaral 	return (errno);
92813c5b75SLuiz Amaral }
93813c5b75SLuiz Amaral 
94813c5b75SLuiz Amaral static nvlist_t *
95813c5b75SLuiz Amaral pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa)
96813c5b75SLuiz Amaral {
97813c5b75SLuiz Amaral 	nvlist_t *nvl;
98813c5b75SLuiz Amaral 
99813c5b75SLuiz Amaral 	nvl = nvlist_create(0);
100813c5b75SLuiz Amaral 	if (nvl == NULL) {
101813c5b75SLuiz Amaral 		return (nvl);
102813c5b75SLuiz Amaral 	}
103813c5b75SLuiz Amaral 
104813c5b75SLuiz Amaral 	switch (sa->ss_family) {
105813c5b75SLuiz Amaral #ifdef INET
106813c5b75SLuiz Amaral 	case AF_INET: {
107813c5b75SLuiz Amaral 		struct sockaddr_in *in = (struct sockaddr_in *)sa;
108813c5b75SLuiz Amaral 		nvlist_add_number(nvl, "af", in->sin_family);
109813c5b75SLuiz Amaral 		nvlist_add_binary(nvl, "address", in, sizeof(*in));
110813c5b75SLuiz Amaral 		break;
111813c5b75SLuiz Amaral 	}
112813c5b75SLuiz Amaral #endif
113813c5b75SLuiz Amaral #ifdef INET6
114813c5b75SLuiz Amaral 	case AF_INET6: {
115813c5b75SLuiz Amaral 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
116813c5b75SLuiz Amaral 		nvlist_add_number(nvl, "af", in6->sin6_family);
117813c5b75SLuiz Amaral 		nvlist_add_binary(nvl, "address", in6, sizeof(*in6));
118813c5b75SLuiz Amaral 		break;
119813c5b75SLuiz Amaral 	}
120813c5b75SLuiz Amaral #endif
121813c5b75SLuiz Amaral 	default:
122813c5b75SLuiz Amaral 		nvlist_add_number(nvl, "af", AF_UNSPEC);
123813c5b75SLuiz Amaral 		nvlist_add_binary(nvl, "address", sa, sizeof(*sa));
124813c5b75SLuiz Amaral 		break;
125813c5b75SLuiz Amaral 	}
126813c5b75SLuiz Amaral 
127813c5b75SLuiz Amaral 	return (nvl);
128813c5b75SLuiz Amaral }
129813c5b75SLuiz Amaral 
130813c5b75SLuiz Amaral static int
131813c5b75SLuiz Amaral pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl,
132813c5b75SLuiz Amaral     struct sockaddr_storage *sa)
133813c5b75SLuiz Amaral {
134813c5b75SLuiz Amaral 	int af;
135813c5b75SLuiz Amaral 
136813c5b75SLuiz Amaral 	if (!nvlist_exists_number(nvl, "af"))
137813c5b75SLuiz Amaral 		return (EINVAL);
138813c5b75SLuiz Amaral 	if (!nvlist_exists_binary(nvl, "address"))
139813c5b75SLuiz Amaral 		return (EINVAL);
140813c5b75SLuiz Amaral 
141813c5b75SLuiz Amaral 	af = nvlist_get_number(nvl, "af");
142813c5b75SLuiz Amaral 
143813c5b75SLuiz Amaral 	switch (af) {
144813c5b75SLuiz Amaral #ifdef INET
145813c5b75SLuiz Amaral 	case AF_INET: {
146813c5b75SLuiz Amaral 		struct sockaddr_in *in = (struct sockaddr_in *)sa;
147813c5b75SLuiz Amaral 		size_t len;
148813c5b75SLuiz Amaral 		const void *addr = nvlist_get_binary(nvl, "address", &len);
149813c5b75SLuiz Amaral 		in->sin_family = af;
150813c5b75SLuiz Amaral 		if (len != sizeof(*in))
151813c5b75SLuiz Amaral 			return (EINVAL);
152813c5b75SLuiz Amaral 
153813c5b75SLuiz Amaral 		memcpy(in, addr, sizeof(*in));
154813c5b75SLuiz Amaral 		break;
155813c5b75SLuiz Amaral 	}
156813c5b75SLuiz Amaral #endif
157813c5b75SLuiz Amaral #ifdef INET6
158813c5b75SLuiz Amaral 	case AF_INET6: {
159813c5b75SLuiz Amaral 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
160813c5b75SLuiz Amaral 		size_t len;
161813c5b75SLuiz Amaral 		const void *addr = nvlist_get_binary(nvl, "address", &len);
162813c5b75SLuiz Amaral 		if (len != sizeof(*in6))
163813c5b75SLuiz Amaral 			return (EINVAL);
164813c5b75SLuiz Amaral 
165813c5b75SLuiz Amaral 		memcpy(in6, addr, sizeof(*in6));
166813c5b75SLuiz Amaral 		break;
167813c5b75SLuiz Amaral 	}
168813c5b75SLuiz Amaral #endif
169813c5b75SLuiz Amaral 	default:
170813c5b75SLuiz Amaral 		return (EINVAL);
171813c5b75SLuiz Amaral 	}
172813c5b75SLuiz Amaral 
173813c5b75SLuiz Amaral 	return (0);
174813c5b75SLuiz Amaral }
175813c5b75SLuiz Amaral 
176a9771948SGleb Smirnoff void
17710a51bf5SMax Laier setpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
178a9771948SGleb Smirnoff {
179813c5b75SLuiz Amaral 	nvlist_t *nvl = nvlist_create(0);
180a9771948SGleb Smirnoff 
181813c5b75SLuiz Amaral 	if (strlen(val) > IFNAMSIZ)
182813c5b75SLuiz Amaral 		errx(1, "interface name %s is too long", val);
183a9771948SGleb Smirnoff 
184813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
185813c5b75SLuiz Amaral 		err(1, "SIOCGETPFSYNCNV");
186a9771948SGleb Smirnoff 
187813c5b75SLuiz Amaral 	if (nvlist_exists_string(nvl, "syncdev"))
188813c5b75SLuiz Amaral 		nvlist_free_string(nvl, "syncdev");
189a9771948SGleb Smirnoff 
190813c5b75SLuiz Amaral 	nvlist_add_string(nvl, "syncdev", val);
191813c5b75SLuiz Amaral 
192813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
193813c5b75SLuiz Amaral 		err(1, "SIOCSETPFSYNCNV");
194a9771948SGleb Smirnoff }
195a9771948SGleb Smirnoff 
19610a51bf5SMax Laier /* ARGSUSED */
197a9771948SGleb Smirnoff void
19810a51bf5SMax Laier unsetpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
199a9771948SGleb Smirnoff {
200813c5b75SLuiz Amaral 	nvlist_t *nvl = nvlist_create(0);
201a9771948SGleb Smirnoff 
202813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
203813c5b75SLuiz Amaral 		err(1, "SIOCGETPFSYNCNV");
204a9771948SGleb Smirnoff 
205813c5b75SLuiz Amaral 	if (nvlist_exists_string(nvl, "syncdev"))
206813c5b75SLuiz Amaral 		nvlist_free_string(nvl, "syncdev");
207a9771948SGleb Smirnoff 
208813c5b75SLuiz Amaral 	nvlist_add_string(nvl, "syncdev", "");
209a9771948SGleb Smirnoff 
210813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
211813c5b75SLuiz Amaral 		err(1, "SIOCSETPFSYNCNV");
212a9771948SGleb Smirnoff }
213a9771948SGleb Smirnoff 
21410a51bf5SMax Laier /* ARGSUSED */
21510a51bf5SMax Laier void
21610a51bf5SMax Laier setpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
21710a51bf5SMax Laier {
218813c5b75SLuiz Amaral 	struct addrinfo *peerres;
219813c5b75SLuiz Amaral 	struct sockaddr_storage addr;
22010a51bf5SMax Laier 	int ecode;
22110a51bf5SMax Laier 
222813c5b75SLuiz Amaral 	nvlist_t *nvl = nvlist_create(0);
22310a51bf5SMax Laier 
224813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
225813c5b75SLuiz Amaral 		err(1, "SIOCGETPFSYNCNV");
22610a51bf5SMax Laier 
227813c5b75SLuiz Amaral 	if ((ecode = getaddrinfo(val, NULL, NULL, &peerres)) != 0)
22810a51bf5SMax Laier 		errx(1, "error in parsing address string: %s",
22910a51bf5SMax Laier 		    gai_strerror(ecode));
23010a51bf5SMax Laier 
231813c5b75SLuiz Amaral 	switch (peerres->ai_family) {
232813c5b75SLuiz Amaral #ifdef INET
233813c5b75SLuiz Amaral 	case AF_INET: {
234813c5b75SLuiz Amaral 		struct sockaddr_in *sin = (struct sockaddr_in *)
235813c5b75SLuiz Amaral 					      peerres->ai_addr;
23610a51bf5SMax Laier 
237813c5b75SLuiz Amaral 		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
238813c5b75SLuiz Amaral 			errx(1, "syncpeer address cannot be multicast");
23910a51bf5SMax Laier 
240813c5b75SLuiz Amaral 		memcpy(&addr, sin, sizeof(*sin));
241813c5b75SLuiz Amaral 		break;
242813c5b75SLuiz Amaral 	}
243813c5b75SLuiz Amaral #endif
244813c5b75SLuiz Amaral 	default:
245813c5b75SLuiz Amaral 		errx(1, "syncpeer address %s not supported", val);
246813c5b75SLuiz Amaral 	}
247813c5b75SLuiz Amaral 
248813c5b75SLuiz Amaral 	if (nvlist_exists_nvlist(nvl, "syncpeer"))
249813c5b75SLuiz Amaral 		nvlist_free_nvlist(nvl, "syncpeer");
250813c5b75SLuiz Amaral 
251813c5b75SLuiz Amaral 	nvlist_add_nvlist(nvl, "syncpeer",
252813c5b75SLuiz Amaral 	    pfsync_sockaddr_to_syncpeer_nvlist(&addr));
253813c5b75SLuiz Amaral 
254813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
255813c5b75SLuiz Amaral 		err(1, "SIOCSETPFSYNCNV");
256813c5b75SLuiz Amaral 
257813c5b75SLuiz Amaral 	nvlist_destroy(nvl);
2586223cc33SAlan Somers 	freeaddrinfo(peerres);
25910a51bf5SMax Laier }
26010a51bf5SMax Laier 
26110a51bf5SMax Laier /* ARGSUSED */
26210a51bf5SMax Laier void
26310a51bf5SMax Laier unsetpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
26410a51bf5SMax Laier {
265813c5b75SLuiz Amaral 	struct sockaddr_storage addr;
266813c5b75SLuiz Amaral 	memset(&addr, 0, sizeof(addr));
26710a51bf5SMax Laier 
268813c5b75SLuiz Amaral 	nvlist_t *nvl = nvlist_create(0);
26910a51bf5SMax Laier 
270813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
271813c5b75SLuiz Amaral 		err(1, "SIOCGETPFSYNCNV");
27210a51bf5SMax Laier 
273813c5b75SLuiz Amaral 	if (nvlist_exists_nvlist(nvl, "syncpeer"))
274813c5b75SLuiz Amaral 		nvlist_free_nvlist(nvl, "syncpeer");
27510a51bf5SMax Laier 
276813c5b75SLuiz Amaral 	nvlist_add_nvlist(nvl, "syncpeer",
277813c5b75SLuiz Amaral 	    pfsync_sockaddr_to_syncpeer_nvlist(&addr));
278813c5b75SLuiz Amaral 
279813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
280813c5b75SLuiz Amaral 		err(1, "SIOCSETPFSYNCNV");
281813c5b75SLuiz Amaral 
282813c5b75SLuiz Amaral 	nvlist_destroy(nvl);
28310a51bf5SMax Laier }
28410a51bf5SMax Laier 
28510a51bf5SMax Laier /* ARGSUSED */
286a9771948SGleb Smirnoff void
287a9771948SGleb Smirnoff setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp)
288a9771948SGleb Smirnoff {
28910a51bf5SMax Laier 	int maxupdates;
290813c5b75SLuiz Amaral 	nvlist_t *nvl = nvlist_create(0);
291a9771948SGleb Smirnoff 
292a9771948SGleb Smirnoff 	maxupdates = atoi(val);
29310a51bf5SMax Laier 	if ((maxupdates < 0) || (maxupdates > 255))
29410a51bf5SMax Laier 		errx(1, "maxupd %s: out of range", val);
295a9771948SGleb Smirnoff 
296813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
297813c5b75SLuiz Amaral 		err(1, "SIOCGETPFSYNCNV");
298a9771948SGleb Smirnoff 
299813c5b75SLuiz Amaral 	nvlist_free_number(nvl, "maxupdates");
300813c5b75SLuiz Amaral 	nvlist_add_number(nvl, "maxupdates", maxupdates);
301a9771948SGleb Smirnoff 
302813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
303813c5b75SLuiz Amaral 		err(1, "SIOCSETPFSYNCNV");
304a9771948SGleb Smirnoff 
305813c5b75SLuiz Amaral 	nvlist_destroy(nvl);
306a9771948SGleb Smirnoff }
307a9771948SGleb Smirnoff 
30874e9ff65SGleb Smirnoff /* ARGSUSED */
30974e9ff65SGleb Smirnoff void
31074e9ff65SGleb Smirnoff setpfsync_defer(const char *val, int d, int s, const struct afswtch *rafp)
31174e9ff65SGleb Smirnoff {
312813c5b75SLuiz Amaral 	nvlist_t *nvl = nvlist_create(0);
31374e9ff65SGleb Smirnoff 
314813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
315813c5b75SLuiz Amaral 		err(1, "SIOCGETPFSYNCNV");
31674e9ff65SGleb Smirnoff 
317813c5b75SLuiz Amaral 	nvlist_free_number(nvl, "flags");
318813c5b75SLuiz Amaral 	nvlist_add_number(nvl, "flags", d ? PFSYNCF_DEFER : 0);
31974e9ff65SGleb Smirnoff 
320813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
321813c5b75SLuiz Amaral 		err(1, "SIOCSETPFSYNCNV");
322813c5b75SLuiz Amaral 
323813c5b75SLuiz Amaral 	nvlist_destroy(nvl);
32474e9ff65SGleb Smirnoff }
32574e9ff65SGleb Smirnoff 
326a9771948SGleb Smirnoff void
327ef3abbe8SGleb Smirnoff pfsync_status(int s)
328a9771948SGleb Smirnoff {
329813c5b75SLuiz Amaral 	nvlist_t *nvl;
330813c5b75SLuiz Amaral 	char syncdev[IFNAMSIZ];
331813c5b75SLuiz Amaral 	char syncpeer_str[NI_MAXHOST];
332813c5b75SLuiz Amaral 	struct sockaddr_storage syncpeer;
333*44cd85d4SAlexander V. Chernikov 	int maxupdates = 0;
334*44cd85d4SAlexander V. Chernikov 	int flags = 0;
335813c5b75SLuiz Amaral 	int error;
336a9771948SGleb Smirnoff 
337813c5b75SLuiz Amaral 	nvl = nvlist_create(0);
338a9771948SGleb Smirnoff 
339813c5b75SLuiz Amaral 	if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1) {
340813c5b75SLuiz Amaral 		nvlist_destroy(nvl);
341a9771948SGleb Smirnoff 		return;
342813c5b75SLuiz Amaral 	}
343a9771948SGleb Smirnoff 
344813c5b75SLuiz Amaral 	memset((char *)&syncdev, 0, IFNAMSIZ);
345813c5b75SLuiz Amaral 	if (nvlist_exists_string(nvl, "syncdev"))
346813c5b75SLuiz Amaral 		strlcpy(syncdev, nvlist_get_string(nvl, "syncdev"),
347813c5b75SLuiz Amaral 		    IFNAMSIZ);
348813c5b75SLuiz Amaral 	if (nvlist_exists_number(nvl, "maxupdates"))
349813c5b75SLuiz Amaral 		maxupdates = nvlist_get_number(nvl, "maxupdates");
350813c5b75SLuiz Amaral 	if (nvlist_exists_number(nvl, "flags"))
351813c5b75SLuiz Amaral 		flags = nvlist_get_number(nvl, "flags");
352813c5b75SLuiz Amaral 	if (nvlist_exists_nvlist(nvl, "syncpeer")) {
353813c5b75SLuiz Amaral 		pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl,
354813c5b75SLuiz Amaral 							     "syncpeer"),
355813c5b75SLuiz Amaral 		    &syncpeer);
356813c5b75SLuiz Amaral 	}
357813c5b75SLuiz Amaral 
358813c5b75SLuiz Amaral 	nvlist_destroy(nvl);
359813c5b75SLuiz Amaral 
360813c5b75SLuiz Amaral 	if (syncdev[0] != '\0' || syncpeer.ss_family != AF_UNSPEC)
36111c4984fSGleb Smirnoff 		printf("\t");
36211c4984fSGleb Smirnoff 
363813c5b75SLuiz Amaral 	if (syncdev[0] != '\0')
364813c5b75SLuiz Amaral 		printf("syncdev: %s ", syncdev);
36511c4984fSGleb Smirnoff 
366813c5b75SLuiz Amaral 	if (syncpeer.ss_family == AF_INET &&
367813c5b75SLuiz Amaral 	    ((struct sockaddr_in *)&syncpeer)->sin_addr.s_addr !=
368813c5b75SLuiz Amaral 		htonl(INADDR_PFSYNC_GROUP)) {
369813c5b75SLuiz Amaral 
370813c5b75SLuiz Amaral 		struct sockaddr *syncpeer_sa =
371813c5b75SLuiz Amaral 		    (struct sockaddr *)&syncpeer;
372813c5b75SLuiz Amaral 		if ((error = getnameinfo(syncpeer_sa, syncpeer_sa->sa_len,
373813c5b75SLuiz Amaral 			 syncpeer_str, sizeof(syncpeer_str), NULL, 0,
374813c5b75SLuiz Amaral 			 NI_NUMERICHOST)) != 0)
375813c5b75SLuiz Amaral 			errx(1, "getnameinfo: %s", gai_strerror(error));
376813c5b75SLuiz Amaral 		printf("syncpeer: %s ", syncpeer_str);
37774e9ff65SGleb Smirnoff 	}
378813c5b75SLuiz Amaral 
379813c5b75SLuiz Amaral 	printf("maxupd: %d ", maxupdates);
380813c5b75SLuiz Amaral 	printf("defer: %s\n", (flags & PFSYNCF_DEFER) ? "on" : "off");
381813c5b75SLuiz Amaral 	printf("\tsyncok: %d\n", (flags & PFSYNCF_OK) ? 1 : 0);
382a9771948SGleb Smirnoff }
383a9771948SGleb Smirnoff 
384a9771948SGleb Smirnoff static struct cmd pfsync_cmds[] = {
38510a51bf5SMax Laier 	DEF_CMD_ARG("syncdev",		setpfsync_syncdev),
38610a51bf5SMax Laier 	DEF_CMD("-syncdev",	1,	unsetpfsync_syncdev),
38710a51bf5SMax Laier 	DEF_CMD_ARG("syncif",		setpfsync_syncdev),
38810a51bf5SMax Laier 	DEF_CMD("-syncif",	1,	unsetpfsync_syncdev),
38910a51bf5SMax Laier 	DEF_CMD_ARG("syncpeer",		setpfsync_syncpeer),
39010a51bf5SMax Laier 	DEF_CMD("-syncpeer",	1,	unsetpfsync_syncpeer),
39174e9ff65SGleb Smirnoff 	DEF_CMD_ARG("maxupd",		setpfsync_maxupd),
39274e9ff65SGleb Smirnoff 	DEF_CMD("defer",	1,	setpfsync_defer),
39374e9ff65SGleb Smirnoff 	DEF_CMD("-defer",	0,	setpfsync_defer),
394a9771948SGleb Smirnoff };
395a9771948SGleb Smirnoff static struct afswtch af_pfsync = {
396a9771948SGleb Smirnoff 	.af_name	= "af_pfsync",
397a9771948SGleb Smirnoff 	.af_af		= AF_UNSPEC,
398ef3abbe8SGleb Smirnoff 	.af_other_status = pfsync_status,
399a9771948SGleb Smirnoff };
400a9771948SGleb Smirnoff 
401a9771948SGleb Smirnoff static __constructor void
402a9771948SGleb Smirnoff pfsync_ctor(void)
403a9771948SGleb Smirnoff {
404*44cd85d4SAlexander V. Chernikov 	for (size_t i = 0; i < nitems(pfsync_cmds);  i++)
405a9771948SGleb Smirnoff 		cmd_register(&pfsync_cmds[i]);
406a9771948SGleb Smirnoff 	af_register(&af_pfsync);
407a9771948SGleb Smirnoff }
408