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