1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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 #include "opt_inet.h"
31 #include "opt_inet6.h"
32
33 #include <sys/param.h>
34 #include <sys/errno.h>
35
36 #include <netinet/in.h>
37
38 #include <netinet6/ip6_var.h>
39 #include <netinet6/scope6_var.h>
40
41 #include <netpfil/pf/pfsync_nv.h>
42
43 int
pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t * nvl,struct sockaddr_storage * sa)44 pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl,
45 struct sockaddr_storage *sa)
46 {
47 int af;
48
49 if (!nvlist_exists_number(nvl, "af"))
50 return (EINVAL);
51 if (!nvlist_exists_binary(nvl, "address"))
52 return (EINVAL);
53
54 af = nvlist_get_number(nvl, "af");
55
56 switch (af) {
57 #ifdef INET
58 case AF_INET: {
59 struct sockaddr_in *in = (struct sockaddr_in *)sa;
60 size_t len;
61 const void *addr = nvlist_get_binary(nvl, "address", &len);
62 in->sin_family = af;
63 if (len != sizeof(*in))
64 return (EINVAL);
65
66 memcpy(in, addr, sizeof(*in));
67 break;
68 }
69 #endif
70 #ifdef INET6
71 case AF_INET6: {
72 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
73 size_t len;
74 int error;
75 const void *addr = nvlist_get_binary(nvl, "address", &len);
76 in6->sin6_family = af;
77 if (len != sizeof(*in6))
78 return (EINVAL);
79
80 memcpy(in6, addr, sizeof(*in6));
81
82 error = sa6_embedscope(in6, V_ip6_use_defzone);
83 if (error)
84 return (error);
85
86 break;
87 }
88 #endif
89 default:
90 return (EINVAL);
91 }
92
93 return (0);
94 }
95
96 nvlist_t *
pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage * sa)97 pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa)
98 {
99 nvlist_t *nvl;
100
101 nvl = nvlist_create(0);
102 if (nvl == NULL) {
103 return (nvl);
104 }
105
106 switch (sa->ss_family) {
107 #ifdef INET
108 case AF_INET: {
109 struct sockaddr_in *in = (struct sockaddr_in *)sa;
110 nvlist_add_number(nvl, "af", in->sin_family);
111 nvlist_add_binary(nvl, "address", in, sizeof(*in));
112 break;
113 }
114 #endif
115 #ifdef INET6
116 case AF_INET6: {
117 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
118 sa6_recoverscope(in6);
119 nvlist_add_number(nvl, "af", in6->sin6_family);
120 nvlist_add_binary(nvl, "address", in6, sizeof(*in6));
121 break;
122 }
123 #endif
124 default:
125 return NULL;
126 }
127
128 return (nvl);
129 }
130
131 int
pfsync_nvstatus_to_kstatus(const nvlist_t * nvl,struct pfsync_kstatus * status)132 pfsync_nvstatus_to_kstatus(const nvlist_t *nvl, struct pfsync_kstatus *status)
133 {
134 struct sockaddr_storage addr;
135 int error;
136
137 if (!nvlist_exists_number(nvl, "maxupdates"))
138 return (EINVAL);
139 if (!nvlist_exists_number(nvl, "flags"))
140 return (EINVAL);
141
142 status->maxupdates = nvlist_get_number(nvl, "maxupdates");
143 status->version = nvlist_get_number(nvl, "version");
144 status->flags = nvlist_get_number(nvl, "flags");
145
146 if (nvlist_exists_string(nvl, "syncdev"))
147 strlcpy(status->syncdev, nvlist_get_string(nvl, "syncdev"),
148 IFNAMSIZ);
149
150 if (nvlist_exists_nvlist(nvl, "syncpeer")) {
151 memset(&addr, 0, sizeof(addr));
152 if ((error = pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl, "syncpeer"), &addr)) != 0)
153 return (error);
154
155 status->syncpeer = addr;
156 } else {
157 memset(&status->syncpeer, 0, sizeof(status->syncpeer));
158 }
159
160 return (0);
161 }
162