xref: /f-stack/tools/ifconfig/ifpfsync.c (revision 22ce4aff)
1*22ce4affSfengbojiang /*-
2*22ce4affSfengbojiang  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*22ce4affSfengbojiang  *
4df6ad731Slogwang  * Copyright (c) 2003 Ryan McBride. All rights reserved.
5df6ad731Slogwang  * Copyright (c) 2004 Max Laier. All rights reserved.
6df6ad731Slogwang  *
7df6ad731Slogwang  * Redistribution and use in source and binary forms, with or without
8df6ad731Slogwang  * modification, are permitted provided that the following conditions
9df6ad731Slogwang  * are met:
10df6ad731Slogwang  * 1. Redistributions of source code must retain the above copyright
11df6ad731Slogwang  *    notice, this list of conditions and the following disclaimer.
12df6ad731Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
13df6ad731Slogwang  *    notice, this list of conditions and the following disclaimer in the
14df6ad731Slogwang  *    documentation and/or other materials provided with the distribution.
15df6ad731Slogwang  *
16df6ad731Slogwang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17df6ad731Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18df6ad731Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19df6ad731Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20df6ad731Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21df6ad731Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22df6ad731Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23df6ad731Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24df6ad731Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25df6ad731Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26df6ad731Slogwang  * SUCH DAMAGE.
27df6ad731Slogwang  *
28df6ad731Slogwang  * $FreeBSD$
29df6ad731Slogwang  */
30df6ad731Slogwang 
31df6ad731Slogwang #include <sys/param.h>
32df6ad731Slogwang #include <sys/ioctl.h>
33df6ad731Slogwang #include <sys/socket.h>
34df6ad731Slogwang 
35df6ad731Slogwang #include <net/if.h>
36df6ad731Slogwang #include <netinet/in.h>
37df6ad731Slogwang #include <net/pfvar.h>
38df6ad731Slogwang #include <net/if_pfsync.h>
39df6ad731Slogwang #include <net/route.h>
40df6ad731Slogwang #include <arpa/inet.h>
41df6ad731Slogwang 
42df6ad731Slogwang #include <err.h>
43df6ad731Slogwang #include <netdb.h>
44df6ad731Slogwang #include <stdio.h>
45df6ad731Slogwang #include <stdlib.h>
46df6ad731Slogwang #include <string.h>
47df6ad731Slogwang #include <unistd.h>
48df6ad731Slogwang 
49df6ad731Slogwang #include "ifconfig.h"
50df6ad731Slogwang 
51df6ad731Slogwang void setpfsync_syncdev(const char *, int, int, const struct afswtch *);
52df6ad731Slogwang void unsetpfsync_syncdev(const char *, int, int, const struct afswtch *);
53df6ad731Slogwang void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
54df6ad731Slogwang void unsetpfsync_syncpeer(const char *, int, int, const struct afswtch *);
55df6ad731Slogwang void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
56df6ad731Slogwang void setpfsync_maxupd(const char *, int, int, const struct afswtch *);
57df6ad731Slogwang void setpfsync_defer(const char *, int, int, const struct afswtch *);
58df6ad731Slogwang void pfsync_status(int);
59df6ad731Slogwang 
60df6ad731Slogwang void
setpfsync_syncdev(const char * val,int d,int s,const struct afswtch * rafp)61df6ad731Slogwang setpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
62df6ad731Slogwang {
63df6ad731Slogwang 	struct pfsyncreq preq;
64df6ad731Slogwang 
65df6ad731Slogwang 	bzero((char *)&preq, sizeof(struct pfsyncreq));
66df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
67df6ad731Slogwang 
68df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
69df6ad731Slogwang 		err(1, "SIOCGETPFSYNC");
70df6ad731Slogwang 
71df6ad731Slogwang 	strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev));
72df6ad731Slogwang 
73df6ad731Slogwang 	if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
74df6ad731Slogwang 		err(1, "SIOCSETPFSYNC");
75df6ad731Slogwang }
76df6ad731Slogwang 
77df6ad731Slogwang /* ARGSUSED */
78df6ad731Slogwang void
unsetpfsync_syncdev(const char * val,int d,int s,const struct afswtch * rafp)79df6ad731Slogwang unsetpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
80df6ad731Slogwang {
81df6ad731Slogwang 	struct pfsyncreq preq;
82df6ad731Slogwang 
83df6ad731Slogwang 	bzero((char *)&preq, sizeof(struct pfsyncreq));
84df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
85df6ad731Slogwang 
86df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
87df6ad731Slogwang 		err(1, "SIOCGETPFSYNC");
88df6ad731Slogwang 
89df6ad731Slogwang 	bzero((char *)&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev));
90df6ad731Slogwang 
91df6ad731Slogwang 	if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
92df6ad731Slogwang 		err(1, "SIOCSETPFSYNC");
93df6ad731Slogwang }
94df6ad731Slogwang 
95df6ad731Slogwang /* ARGSUSED */
96df6ad731Slogwang void
setpfsync_syncpeer(const char * val,int d,int s,const struct afswtch * rafp)97df6ad731Slogwang setpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
98df6ad731Slogwang {
99df6ad731Slogwang 	struct pfsyncreq preq;
100df6ad731Slogwang 	struct addrinfo hints, *peerres;
101df6ad731Slogwang 	int ecode;
102df6ad731Slogwang 
103df6ad731Slogwang 	bzero((char *)&preq, sizeof(struct pfsyncreq));
104df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
105df6ad731Slogwang 
106df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
107df6ad731Slogwang 		err(1, "SIOCGETPFSYNC");
108df6ad731Slogwang 
109df6ad731Slogwang 	memset(&hints, 0, sizeof(hints));
110df6ad731Slogwang 	hints.ai_family = AF_INET;
111df6ad731Slogwang 	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
112df6ad731Slogwang 
113df6ad731Slogwang 	if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0)
114df6ad731Slogwang 		errx(1, "error in parsing address string: %s",
115df6ad731Slogwang 		    gai_strerror(ecode));
116df6ad731Slogwang 
117df6ad731Slogwang 	if (peerres->ai_addr->sa_family != AF_INET)
118df6ad731Slogwang 		errx(1, "only IPv4 addresses supported for the syncpeer");
119df6ad731Slogwang 
120df6ad731Slogwang 	preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *)
121df6ad731Slogwang 	    peerres->ai_addr)->sin_addr.s_addr;
122df6ad731Slogwang 
123df6ad731Slogwang 	if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
124df6ad731Slogwang 		err(1, "SIOCSETPFSYNC");
125*22ce4affSfengbojiang 	freeaddrinfo(peerres);
126df6ad731Slogwang }
127df6ad731Slogwang 
128df6ad731Slogwang /* ARGSUSED */
129df6ad731Slogwang void
unsetpfsync_syncpeer(const char * val,int d,int s,const struct afswtch * rafp)130df6ad731Slogwang unsetpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
131df6ad731Slogwang {
132df6ad731Slogwang 	struct pfsyncreq preq;
133df6ad731Slogwang 
134df6ad731Slogwang 	bzero((char *)&preq, sizeof(struct pfsyncreq));
135df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
136df6ad731Slogwang 
137df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
138df6ad731Slogwang 		err(1, "SIOCGETPFSYNC");
139df6ad731Slogwang 
140df6ad731Slogwang 	preq.pfsyncr_syncpeer.s_addr = 0;
141df6ad731Slogwang 
142df6ad731Slogwang 	if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
143df6ad731Slogwang 		err(1, "SIOCSETPFSYNC");
144df6ad731Slogwang }
145df6ad731Slogwang 
146df6ad731Slogwang /* ARGSUSED */
147df6ad731Slogwang void
setpfsync_maxupd(const char * val,int d,int s,const struct afswtch * rafp)148df6ad731Slogwang setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp)
149df6ad731Slogwang {
150df6ad731Slogwang 	struct pfsyncreq preq;
151df6ad731Slogwang 	int maxupdates;
152df6ad731Slogwang 
153df6ad731Slogwang 	maxupdates = atoi(val);
154df6ad731Slogwang 	if ((maxupdates < 0) || (maxupdates > 255))
155df6ad731Slogwang 		errx(1, "maxupd %s: out of range", val);
156df6ad731Slogwang 
157df6ad731Slogwang 	memset((char *)&preq, 0, sizeof(struct pfsyncreq));
158df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
159df6ad731Slogwang 
160df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
161df6ad731Slogwang 		err(1, "SIOCGETPFSYNC");
162df6ad731Slogwang 
163df6ad731Slogwang 	preq.pfsyncr_maxupdates = maxupdates;
164df6ad731Slogwang 
165df6ad731Slogwang 	if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
166df6ad731Slogwang 		err(1, "SIOCSETPFSYNC");
167df6ad731Slogwang }
168df6ad731Slogwang 
169df6ad731Slogwang /* ARGSUSED */
170df6ad731Slogwang void
setpfsync_defer(const char * val,int d,int s,const struct afswtch * rafp)171df6ad731Slogwang setpfsync_defer(const char *val, int d, int s, const struct afswtch *rafp)
172df6ad731Slogwang {
173df6ad731Slogwang 	struct pfsyncreq preq;
174df6ad731Slogwang 
175df6ad731Slogwang 	memset((char *)&preq, 0, sizeof(struct pfsyncreq));
176df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
177df6ad731Slogwang 
178df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
179df6ad731Slogwang 		err(1, "SIOCGETPFSYNC");
180df6ad731Slogwang 
181df6ad731Slogwang 	preq.pfsyncr_defer = d;
182df6ad731Slogwang 	if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
183df6ad731Slogwang 		err(1, "SIOCSETPFSYNC");
184df6ad731Slogwang }
185df6ad731Slogwang 
186df6ad731Slogwang void
pfsync_status(int s)187df6ad731Slogwang pfsync_status(int s)
188df6ad731Slogwang {
189df6ad731Slogwang 	struct pfsyncreq preq;
190df6ad731Slogwang 
191df6ad731Slogwang 	bzero((char *)&preq, sizeof(struct pfsyncreq));
192df6ad731Slogwang 	ifr.ifr_data = (caddr_t)&preq;
193df6ad731Slogwang 
194df6ad731Slogwang 	if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
195df6ad731Slogwang 		return;
196df6ad731Slogwang 
197df6ad731Slogwang 	if (preq.pfsyncr_syncdev[0] != '\0' ||
198*22ce4affSfengbojiang 	    preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP))
199df6ad731Slogwang 			printf("\t");
200df6ad731Slogwang 
201df6ad731Slogwang 	if (preq.pfsyncr_syncdev[0] != '\0')
202df6ad731Slogwang 		printf("pfsync: syncdev: %s ", preq.pfsyncr_syncdev);
203*22ce4affSfengbojiang 	if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP))
204df6ad731Slogwang 		printf("syncpeer: %s ", inet_ntoa(preq.pfsyncr_syncpeer));
205df6ad731Slogwang 
206df6ad731Slogwang 	if (preq.pfsyncr_syncdev[0] != '\0' ||
207*22ce4affSfengbojiang 	    preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
208df6ad731Slogwang 		printf("maxupd: %d ", preq.pfsyncr_maxupdates);
209df6ad731Slogwang 		printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off");
210df6ad731Slogwang 	}
211df6ad731Slogwang }
212df6ad731Slogwang 
213df6ad731Slogwang static struct cmd pfsync_cmds[] = {
214df6ad731Slogwang 	DEF_CMD_ARG("syncdev",		setpfsync_syncdev),
215df6ad731Slogwang 	DEF_CMD("-syncdev",	1,	unsetpfsync_syncdev),
216df6ad731Slogwang 	DEF_CMD_ARG("syncif",		setpfsync_syncdev),
217df6ad731Slogwang 	DEF_CMD("-syncif",	1,	unsetpfsync_syncdev),
218df6ad731Slogwang 	DEF_CMD_ARG("syncpeer",		setpfsync_syncpeer),
219df6ad731Slogwang 	DEF_CMD("-syncpeer",	1,	unsetpfsync_syncpeer),
220df6ad731Slogwang 	DEF_CMD_ARG("maxupd",		setpfsync_maxupd),
221df6ad731Slogwang 	DEF_CMD("defer",	1,	setpfsync_defer),
222df6ad731Slogwang 	DEF_CMD("-defer",	0,	setpfsync_defer),
223df6ad731Slogwang };
224df6ad731Slogwang static struct afswtch af_pfsync = {
225df6ad731Slogwang 	.af_name	= "af_pfsync",
226df6ad731Slogwang 	.af_af		= AF_UNSPEC,
227df6ad731Slogwang 	.af_other_status = pfsync_status,
228df6ad731Slogwang };
229df6ad731Slogwang 
230df6ad731Slogwang static __constructor void
pfsync_ctor(void)231df6ad731Slogwang pfsync_ctor(void)
232df6ad731Slogwang {
233df6ad731Slogwang 	int i;
234df6ad731Slogwang 
235df6ad731Slogwang 	for (i = 0; i < nitems(pfsync_cmds);  i++)
236df6ad731Slogwang 		cmd_register(&pfsync_cmds[i]);
237df6ad731Slogwang 	af_register(&af_pfsync);
238df6ad731Slogwang }
239