xref: /netbsd-src/usr.sbin/npf/npfctl/npfctl.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: npfctl.c,v 1.1 2010/08/22 18:56:24 rmind Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This material is based upon work partially supported by The
8  * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/ioctl.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <err.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 
43 #include "npfctl.h"
44 
45 #define	NPFCTL_START		1
46 #define	NPFCTL_STOP		2
47 #define	NPFCTL_RELOAD		3
48 #define	NPFCTL_FLUSH		4
49 #define	NPFCTL_TABLE		5
50 
51 static struct operations_s {
52 	const char *		cmd;
53 	int			action;
54 } operations[] = {
55 	/* Start, stop, reload */
56 	{	"start",	NPFCTL_START	},
57 	{	"stop",		NPFCTL_STOP	},
58 	{	"reload",	NPFCTL_RELOAD	},
59 	{	"flush",	NPFCTL_FLUSH	},
60 	/* Table */
61 	{	"table",	NPFCTL_TABLE	},
62 	/* --- */
63 	{	NULL,		0		}
64 };
65 
66 void *
67 zalloc(size_t sz)
68 {
69 	void *p;
70 
71 	p = malloc(sz);
72 	if (p == NULL) {
73 		perror("zalloc");
74 		exit(EXIT_FAILURE);
75 	}
76 	memset(p, 0, sz);
77 	return p;
78 }
79 
80 char *
81 xstrdup(const char *s)
82 {
83 	char *p;
84 
85 	p = strdup(s);
86 	if (p == NULL) {
87 		perror("xstrdup");
88 		exit(EXIT_FAILURE);
89 	}
90 	return p;
91 }
92 
93 static void
94 usage(void)
95 {
96 	const char *progname = getprogname();
97 
98 	fprintf(stderr,
99 	    "usage:\t%s [ start | stop | reload ]\n",
100 	    progname);
101 	fprintf(stderr,
102 	    "\t%s table <tid> [ flush ]\n",
103 	    progname);
104 	fprintf(stderr,
105 	    "\t%s table <tid> { add | rem } <address/mask>\n",
106 	    progname);
107 
108 	exit(EXIT_FAILURE);
109 }
110 
111 static void
112 npfctl_parsecfg(const char *cfg)
113 {
114 	char *buf, *p;
115 	FILE *fp;
116 	size_t n;
117 	int l;
118 
119 	fp = fopen(cfg, "r");
120 	if (fp == NULL) {
121 		err(EXIT_FAILURE, "fopen");
122 	}
123 	l = 0;
124 	buf = NULL;
125 	while (getline(&buf, &n, fp) != -1) {
126 		l++;
127 		p = strpbrk(buf, "#\n");
128 		if (p != NULL) {
129 			*p = '\0';
130 		}
131 		if (npf_parseline(buf)) {
132 			fprintf(stderr, "invalid syntax at line %d\n", l);
133 			exit(EXIT_FAILURE);
134 		}
135 	}
136 	if (buf != NULL) {
137 		free(buf);
138 	}
139 }
140 
141 static void
142 npfctl(int action, int argc, char **argv)
143 {
144 	int fd, ret, ver, boolval;
145 	npf_ioctl_table_t tbl;
146 	char *arg;
147 
148 #ifdef DEBUG
149 	npfctl_init_data();
150 	npfctl_parsecfg("npf.conf");
151 	ret = npfctl_ioctl_send(fd);
152 	return;
153 #endif
154 	fd = open(NPF_DEV_PATH, O_RDONLY);
155 	if (fd == -1) {
156 		err(EXIT_FAILURE, "cannot open " NPF_DEV_PATH);
157 	}
158 	ret = ioctl(fd, IOC_NPF_VERSION, &ver);
159 	if (ver != NPF_VERSION) {
160 		errx(EXIT_FAILURE, "incompatible npf interface version "
161 		    "(%d, kernel %d)", NPF_VERSION, ver);
162 	}
163 	switch (action) {
164 	case NPFCTL_START:
165 		boolval = true;
166 		ret = ioctl(fd, IOC_NPF_SWITCH, &boolval);
167 		break;
168 	case NPFCTL_STOP:
169 		boolval = false;
170 		ret = ioctl(fd, IOC_NPF_SWITCH, &boolval);
171 		break;
172 	case NPFCTL_RELOAD:
173 		npfctl_init_data();
174 		npfctl_parsecfg(argc < 3 ? NPF_CONF_PATH : argv[2]);
175 		ret = npfctl_ioctl_send(fd);
176 		break;
177 	case NPFCTL_FLUSH:
178 		/* Pass empty configuration to flush. */
179 		npfctl_init_data();
180 		ret = npfctl_ioctl_send(fd);
181 		break;
182 	case NPFCTL_TABLE:
183 		if (argc < 5) {
184 			usage();
185 		}
186 		tbl.nct_tid = atoi(argv[2]);
187 		if (strcmp(argv[3], "add") == 0) {
188 			tbl.nct_action = NPF_IOCTL_TBLENT_ADD;
189 			arg = argv[4];
190 		} else if (strcmp(argv[3], "rem") == 0) {
191 			tbl.nct_action = NPF_IOCTL_TBLENT_REM;
192 			arg = argv[4];
193 		} else {
194 			tbl.nct_action = 0;
195 			arg = argv[3];
196 		}
197 		if (!npfctl_parse_v4mask(arg,
198 		    &tbl.nct_addr, &tbl.nct_mask)) {
199 			errx(EXIT_FAILURE, "invalid CIDR '%s'", arg);
200 		}
201 		ret = ioctl(fd, IOC_NPF_TABLE, &tbl);
202 		break;
203 	}
204 	if (ret == -1) {
205 		err(EXIT_FAILURE, "ioctl");
206 	}
207 	close(fd);
208 }
209 
210 int
211 main(int argc, char **argv)
212 {
213 	char *cmd;
214 	int n;
215 
216 	if (argc < 2) {
217 		usage();
218 	}
219 	cmd = argv[1];
220 
221 	/* Find and call the subroutine */
222 	for (n = 0; operations[n].cmd != NULL; n++) {
223 		if (strcmp(cmd, operations[n].cmd) != 0)
224 			continue;
225 		npfctl(operations[n].action, argc, argv);
226 		break;
227 	}
228 	return 0;
229 }
230