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