1*8ee626c9Schristos /* $NetBSD: pfs.c,v 1.2 2015/06/16 23:04:14 christos Exp $ */
2ca38e323Sdegroote
3ca38e323Sdegroote /*-
4ca38e323Sdegroote * Copyright (c) 2010 The NetBSD Foundation, Inc.
5ca38e323Sdegroote * All rights reserved.
6ca38e323Sdegroote *
7ca38e323Sdegroote * Redistribution and use in source and binary forms, with or without
8ca38e323Sdegroote * modification, are permitted provided that the following conditions
9ca38e323Sdegroote * are met:
10ca38e323Sdegroote * 1. Redistributions of source code must retain the above copyright
11ca38e323Sdegroote * notice, this list of conditions and the following disclaimer.
12ca38e323Sdegroote * 2. Redistributions in binary form must reproduce the above copyright
13ca38e323Sdegroote * notice, this list of conditions and the following disclaimer in the
14ca38e323Sdegroote * documentation and/or other materials provided with the distribution.
15ca38e323Sdegroote *
16ca38e323Sdegroote * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17ca38e323Sdegroote * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18ca38e323Sdegroote * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19ca38e323Sdegroote * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20ca38e323Sdegroote * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21ca38e323Sdegroote * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22ca38e323Sdegroote * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23ca38e323Sdegroote * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24ca38e323Sdegroote * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ca38e323Sdegroote * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26ca38e323Sdegroote * POSSIBILITY OF SUCH DAMAGE.
27ca38e323Sdegroote */
28ca38e323Sdegroote
29ca38e323Sdegroote #include <sys/cdefs.h>
30ca38e323Sdegroote
31ca38e323Sdegroote #ifndef lint
32*8ee626c9Schristos __RCSID("$NetBSD: pfs.c,v 1.2 2015/06/16 23:04:14 christos Exp $");
33ca38e323Sdegroote #endif
34ca38e323Sdegroote
35ca38e323Sdegroote #include <sys/types.h>
36ca38e323Sdegroote #include <sys/ioctl.h>
37ca38e323Sdegroote #include <sys/socket.h>
38ca38e323Sdegroote #include <sys/stat.h>
39ca38e323Sdegroote
40ca38e323Sdegroote #include <net/if.h>
41ca38e323Sdegroote #include <netinet/in.h>
42ca38e323Sdegroote #define TCPSTATES
43ca38e323Sdegroote #include <netinet/tcp_fsm.h>
44ca38e323Sdegroote #include <net/pfvar.h>
45ca38e323Sdegroote #include <arpa/inet.h>
46ca38e323Sdegroote
47ca38e323Sdegroote #include <err.h>
48ca38e323Sdegroote #include <errno.h>
49ca38e323Sdegroote #include <fcntl.h>
50ca38e323Sdegroote #include <limits.h>
51ca38e323Sdegroote #include <netdb.h>
52ca38e323Sdegroote #include <stdio.h>
53ca38e323Sdegroote #include <stdlib.h>
54ca38e323Sdegroote #include <string.h>
55ca38e323Sdegroote #include <stdbool.h>
56ca38e323Sdegroote #include <unistd.h>
57ca38e323Sdegroote
58ca38e323Sdegroote #include "parser.h"
59ca38e323Sdegroote
60ca38e323Sdegroote __dead static void usage(void);
61ca38e323Sdegroote static int setlock(int, int, int);
62ca38e323Sdegroote static int get_states(int, int, struct pfioc_states*);
63ca38e323Sdegroote static int dump_states_binary(int, int, const char*);
64ca38e323Sdegroote static int restore_states_binary(int, int, const char*);
65ca38e323Sdegroote static int dump_states_ascii(int, int, const char*);
66ca38e323Sdegroote static int restore_states_ascii(int, int, const char*);
67ca38e323Sdegroote static char* print_host(const struct pfsync_state_host *h, sa_family_t, char*, size_t);
68ca38e323Sdegroote static void print_peer(const struct pfsync_state_peer *peer, uint8_t, FILE*);
69ca38e323Sdegroote static int print_states(int, int, FILE*);
70ca38e323Sdegroote static void display_states(const struct pfioc_states*, int, FILE*);
71ca38e323Sdegroote static int test_ascii_dump(int, const char*, const char*);
72ca38e323Sdegroote
73ca38e323Sdegroote static char pf_device[] = "/dev/pf";
74ca38e323Sdegroote
75ca38e323Sdegroote __dead static void
usage(void)76ca38e323Sdegroote usage(void)
77ca38e323Sdegroote {
78ca38e323Sdegroote fprintf(stderr,
79ca38e323Sdegroote "usage : %s [-v] [-u | -l | -w <filename> | -r <filename> |\n"
80ca38e323Sdegroote " [ -W <filename> | -R <filename> ]\n",
81ca38e323Sdegroote getprogname());
82ca38e323Sdegroote exit(EXIT_FAILURE);
83ca38e323Sdegroote }
84ca38e323Sdegroote
85ca38e323Sdegroote /*
86ca38e323Sdegroote * The state table must be locked before calling this function
87ca38e323Sdegroote * Return the number of state in case of success, -1 in case of failure
88ca38e323Sdegroote * ps::ps_buf must be freed by user after use (in case of success)
89ca38e323Sdegroote */
90ca38e323Sdegroote static int
get_states(int fd,int verbose __unused,struct pfioc_states * ps)91ca38e323Sdegroote get_states(int fd, int verbose __unused, struct pfioc_states* ps)
92ca38e323Sdegroote {
93ca38e323Sdegroote memset(ps, 0, sizeof(*ps));
94ca38e323Sdegroote ps->ps_len = 0;
95ca38e323Sdegroote char* inbuf;
96ca38e323Sdegroote
97ca38e323Sdegroote // ask the kernel how much memory we need to allocate
98ca38e323Sdegroote if (ioctl(fd, DIOCGETSTATES, ps) == -1) {
99ca38e323Sdegroote err(EXIT_FAILURE, "DIOCGETSTATES");
100ca38e323Sdegroote }
101ca38e323Sdegroote
102ca38e323Sdegroote /* no state */
103ca38e323Sdegroote if (ps->ps_len == 0)
104ca38e323Sdegroote return 0;
105ca38e323Sdegroote
106ca38e323Sdegroote inbuf = malloc(ps->ps_len);
107ca38e323Sdegroote if (inbuf == NULL)
108ca38e323Sdegroote err(EXIT_FAILURE, NULL);
109ca38e323Sdegroote
110ca38e323Sdegroote ps->ps_buf = inbuf;
111ca38e323Sdegroote
112ca38e323Sdegroote // really retrieve the different states
113ca38e323Sdegroote if (ioctl(fd, DIOCGETSTATES, ps) == -1) {
114ca38e323Sdegroote free(ps->ps_buf);
115ca38e323Sdegroote err(EXIT_FAILURE, "DIOCGETSTATES");
116ca38e323Sdegroote }
117ca38e323Sdegroote
118ca38e323Sdegroote return (ps->ps_len / sizeof(struct pfsync_state));
119ca38e323Sdegroote }
120ca38e323Sdegroote
121ca38e323Sdegroote static int
dump_states_binary(int fd,int verbose,const char * filename)122ca38e323Sdegroote dump_states_binary(int fd, int verbose, const char* filename)
123ca38e323Sdegroote {
124ca38e323Sdegroote int wfd;
125ca38e323Sdegroote struct pfioc_states ps;
126ca38e323Sdegroote struct pfsync_state *p = NULL;
127ca38e323Sdegroote int nb_states;
128ca38e323Sdegroote int i;
129ca38e323Sdegroote int error = 0;
130ca38e323Sdegroote int errno_saved = 0;
131ca38e323Sdegroote
132ca38e323Sdegroote wfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0600);
133ca38e323Sdegroote if (wfd == -1)
134ca38e323Sdegroote err(EXIT_FAILURE, "Cannot open %s", filename);
135ca38e323Sdegroote
136ca38e323Sdegroote nb_states = get_states(fd, verbose, &ps);
137ca38e323Sdegroote if (nb_states <= 0) {
138ca38e323Sdegroote close(wfd);
139ca38e323Sdegroote return nb_states;
140ca38e323Sdegroote }
141ca38e323Sdegroote
142ca38e323Sdegroote /*
143ca38e323Sdegroote * In the file, write the number of states, then store the different states
144ca38e323Sdegroote * When we will switch to text format, we probably don't care any more about the len
145ca38e323Sdegroote */
146ca38e323Sdegroote if (write(wfd, &nb_states, sizeof(nb_states)) != sizeof(nb_states)) {
147ca38e323Sdegroote error = EXIT_FAILURE;
148ca38e323Sdegroote errno_saved = errno;
149ca38e323Sdegroote goto done;
150ca38e323Sdegroote }
151ca38e323Sdegroote
152ca38e323Sdegroote p = ps.ps_states;
153ca38e323Sdegroote for (i = 0; i < nb_states; i++) {
154ca38e323Sdegroote if (write(wfd, &p[i], sizeof(*p)) != sizeof(*p)) {
155ca38e323Sdegroote error = EXIT_FAILURE;
156ca38e323Sdegroote errno_saved = errno;
157ca38e323Sdegroote goto done;
158ca38e323Sdegroote }
159ca38e323Sdegroote }
160ca38e323Sdegroote
161ca38e323Sdegroote done:
162ca38e323Sdegroote free(p);
163ca38e323Sdegroote close(wfd);
164ca38e323Sdegroote // close can't modify errno
165ca38e323Sdegroote if (error) {
166ca38e323Sdegroote errno = errno_saved;
167ca38e323Sdegroote err(error, NULL);
168ca38e323Sdegroote }
169ca38e323Sdegroote
170ca38e323Sdegroote return 0;
171ca38e323Sdegroote }
172ca38e323Sdegroote
173ca38e323Sdegroote static int
restore_states_binary(int fd,int verbose __unused,const char * filename)174ca38e323Sdegroote restore_states_binary(int fd, int verbose __unused, const char* filename)
175ca38e323Sdegroote {
176ca38e323Sdegroote int rfd;
177ca38e323Sdegroote struct pfioc_states ps;
178ca38e323Sdegroote struct pfsync_state *p;
179ca38e323Sdegroote int nb_states;
180ca38e323Sdegroote int errno_saved = 0;
181ca38e323Sdegroote int i;
182ca38e323Sdegroote
183ca38e323Sdegroote rfd = open(filename, O_RDONLY, 0600);
184ca38e323Sdegroote if (rfd == -1)
185ca38e323Sdegroote err(EXIT_FAILURE, "Cannot open %s", filename);
186ca38e323Sdegroote
187ca38e323Sdegroote if (read(rfd, &nb_states, sizeof(nb_states)) != sizeof(nb_states)) {
188ca38e323Sdegroote errno_saved = errno;
189ca38e323Sdegroote close(rfd);
190ca38e323Sdegroote errno = errno_saved;
191ca38e323Sdegroote err(EXIT_FAILURE, NULL);
192ca38e323Sdegroote }
193ca38e323Sdegroote
194ca38e323Sdegroote ps.ps_len = nb_states * sizeof(struct pfsync_state);
195ca38e323Sdegroote ps.ps_states = malloc(ps.ps_len);
196ca38e323Sdegroote if (ps.ps_states == NULL) {
197ca38e323Sdegroote errno_saved = errno;
198ca38e323Sdegroote close(rfd);
199ca38e323Sdegroote errno = errno_saved;
200ca38e323Sdegroote err(EXIT_FAILURE, NULL);
201ca38e323Sdegroote }
202ca38e323Sdegroote
203ca38e323Sdegroote p = ps.ps_states;
204ca38e323Sdegroote
205ca38e323Sdegroote for (i = 0; i < nb_states; i++) {
206ca38e323Sdegroote if (read(rfd, &p[i], sizeof(*p)) != sizeof(*p)) {
207ca38e323Sdegroote errno_saved = errno;
208ca38e323Sdegroote close(rfd);
209ca38e323Sdegroote free(ps.ps_states);
210ca38e323Sdegroote errno = errno_saved;
211ca38e323Sdegroote err(EXIT_FAILURE, NULL);
212ca38e323Sdegroote }
213ca38e323Sdegroote }
214ca38e323Sdegroote
215ca38e323Sdegroote if (ioctl(fd, DIOCADDSTATES, &ps) == -1) {
216ca38e323Sdegroote errno_saved = errno;
217ca38e323Sdegroote close(rfd);
218ca38e323Sdegroote free(ps.ps_states);
219ca38e323Sdegroote errno = errno_saved;
220ca38e323Sdegroote err(EXIT_FAILURE, "DIOCADDSTATES");
221ca38e323Sdegroote }
222ca38e323Sdegroote
223ca38e323Sdegroote free(ps.ps_states);
224ca38e323Sdegroote close(rfd);
225ca38e323Sdegroote return 0;
226ca38e323Sdegroote }
227ca38e323Sdegroote
228ca38e323Sdegroote static char*
print_host(const struct pfsync_state_host * h,sa_family_t af,char * buf,size_t size_buf)229ca38e323Sdegroote print_host(const struct pfsync_state_host *h, sa_family_t af, char* buf,
230ca38e323Sdegroote size_t size_buf)
231ca38e323Sdegroote {
232ca38e323Sdegroote uint16_t port;
233ca38e323Sdegroote char buf_addr[48];
234ca38e323Sdegroote
235ca38e323Sdegroote port = ntohs(h->port);
236ca38e323Sdegroote if (inet_ntop(af, &(h->addr) , buf_addr, sizeof(buf_addr)) == NULL) {
237ca38e323Sdegroote strcpy(buf_addr, "?");
238ca38e323Sdegroote }
239ca38e323Sdegroote
240ca38e323Sdegroote snprintf(buf, size_buf, "%s:[%d]", buf_addr, port);
241ca38e323Sdegroote return buf;
242ca38e323Sdegroote }
243ca38e323Sdegroote
244ca38e323Sdegroote static void
print_peer(const struct pfsync_state_peer * peer,uint8_t proto,FILE * f)245ca38e323Sdegroote print_peer(const struct pfsync_state_peer* peer, uint8_t proto, FILE* f)
246ca38e323Sdegroote {
247ca38e323Sdegroote if (proto == IPPROTO_TCP) {
248ca38e323Sdegroote if (peer->state < TCP_NSTATES)
249ca38e323Sdegroote fprintf(f, "state %s", tcpstates[peer->state]);
250ca38e323Sdegroote
251ca38e323Sdegroote if (peer->seqdiff != 0)
252ca38e323Sdegroote fprintf(f, " seq [%" PRIu32 ":%" PRIu32 ",%" PRIu32"]",
253ca38e323Sdegroote peer->seqlo, peer->seqhi, peer->seqdiff);
254ca38e323Sdegroote else
255ca38e323Sdegroote fprintf(f, " seq [%" PRIu32 ":%" PRIu32 "]",
256ca38e323Sdegroote peer->seqlo, peer->seqhi);
257ca38e323Sdegroote
258ca38e323Sdegroote if (peer->mss != 0)
259ca38e323Sdegroote fprintf(f, " max_win %" PRIu16 " mss %" PRIu16 " wscale %" PRIu8,
260ca38e323Sdegroote peer->max_win, peer->mss, peer->wscale);
261ca38e323Sdegroote else
262ca38e323Sdegroote fprintf(f, " max_win %" PRIu16 " wscale %" PRIu8, peer->max_win,
263ca38e323Sdegroote peer->wscale);
264ca38e323Sdegroote
265ca38e323Sdegroote } else {
266ca38e323Sdegroote if (proto == IPPROTO_UDP) {
267ca38e323Sdegroote const char *mystates[] = PFUDPS_NAMES;
268ca38e323Sdegroote if (peer->state < PFUDPS_NSTATES)
269ca38e323Sdegroote fprintf(f, "state %s", mystates[peer->state]);
270ca38e323Sdegroote } else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
271ca38e323Sdegroote fprintf(f, " state %" PRIu8, peer->state);
272ca38e323Sdegroote } else {
273ca38e323Sdegroote const char *mystates[] = PFOTHERS_NAMES;
274ca38e323Sdegroote if (peer->state < PFOTHERS_NSTATES)
275ca38e323Sdegroote fprintf(f, " state %s", mystates[peer->state]);
276ca38e323Sdegroote }
277ca38e323Sdegroote }
278ca38e323Sdegroote
279ca38e323Sdegroote if (peer->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID) {
280ca38e323Sdegroote fprintf(f, " scrub flags %" PRIu16 "ttl %" PRIu8 "mod %"PRIu32,
281ca38e323Sdegroote peer->scrub.pfss_flags, peer->scrub.pfss_ttl, peer->scrub.pfss_ts_mod);
282ca38e323Sdegroote } else {
283ca38e323Sdegroote fprintf(f, " no-scrub");
284ca38e323Sdegroote }
285ca38e323Sdegroote }
286ca38e323Sdegroote
287ca38e323Sdegroote static void
display_states(const struct pfioc_states * ps,int verbose __unused,FILE * f)288ca38e323Sdegroote display_states(const struct pfioc_states *ps, int verbose __unused, FILE* f)
289ca38e323Sdegroote {
290ca38e323Sdegroote struct pfsync_state *p = NULL;
291ca38e323Sdegroote struct pfsync_state_peer *src, *dst;
292ca38e323Sdegroote struct protoent *proto;
293ca38e323Sdegroote int nb_states;
294ca38e323Sdegroote int i;
295ca38e323Sdegroote uint64_t id;
296ca38e323Sdegroote
297ca38e323Sdegroote p = ps->ps_states;
298ca38e323Sdegroote nb_states = ps->ps_len / sizeof(struct pfsync_state);
299ca38e323Sdegroote
300ca38e323Sdegroote for (i = 0; i < nb_states; i++, p++) {
301ca38e323Sdegroote fprintf(f, "state %s ", p->direction == PF_OUT ? "out" : "in");
302ca38e323Sdegroote fprintf(f, "on %s ", p->ifname);
303ca38e323Sdegroote
304ca38e323Sdegroote if ((proto = getprotobynumber(p->proto)) != NULL)
305ca38e323Sdegroote fprintf(f, "proto %s ", proto->p_name);
306ca38e323Sdegroote else
307ca38e323Sdegroote fprintf(f, "proto %u ", p->proto);
308ca38e323Sdegroote
309ca38e323Sdegroote
310ca38e323Sdegroote if (PF_ANEQ(&p->lan.addr, &p->gwy.addr, p->af) ||
311ca38e323Sdegroote (p->lan.port != p->gwy.port)) {
312ca38e323Sdegroote
313ca38e323Sdegroote char buf1[64], buf2[64], buf3[64];
314ca38e323Sdegroote fprintf(f, "from %s to %s using %s",
315ca38e323Sdegroote print_host(&p->lan, p->af, buf1, sizeof(buf1)),
316ca38e323Sdegroote print_host(&p->ext, p->af, buf2, sizeof(buf2)),
317ca38e323Sdegroote print_host(&p->gwy, p->af, buf3, sizeof(buf3)));
318ca38e323Sdegroote } else {
319ca38e323Sdegroote char buf1[64], buf2[64];
320ca38e323Sdegroote fprintf(f, "from %s to %s",
321ca38e323Sdegroote print_host(&p->lan, p->af, buf1, sizeof(buf1)),
322ca38e323Sdegroote print_host(&p->ext, p->af, buf2, sizeof(buf2)));
323ca38e323Sdegroote }
324ca38e323Sdegroote
325ca38e323Sdegroote memcpy(&id, p->id, sizeof(p->id));
326ca38e323Sdegroote fprintf(f, " id %" PRIu64 " cid %" PRIu32 " expire %" PRIu32 " timeout %" PRIu8,
327ca38e323Sdegroote id , p->creatorid, p->expire, p->timeout);
328ca38e323Sdegroote
329ca38e323Sdegroote if (p->direction == PF_OUT) {
330ca38e323Sdegroote src = &p->src;
331ca38e323Sdegroote dst = &p->dst;
332ca38e323Sdegroote } else {
333ca38e323Sdegroote src = &p->dst;
334ca38e323Sdegroote dst = &p->src;
335ca38e323Sdegroote }
336ca38e323Sdegroote
337ca38e323Sdegroote fprintf(f, " src ");
338ca38e323Sdegroote print_peer(src, p->proto, f);
339ca38e323Sdegroote fprintf(f, " dst ");
340ca38e323Sdegroote print_peer(dst, p->proto, f);
341ca38e323Sdegroote
342ca38e323Sdegroote fprintf(f, "\n");
343ca38e323Sdegroote }
344ca38e323Sdegroote }
345ca38e323Sdegroote
346ca38e323Sdegroote static int
print_states(int fd,int verbose,FILE * f)347ca38e323Sdegroote print_states(int fd, int verbose, FILE* f)
348ca38e323Sdegroote {
349ca38e323Sdegroote struct pfioc_states ps;
350ca38e323Sdegroote int nb_states;
351ca38e323Sdegroote
352ca38e323Sdegroote nb_states = get_states(fd, verbose, &ps);
353ca38e323Sdegroote if (nb_states <= 0) {
354ca38e323Sdegroote return nb_states;
355ca38e323Sdegroote }
356ca38e323Sdegroote
357ca38e323Sdegroote display_states(&ps, verbose, f);
358ca38e323Sdegroote
359ca38e323Sdegroote free(ps.ps_states);
360ca38e323Sdegroote return 0;
361ca38e323Sdegroote }
362ca38e323Sdegroote
363ca38e323Sdegroote static int
dump_states_ascii(int fd,int verbose,const char * filename)364ca38e323Sdegroote dump_states_ascii(int fd, int verbose, const char* filename)
365ca38e323Sdegroote {
366ca38e323Sdegroote FILE *f;
367ca38e323Sdegroote
368ca38e323Sdegroote if (strcmp(filename, "-") == 0) {
369ca38e323Sdegroote f = stdout;
370ca38e323Sdegroote } else {
371ca38e323Sdegroote f = fopen(filename, "w");
372ca38e323Sdegroote if (f == NULL)
373*8ee626c9Schristos err(EXIT_FAILURE, "Can't open %s", filename);
374ca38e323Sdegroote }
375ca38e323Sdegroote
376ca38e323Sdegroote print_states(fd, verbose, f);
377ca38e323Sdegroote
378ca38e323Sdegroote if (f != stdout)
379ca38e323Sdegroote fclose(f);
380ca38e323Sdegroote
381ca38e323Sdegroote return 0;
382ca38e323Sdegroote }
383ca38e323Sdegroote
384ca38e323Sdegroote static int
restore_states_ascii(int fd,int verbose __unused,const char * filename)385ca38e323Sdegroote restore_states_ascii(int fd, int verbose __unused, const char* filename)
386ca38e323Sdegroote {
387ca38e323Sdegroote FILE *f;
388ca38e323Sdegroote struct pfioc_states ps;
389ca38e323Sdegroote int errno_saved;
390ca38e323Sdegroote
391ca38e323Sdegroote f = fopen(filename, "r");
392ca38e323Sdegroote if (f == NULL)
393*8ee626c9Schristos err(EXIT_FAILURE, "Can't open %s", filename);
394ca38e323Sdegroote
395ca38e323Sdegroote parse(f, &ps);
396ca38e323Sdegroote
397ca38e323Sdegroote if (ioctl(fd, DIOCADDSTATES, &ps) == -1) {
398ca38e323Sdegroote errno_saved = errno;
399ca38e323Sdegroote fclose(f);
400ca38e323Sdegroote free(ps.ps_states);
401ca38e323Sdegroote errno = errno_saved;
402ca38e323Sdegroote err(EXIT_FAILURE, "DIOCADDSTATES");
403ca38e323Sdegroote }
404ca38e323Sdegroote
405ca38e323Sdegroote free(ps.ps_states);
406ca38e323Sdegroote fclose(f);
407ca38e323Sdegroote return 0;
408ca38e323Sdegroote }
409ca38e323Sdegroote
410ca38e323Sdegroote static int
setlock(int fd,int verbose,int lock)411ca38e323Sdegroote setlock(int fd, int verbose, int lock)
412ca38e323Sdegroote {
413ca38e323Sdegroote if (verbose)
414ca38e323Sdegroote printf("Turning lock %s\n", lock ? "on" : "off");
415ca38e323Sdegroote
416ca38e323Sdegroote if (ioctl(fd, DIOCSETLCK, &lock) == -1)
417ca38e323Sdegroote err(EXIT_FAILURE, "DIOCSETLCK");
418ca38e323Sdegroote
419ca38e323Sdegroote return 0;
420ca38e323Sdegroote }
421ca38e323Sdegroote
422ca38e323Sdegroote static int
test_ascii_dump(int verbose,const char * file1,const char * file2)423ca38e323Sdegroote test_ascii_dump(int verbose, const char* file1, const char *file2)
424ca38e323Sdegroote {
425ca38e323Sdegroote FILE *f1, *f2;
426ca38e323Sdegroote struct pfioc_states ps;
427ca38e323Sdegroote int errno_saved;
428ca38e323Sdegroote
429ca38e323Sdegroote f1 = fopen(file1, "r");
430ca38e323Sdegroote if (f1 == NULL)
431*8ee626c9Schristos err(EXIT_FAILURE, "Can't open %s", file1);
432ca38e323Sdegroote
433ca38e323Sdegroote
434ca38e323Sdegroote f2 = fopen(file2, "w");
435ca38e323Sdegroote if (f2 == NULL) {
436ca38e323Sdegroote errno_saved = errno;
437ca38e323Sdegroote fclose(f2);
438ca38e323Sdegroote errno = errno_saved;
439*8ee626c9Schristos err(EXIT_FAILURE, "Can't open %s", file2);
440ca38e323Sdegroote }
441ca38e323Sdegroote
442ca38e323Sdegroote parse(f1, &ps);
443ca38e323Sdegroote display_states(&ps, verbose, f2);
444ca38e323Sdegroote
445ca38e323Sdegroote free(ps.ps_states);
446ca38e323Sdegroote fclose(f1);
447ca38e323Sdegroote fclose(f2);
448ca38e323Sdegroote
449ca38e323Sdegroote return 0;
450ca38e323Sdegroote }
451ca38e323Sdegroote
main(int argc,char * argv[])452ca38e323Sdegroote int main(int argc, char *argv[])
453ca38e323Sdegroote {
454ca38e323Sdegroote setprogname(argv[0]);
455ca38e323Sdegroote
456ca38e323Sdegroote int lock = 0;
457ca38e323Sdegroote int set = 0;
458ca38e323Sdegroote int dump = 0;
459ca38e323Sdegroote int restore = 0;
460ca38e323Sdegroote int verbose = 0;
461ca38e323Sdegroote int test = 0;
462ca38e323Sdegroote bool binary = false;
463ca38e323Sdegroote char* filename = NULL;
464ca38e323Sdegroote char* filename2 = NULL;
465ca38e323Sdegroote int error = 0;
466ca38e323Sdegroote int fd;
467ca38e323Sdegroote int c;
468ca38e323Sdegroote
469ca38e323Sdegroote while ((c = getopt(argc, argv, "ulvw:r:R:W:bt:o:")) != -1)
470ca38e323Sdegroote switch (c) {
471ca38e323Sdegroote case 'u' :
472ca38e323Sdegroote lock = 0;
473ca38e323Sdegroote set = 1;
474ca38e323Sdegroote break;
475ca38e323Sdegroote
476ca38e323Sdegroote case 'l' :
477ca38e323Sdegroote lock = 1;
478ca38e323Sdegroote set = 1;
479ca38e323Sdegroote break;
480ca38e323Sdegroote
481ca38e323Sdegroote case 'b':
482ca38e323Sdegroote binary = true;
483ca38e323Sdegroote break;
484ca38e323Sdegroote
485ca38e323Sdegroote case 'r':
486ca38e323Sdegroote restore = 1;
487ca38e323Sdegroote filename = optarg;
488ca38e323Sdegroote break;
489ca38e323Sdegroote
490ca38e323Sdegroote case 'v':
491ca38e323Sdegroote verbose=1;
492ca38e323Sdegroote break;
493ca38e323Sdegroote
494ca38e323Sdegroote case 'w':
495ca38e323Sdegroote dump=1;
496ca38e323Sdegroote filename=optarg;
497ca38e323Sdegroote break;
498ca38e323Sdegroote
499ca38e323Sdegroote case 'R':
500ca38e323Sdegroote restore = 1;
501ca38e323Sdegroote set = 1;
502ca38e323Sdegroote filename = optarg;
503ca38e323Sdegroote break;
504ca38e323Sdegroote
505ca38e323Sdegroote case 'W':
506ca38e323Sdegroote dump = 1;
507ca38e323Sdegroote set = 1;
508ca38e323Sdegroote filename = optarg;
509ca38e323Sdegroote break;
510ca38e323Sdegroote
511ca38e323Sdegroote case 't':
512ca38e323Sdegroote test=1;
513ca38e323Sdegroote filename = optarg;
514ca38e323Sdegroote break;
515ca38e323Sdegroote
516ca38e323Sdegroote case 'o':
517ca38e323Sdegroote filename2 = optarg;
518ca38e323Sdegroote break;
519ca38e323Sdegroote
520ca38e323Sdegroote case '?' :
521ca38e323Sdegroote default:
522ca38e323Sdegroote usage();
523ca38e323Sdegroote }
524ca38e323Sdegroote
525ca38e323Sdegroote if (set == 0 && dump == 0 && restore == 0 && test == 0)
526ca38e323Sdegroote usage();
527ca38e323Sdegroote
528ca38e323Sdegroote if (dump == 1 && restore == 1)
529ca38e323Sdegroote usage();
530ca38e323Sdegroote
531ca38e323Sdegroote if (test == 1) {
532ca38e323Sdegroote if (filename2 == NULL) {
533ca38e323Sdegroote fprintf(stderr, "-o <file> is required when using -t\n");
534ca38e323Sdegroote err(EXIT_FAILURE, NULL);
535ca38e323Sdegroote }
536ca38e323Sdegroote error = test_ascii_dump(verbose, filename, filename2);
537ca38e323Sdegroote } else {
538ca38e323Sdegroote fd = open(pf_device, O_RDWR);
539ca38e323Sdegroote if (fd == -1)
540ca38e323Sdegroote err(EXIT_FAILURE, "Cannot open %s", pf_device);
541ca38e323Sdegroote
542ca38e323Sdegroote if (set != 0 && dump == 0 && restore == 0)
543ca38e323Sdegroote error = setlock(fd, verbose, lock);
544ca38e323Sdegroote
545ca38e323Sdegroote if (dump) {
546ca38e323Sdegroote if (set)
547ca38e323Sdegroote error = setlock(fd, verbose, 1);
548ca38e323Sdegroote
549ca38e323Sdegroote if (binary)
550ca38e323Sdegroote error = dump_states_binary(fd, verbose, filename);
551ca38e323Sdegroote else
552ca38e323Sdegroote error = dump_states_ascii(fd, verbose, filename);
553ca38e323Sdegroote
554ca38e323Sdegroote if (set)
555ca38e323Sdegroote error = setlock(fd, verbose, 0);
556ca38e323Sdegroote }
557ca38e323Sdegroote
558ca38e323Sdegroote if (restore) {
559ca38e323Sdegroote if (set)
560ca38e323Sdegroote error = setlock(fd, verbose, 1);
561ca38e323Sdegroote
562ca38e323Sdegroote if (binary)
563ca38e323Sdegroote error = restore_states_binary(fd, verbose, filename);
564ca38e323Sdegroote else
565ca38e323Sdegroote error = restore_states_ascii(fd, verbose, filename);
566ca38e323Sdegroote
567ca38e323Sdegroote if (set)
568ca38e323Sdegroote error = setlock(fd, verbose, 0);
569ca38e323Sdegroote }
570ca38e323Sdegroote
571ca38e323Sdegroote close(fd);
572ca38e323Sdegroote }
573ca38e323Sdegroote
574ca38e323Sdegroote return error;
575ca38e323Sdegroote }
576