1 /*- 2 * Copyright (c) 2025 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Emmanuel Nyarko. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __RCSID("$NetBSD: npfext_route.c,v 1.3 2026/10/08 09:28:41 joe Exp $"); 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <sys/ioctl.h> 36 #include <net/if.h> 37 38 #include <stdio.h> 39 #include <string.h> 40 #include <assert.h> 41 #include <errno.h> 42 #include <err.h> 43 #include <unistd.h> 44 #include <arpa/inet.h> 45 46 #include <npf.h> 47 48 int npfext_route_init(void); 49 nl_ext_t * npfext_route_construct(const char *); 50 int npfext_route_param(nl_ext_t *, const char *, const char *); 51 52 int 53 npfext_route_init(void) 54 { 55 /* Nothing to initialise. */ 56 return 0; 57 } 58 59 nl_ext_t * 60 npfext_route_construct(const char *name) 61 { 62 assert(strcmp(name, "route") == 0); 63 return npf_ext_construct(name); 64 } 65 66 int 67 npfext_route_param(nl_ext_t *ext, const char *param, const char *val) 68 { 69 enum ptype { 70 PARAM_INTERFACE, 71 PARAM_INET4, 72 PARAM_INET6, 73 PARAM_DUP, 74 }; 75 static const struct param { 76 const char * name; 77 enum ptype type; 78 bool reqval; 79 } params[] = { 80 { "interface", PARAM_INTERFACE, true }, 81 { "via", PARAM_INET4, true }, 82 { "via6", PARAM_INET6, true }, 83 { "dup-to", PARAM_DUP, false }, 84 }; 85 86 for (unsigned i = 0; i < __arraycount(params); i++) { 87 const char *name = params[i].name; 88 struct in_addr addr; 89 struct in6_addr addr6; 90 91 if (strcmp(name, param) != 0) { 92 continue; 93 } 94 if (val == NULL && params[i].reqval) { 95 return EINVAL; 96 } 97 98 switch (params[i].type) { 99 case PARAM_DUP: 100 npf_ext_param_bool(ext, name, true); 101 break; 102 case PARAM_INTERFACE: 103 npf_ext_param_string(ext, "route-interface", val); 104 break; 105 /* catch invalid addresses early */ 106 case PARAM_INET4: 107 if (inet_pton(AF_INET, val, &addr) != 1) { 108 warn("Invalid IPv4 address `%s'", val); 109 return EINVAL; 110 } 111 npf_ext_param_binary(ext, name, &addr, sizeof(struct in_addr)); 112 break; 113 case PARAM_INET6: 114 if (inet_pton(AF_INET6, val, &addr6) != 1) { 115 warn("Invalid IPv6 address `%s'", val); 116 return EINVAL; 117 } 118 npf_ext_param_binary(ext, name, &addr6, sizeof(struct in6_addr)); 119 break; 120 121 default: 122 break; 123 } 124 } 125 return 0; 126 } 127