xref: /freebsd/sys/netpfil/pf/pf_nv.c (revision 7606a45dcc87cb6b222af929dad37b615cb925cf)
15c62ededSKristof Provost /*-
25c62ededSKristof Provost  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
35c62ededSKristof Provost  *
45c62ededSKristof Provost  * Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
55c62ededSKristof Provost  *
65c62ededSKristof Provost  * Redistribution and use in source and binary forms, with or without
75c62ededSKristof Provost  * modification, are permitted provided that the following conditions
85c62ededSKristof Provost  * are met:
95c62ededSKristof Provost  * 1. Redistributions of source code must retain the above copyright
105c62ededSKristof Provost  *    notice, this list of conditions and the following disclaimer.
115c62ededSKristof Provost  * 2. Redistributions in binary form must reproduce the above copyright
125c62ededSKristof Provost  *    notice, this list of conditions and the following disclaimer in the
135c62ededSKristof Provost  *    documentation and/or other materials provided with the distribution.
145c62ededSKristof Provost  *
155c62ededSKristof Provost  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165c62ededSKristof Provost  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175c62ededSKristof Provost  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185c62ededSKristof Provost  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
195c62ededSKristof Provost  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205c62ededSKristof Provost  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
215c62ededSKristof Provost  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225c62ededSKristof Provost  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235c62ededSKristof Provost  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
245c62ededSKristof Provost  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255c62ededSKristof Provost  * SUCH DAMAGE.
265c62ededSKristof Provost  *
275c62ededSKristof Provost  */
285c62ededSKristof Provost #include <sys/cdefs.h>
295c62ededSKristof Provost __FBSDID("$FreeBSD$");
305c62ededSKristof Provost 
315c62ededSKristof Provost #include <sys/param.h>
325c62ededSKristof Provost #include <sys/errno.h>
335c62ededSKristof Provost #include <sys/limits.h>
345c62ededSKristof Provost #include <sys/systm.h>
355c62ededSKristof Provost 
365c62ededSKristof Provost #include <netpfil/pf/pf_nv.h>
375c62ededSKristof Provost 
38eaabed8aSKristof Provost #define	PF_NV_IMPL_UINT(fnname, type, max)					\
395c62ededSKristof Provost 	int									\
40d710367dSKristof Provost 	pf_nv ## fnname(const nvlist_t *nvl, const char *name, type *val)	\
415c62ededSKristof Provost 	{									\
425c62ededSKristof Provost 		uint64_t raw;							\
435c62ededSKristof Provost 		if (! nvlist_exists_number(nvl, name))				\
445c62ededSKristof Provost 			return (EINVAL);					\
455c62ededSKristof Provost 		raw = nvlist_get_number(nvl, name);				\
465c62ededSKristof Provost 		if (raw > max)							\
475c62ededSKristof Provost 			return (ERANGE);					\
485c62ededSKristof Provost 		*val = (type)raw;						\
495c62ededSKristof Provost 		return (0);							\
505c62ededSKristof Provost 	}									\
515c62ededSKristof Provost 	int									\
52d710367dSKristof Provost 	pf_nv ## fnname ## _array(const nvlist_t *nvl, const char *name,	\
53d710367dSKristof Provost 	    type *array, size_t maxelems, size_t *nelems)			\
545c62ededSKristof Provost 	{									\
555c62ededSKristof Provost 		const uint64_t *n;						\
565c62ededSKristof Provost 		size_t nitems;							\
575c62ededSKristof Provost 		bzero(array, sizeof(type) * maxelems);				\
585c62ededSKristof Provost 		if (! nvlist_exists_number_array(nvl, name))			\
595c62ededSKristof Provost 			return (EINVAL);					\
605c62ededSKristof Provost 		n = nvlist_get_number_array(nvl, name, &nitems);		\
615c62ededSKristof Provost 		if (nitems != maxelems)						\
625c62ededSKristof Provost 			return (E2BIG);						\
635c62ededSKristof Provost 		if (nelems != NULL)						\
645c62ededSKristof Provost 			*nelems = nitems;					\
655c62ededSKristof Provost 		for (size_t i = 0; i < nitems; i++) {				\
665c62ededSKristof Provost 			if (n[i] > max)						\
675c62ededSKristof Provost 				return (ERANGE);				\
685c62ededSKristof Provost 			array[i] = (type)n[i];					\
695c62ededSKristof Provost 		}								\
705c62ededSKristof Provost 		return (0);							\
71d710367dSKristof Provost 	}									\
72d710367dSKristof Provost 	void									\
73d710367dSKristof Provost 	pf_ ## fnname ## _array_nv(nvlist_t *nvl, const char *name,		\
74d710367dSKristof Provost 	    const type *numbers, size_t count)					\
75d710367dSKristof Provost 	{									\
76d710367dSKristof Provost 		uint64_t tmp;							\
77d710367dSKristof Provost 		for (size_t i = 0; i < count; i++) {				\
78d710367dSKristof Provost 			tmp = numbers[i];					\
79d710367dSKristof Provost 			nvlist_append_number_array(nvl, name, tmp);		\
80d710367dSKristof Provost 		}								\
815c62ededSKristof Provost 	}
82d710367dSKristof Provost 
835c62ededSKristof Provost int
845c62ededSKristof Provost pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
855c62ededSKristof Provost     size_t expected_size)
865c62ededSKristof Provost {
875c62ededSKristof Provost 	const uint8_t *nvdata;
885c62ededSKristof Provost 	size_t len;
895c62ededSKristof Provost 
905c62ededSKristof Provost 	bzero(data, expected_size);
915c62ededSKristof Provost 
925c62ededSKristof Provost 	if (! nvlist_exists_binary(nvl, name))
935c62ededSKristof Provost 		return (EINVAL);
945c62ededSKristof Provost 
955c62ededSKristof Provost 	nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len);
965c62ededSKristof Provost 	if (len > expected_size)
975c62ededSKristof Provost 		return (EINVAL);
985c62ededSKristof Provost 
995c62ededSKristof Provost 	memcpy(data, nvdata, len);
1005c62ededSKristof Provost 
1015c62ededSKristof Provost 	return (0);
1025c62ededSKristof Provost }
1035c62ededSKristof Provost 
104eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX);
105eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX);
106eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX);
107*7606a45dSKristof Provost PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX);
1085c62ededSKristof Provost 
1095c62ededSKristof Provost int
1105c62ededSKristof Provost pf_nvint(const nvlist_t *nvl, const char *name, int *val)
1115c62ededSKristof Provost {
1125c62ededSKristof Provost 	int64_t raw;
1135c62ededSKristof Provost 
1145c62ededSKristof Provost 	if (! nvlist_exists_number(nvl, name))
1155c62ededSKristof Provost 		return (EINVAL);
1165c62ededSKristof Provost 
1175c62ededSKristof Provost 	raw = nvlist_get_number(nvl, name);
1185c62ededSKristof Provost 	if (raw > INT_MAX || raw < INT_MIN)
1195c62ededSKristof Provost 		return (ERANGE);
1205c62ededSKristof Provost 
1215c62ededSKristof Provost 	*val = (int)raw;
1225c62ededSKristof Provost 
1235c62ededSKristof Provost 	return (0);
1245c62ededSKristof Provost }
1255c62ededSKristof Provost 
1265c62ededSKristof Provost int
1275c62ededSKristof Provost pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen)
1285c62ededSKristof Provost {
1295c62ededSKristof Provost 	int ret;
1305c62ededSKristof Provost 
1315c62ededSKristof Provost 	if (! nvlist_exists_string(nvl, name))
1325c62ededSKristof Provost 		return (EINVAL);
1335c62ededSKristof Provost 
1345c62ededSKristof Provost 	ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen);
1355c62ededSKristof Provost 	if (ret >= maxlen)
1365c62ededSKristof Provost 		return (EINVAL);
1375c62ededSKristof Provost 
1385c62ededSKristof Provost 	return (0);
1395c62ededSKristof Provost }
140