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