1 /* $NetBSD: pfsync.c,v 1.1 2009/09/14 10:36:49 degroote Exp $ */ 2 /*- 3 * Copyright (c) 2009 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #ifndef lint 30 __RCSID("$NetBSD: pfsync.c,v 1.1 2009/09/14 10:36:49 degroote Exp $"); 31 #endif /* not lint */ 32 33 #include <sys/param.h> 34 #include <sys/ioctl.h> 35 #include <sys/socket.h> 36 #include <sys/sockio.h> 37 38 #include <net/if.h> 39 #include <net/route.h> 40 #include <net/pfvar.h> 41 #include <net/if_pfsync.h> 42 43 #include <arpa/inet.h> 44 45 #include <stdio.h> 46 #include <string.h> 47 #include <stdlib.h> 48 #include <unistd.h> 49 #include <err.h> 50 #include <errno.h> 51 #include <util.h> 52 53 #include "env.h" 54 #include "parse.h" 55 #include "extern.h" 56 57 static status_func_t status; 58 static usage_func_t usage; 59 static cmdloop_branch_t branch; 60 61 static void pfsync_constructor(void) __attribute__((constructor)); 62 static void pfsync_status(prop_dictionary_t, prop_dictionary_t); 63 static int setpfsync_maxupd(prop_dictionary_t, prop_dictionary_t); 64 static int setpfsync_peer(prop_dictionary_t, prop_dictionary_t); 65 static int setpfsyncdev(prop_dictionary_t, prop_dictionary_t); 66 67 struct pinteger parse_maxupd = PINTEGER_INITIALIZER1(&parse_maxupd, "maxupd", 68 0, 255, 10, setpfsync_maxupd, "maxupd", &command_root.pb_parser); 69 70 struct piface pfsyncdev = PIFACE_INITIALIZER(&pfsyncdev, "syncdev", setpfsyncdev, 71 "syncdev", &command_root.pb_parser); 72 73 struct paddr parse_sync_peer = PADDR_INITIALIZER(&parse_sync_peer, "syncpeer", 74 setpfsync_peer, "syncpeer", NULL, NULL, NULL, &command_root.pb_parser); 75 76 static const struct kwinst pfsynckw[] = { 77 {.k_word = "maxupd", .k_nextparser = &parse_maxupd.pi_parser}, 78 {.k_word = "syncdev", .k_nextparser = &pfsyncdev.pif_parser}, 79 {.k_word = "-syncdev", .k_key = "syncdev", .k_type = KW_T_STR, 80 .k_str = "", .k_exec = setpfsyncdev, 81 .k_nextparser = &command_root.pb_parser}, 82 {.k_word = "syncpeer", .k_nextparser = &parse_sync_peer.pa_parser}, 83 {.k_word = "-syncpeer", .k_key = "syncpeer", .k_type = KW_T_STR, 84 .k_str = "", .k_exec = setpfsync_peer, 85 .k_nextparser = &command_root.pb_parser} 86 }; 87 88 struct pkw pfsync = PKW_INITIALIZER(&pfsync, "pfsync", NULL, NULL, 89 pfsynckw, __arraycount(pfsynckw), NULL); 90 91 static void 92 pfsync_set(prop_dictionary_t env, struct pfsyncreq *pfsyncr) 93 { 94 if (indirect_ioctl(env, SIOCSETPFSYNC, pfsyncr) == -1) 95 err(EXIT_FAILURE, "SIOCSETPFSYNC"); 96 } 97 98 static int 99 pfsync_get1(prop_dictionary_t env, struct pfsyncreq *pfsyncr) 100 { 101 memset(pfsyncr, 0, sizeof(*pfsyncr)); 102 103 return indirect_ioctl(env, SIOCGETPFSYNC, pfsyncr); 104 } 105 106 static void 107 pfsync_get(prop_dictionary_t env, struct pfsyncreq *pfsyncr) 108 { 109 if (pfsync_get1(env, pfsyncr) == -1) 110 err(EXIT_FAILURE, "SIOCGETPFSYNC"); 111 } 112 113 static void 114 pfsync_status(prop_dictionary_t env, prop_dictionary_t oenv) 115 { 116 struct pfsyncreq pfsyncr; 117 118 if (pfsync_get1(env, &pfsyncr) == -1) 119 return; 120 121 if (pfsyncr.pfsyncr_syncdev[0] != '\0') { 122 printf("\tpfsync: syncdev: %s ", pfsyncr.pfsyncr_syncdev); 123 if (pfsyncr.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP) 124 printf("syncpeer: %s ", 125 inet_ntoa(pfsyncr.pfsyncr_syncpeer)); 126 printf("maxupd: %d\n", pfsyncr.pfsyncr_maxupdates); 127 } 128 } 129 130 /* ARGSUSED */ 131 int 132 setpfsync_maxupd(prop_dictionary_t env, prop_dictionary_t oenv) 133 { 134 struct pfsyncreq pfsyncr; 135 uint8_t maxupd; 136 137 if (!prop_dictionary_get_uint8(env, "maxupd", &maxupd)) { 138 errno = ENOENT; 139 return -1; 140 } 141 142 pfsync_get(env, &pfsyncr); 143 144 pfsyncr.pfsyncr_maxupdates = maxupd; 145 146 pfsync_set(env, &pfsyncr); 147 return 0; 148 } 149 150 151 /* ARGSUSED */ 152 int 153 setpfsyncdev(prop_dictionary_t env, prop_dictionary_t oenv) 154 { 155 struct pfsyncreq pfsyncr; 156 const char *dev; 157 158 if (!prop_dictionary_get_cstring_nocopy(env, "syncdev", &dev)) { 159 errno = ENOENT; 160 return -1; 161 } 162 163 pfsync_get(env, &pfsyncr); 164 165 strlcpy(pfsyncr.pfsyncr_syncdev, dev, sizeof(pfsyncr.pfsyncr_syncdev)); 166 167 pfsync_set(env, &pfsyncr); 168 return 0; 169 } 170 171 /* ARGSUSED */ 172 int 173 setpfsync_peer(prop_dictionary_t env, prop_dictionary_t oenv) 174 { 175 struct pfsyncreq pfsyncr; 176 prop_data_t data; 177 const struct paddr_prefix *peerpfx; 178 const struct sockaddr_in *s; 179 180 data = (prop_data_t)prop_dictionary_get(env, "syncpeer"); 181 if (data == NULL) { 182 errno = ENOENT; 183 return -1; 184 } 185 186 pfsync_get(env, &pfsyncr); 187 188 peerpfx = prop_data_data_nocopy(data); 189 190 if (peerpfx != NULL) { 191 // Only AF_INET is supported for now 192 if (peerpfx->pfx_addr.sa_family != AF_INET) { 193 errno = ENOENT; 194 return -1; 195 } 196 197 198 s = (const struct sockaddr_in*)&peerpfx->pfx_addr; 199 200 memcpy(&pfsyncr.pfsyncr_syncpeer.s_addr, &s->sin_addr, 201 MIN(sizeof(pfsyncr.pfsyncr_syncpeer.s_addr), 202 peerpfx->pfx_addr.sa_len)); 203 } else { 204 memset(&pfsyncr.pfsyncr_syncpeer.s_addr, 0, 205 sizeof(pfsyncr.pfsyncr_syncpeer.s_addr)); 206 } 207 208 pfsync_set(env, &pfsyncr); 209 210 return 0; 211 } 212 213 static void 214 pfsync_usage(prop_dictionary_t env) 215 { 216 fprintf(stderr, 217 "\t[ maxupd n ] [ syncdev iface ] [syncpeer peer_addr]\n"); 218 } 219 220 static void 221 pfsync_constructor(void) 222 { 223 cmdloop_branch_init(&branch, &pfsync.pk_parser); 224 register_cmdloop_branch(&branch); 225 status_func_init(&status, pfsync_status); 226 usage_func_init(&usage, pfsync_usage); 227 register_status(&status); 228 register_usage(&usage); 229 } 230