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