1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2022 InnoGames GmbH 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include "opt_inet.h" 33 #include "opt_inet6.h" 34 35 #include <sys/param.h> 36 #include <sys/errno.h> 37 38 #include <netpfil/pf/pfsync_nv.h> 39 40 int 41 pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl, 42 struct sockaddr_storage *sa) 43 { 44 int af; 45 46 if (!nvlist_exists_number(nvl, "af")) 47 return (EINVAL); 48 if (!nvlist_exists_binary(nvl, "address")) 49 return (EINVAL); 50 51 af = nvlist_get_number(nvl, "af"); 52 53 switch (af) { 54 #ifdef INET 55 case AF_INET: { 56 struct sockaddr_in *in = (struct sockaddr_in *)sa; 57 size_t len; 58 const void *addr = nvlist_get_binary(nvl, "address", &len); 59 in->sin_family = af; 60 if (len != sizeof(*in)) 61 return (EINVAL); 62 63 memcpy(in, addr, sizeof(*in)); 64 break; 65 } 66 #endif 67 #ifdef INET6 68 case AF_INET6: { 69 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; 70 size_t len; 71 const void *addr = nvlist_get_binary(nvl, "address", &len); 72 in6->sin6_family = af; 73 if (len != sizeof(*in6)) 74 return (EINVAL); 75 76 memcpy(in6, addr, sizeof(*in6)); 77 break; 78 } 79 #endif 80 default: 81 return (EINVAL); 82 } 83 84 return (0); 85 } 86 87 nvlist_t * 88 pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa) 89 { 90 nvlist_t *nvl; 91 92 nvl = nvlist_create(0); 93 if (nvl == NULL) { 94 return (nvl); 95 } 96 97 switch (sa->ss_family) { 98 #ifdef INET 99 case AF_INET: { 100 struct sockaddr_in *in = (struct sockaddr_in *)sa; 101 nvlist_add_number(nvl, "af", in->sin_family); 102 nvlist_add_binary(nvl, "address", in, sizeof(*in)); 103 break; 104 } 105 #endif 106 #ifdef INET6 107 case AF_INET6: { 108 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; 109 nvlist_add_number(nvl, "af", in6->sin6_family); 110 nvlist_add_binary(nvl, "address", in6, sizeof(*in6)); 111 break; 112 } 113 #endif 114 default: 115 return NULL; 116 } 117 118 return (nvl); 119 } 120 121 int 122 pfsync_nvstatus_to_kstatus(const nvlist_t *nvl, struct pfsync_kstatus *status) 123 { 124 struct sockaddr_storage addr; 125 int error; 126 127 if (!nvlist_exists_number(nvl, "maxupdates")) 128 return (EINVAL); 129 if (!nvlist_exists_number(nvl, "flags")) 130 return (EINVAL); 131 132 status->maxupdates = nvlist_get_number(nvl, "maxupdates"); 133 status->flags = nvlist_get_number(nvl, "flags"); 134 135 if (nvlist_exists_string(nvl, "syncdev")) 136 strlcpy(status->syncdev, nvlist_get_string(nvl, "syncdev"), 137 IFNAMSIZ); 138 139 if (nvlist_exists_nvlist(nvl, "syncpeer")) { 140 memset(&addr, 0, sizeof(addr)); 141 if ((error = pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl, "syncpeer"), &addr)) != 0) 142 return (error); 143 144 status->syncpeer = addr; 145 } else { 146 memset(&status->syncpeer, 0, sizeof(status->syncpeer)); 147 } 148 149 return (0); 150 } 151