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