1215bab79SShivank Garg /*- 2215bab79SShivank Garg * Copyright (c) 2003-2004 Networks Associates Technology, Inc. 3215bab79SShivank Garg * Copyright (c) 2006 SPARTA, Inc. 4215bab79SShivank Garg * Copyright (c) 2019, 2023 Shivank Garg <shivank@FreeBSD.org> 5215bab79SShivank Garg * 6215bab79SShivank Garg * This software was developed for the FreeBSD Project by Network 7215bab79SShivank Garg * Associates Laboratories, the Security Research Division of Network 8215bab79SShivank Garg * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 9215bab79SShivank Garg * as part of the DARPA CHATS research program. 10215bab79SShivank Garg * 11215bab79SShivank Garg * This software was enhanced by SPARTA ISSO under SPAWAR contract 12215bab79SShivank Garg * N66001-04-C-6019 ("SEFOS"). 13215bab79SShivank Garg * 14215bab79SShivank Garg * This code was developed as a Google Summer of Code 2019 project 15215bab79SShivank Garg * under the guidance of Bjoern A. Zeeb. 16215bab79SShivank Garg * 17215bab79SShivank Garg * Redistribution and use in source and binary forms, with or without 18215bab79SShivank Garg * modification, are permitted provided that the following conditions 19215bab79SShivank Garg * are met: 20215bab79SShivank Garg * 1. Redistributions of source code must retain the above copyright 21215bab79SShivank Garg * notice, this list of conditions and the following disclaimer. 22215bab79SShivank Garg * 2. Redistributions in binary form must reproduce the above copyright 23215bab79SShivank Garg * notice, this list of conditions and the following disclaimer in the 24215bab79SShivank Garg * documentation and/or other materials provided with the distribution. 25215bab79SShivank Garg * 26215bab79SShivank Garg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27215bab79SShivank Garg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28215bab79SShivank Garg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29215bab79SShivank Garg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30215bab79SShivank Garg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31215bab79SShivank Garg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32215bab79SShivank Garg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33215bab79SShivank Garg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34215bab79SShivank Garg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35215bab79SShivank Garg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36215bab79SShivank Garg * SUCH DAMAGE. 37215bab79SShivank Garg */ 38215bab79SShivank Garg 39215bab79SShivank Garg /* 40215bab79SShivank Garg * The IP address access control policy module - mac_ipacl allows the root of 41215bab79SShivank Garg * the host to limit the VNET jail's privileges of setting IPv4 and IPv6 42215bab79SShivank Garg * addresses via sysctl(8) interface. So, the host can define rules for jails 43215bab79SShivank Garg * and their interfaces about IP addresses. 44215bab79SShivank Garg * sysctl(8) is to be used to modify the rules string in following format- 45215bab79SShivank Garg * "jail_id,allow,interface,address_family,IP_addr/prefix_length[@jail_id,...]" 46215bab79SShivank Garg */ 47215bab79SShivank Garg 48215bab79SShivank Garg #include "opt_inet.h" 49215bab79SShivank Garg #include "opt_inet6.h" 50215bab79SShivank Garg 51215bab79SShivank Garg #include <sys/param.h> 52215bab79SShivank Garg #include <sys/module.h> 53215bab79SShivank Garg #include <sys/errno.h> 54215bab79SShivank Garg #include <sys/kernel.h> 55215bab79SShivank Garg #include <sys/mutex.h> 56215bab79SShivank Garg #include <sys/priv.h> 57215bab79SShivank Garg #include <sys/queue.h> 58215bab79SShivank Garg #include <sys/socket.h> 59215bab79SShivank Garg #include <sys/sysctl.h> 60215bab79SShivank Garg #include <sys/systm.h> 61215bab79SShivank Garg #include <sys/types.h> 62215bab79SShivank Garg #include <sys/ucred.h> 63215bab79SShivank Garg #include <sys/jail.h> 64215bab79SShivank Garg 65215bab79SShivank Garg #include <net/if.h> 66215bab79SShivank Garg #include <net/if_var.h> 67215bab79SShivank Garg 68215bab79SShivank Garg #include <netinet/in.h> 69215bab79SShivank Garg #include <netinet6/scope6_var.h> 70215bab79SShivank Garg 71215bab79SShivank Garg #include <security/mac/mac_policy.h> 72215bab79SShivank Garg 73215bab79SShivank Garg static SYSCTL_NODE(_security_mac, OID_AUTO, ipacl, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 74215bab79SShivank Garg "TrustedBSD mac_ipacl policy controls"); 75215bab79SShivank Garg 76215bab79SShivank Garg #ifdef INET 77215bab79SShivank Garg static int ipacl_ipv4 = 1; 78215bab79SShivank Garg SYSCTL_INT(_security_mac_ipacl, OID_AUTO, ipv4, CTLFLAG_RWTUN, 79215bab79SShivank Garg &ipacl_ipv4, 0, "Enforce mac_ipacl for IPv4 addresses"); 80215bab79SShivank Garg #endif 81215bab79SShivank Garg 82215bab79SShivank Garg #ifdef INET6 83215bab79SShivank Garg static int ipacl_ipv6 = 1; 84215bab79SShivank Garg SYSCTL_INT(_security_mac_ipacl, OID_AUTO, ipv6, CTLFLAG_RWTUN, 85215bab79SShivank Garg &ipacl_ipv6, 0, "Enforce mac_ipacl for IPv6 addresses"); 86215bab79SShivank Garg #endif 87215bab79SShivank Garg 88215bab79SShivank Garg static MALLOC_DEFINE(M_IPACL, "ipacl_rule", "Rules for mac_ipacl"); 89215bab79SShivank Garg 90215bab79SShivank Garg #define MAC_RULE_STRING_LEN 1024 91215bab79SShivank Garg 92215bab79SShivank Garg struct ipacl_addr { 93215bab79SShivank Garg union { 94215bab79SShivank Garg #ifdef INET 95215bab79SShivank Garg struct in_addr ipv4; 96215bab79SShivank Garg #endif 97215bab79SShivank Garg #ifdef INET6 98215bab79SShivank Garg struct in6_addr ipv6; 99215bab79SShivank Garg #endif 100215bab79SShivank Garg u_int8_t addr8[16]; 101215bab79SShivank Garg u_int16_t addr16[8]; 102215bab79SShivank Garg u_int32_t addr32[4]; 103215bab79SShivank Garg } ipa; /* 128 bit address*/ 104215bab79SShivank Garg #ifdef INET 105215bab79SShivank Garg #define v4 ipa.ipv4 106215bab79SShivank Garg #endif 107215bab79SShivank Garg #ifdef INET6 108215bab79SShivank Garg #define v6 ipa.ipv6 109215bab79SShivank Garg #endif 110215bab79SShivank Garg #define addr8 ipa.addr8 111215bab79SShivank Garg #define addr16 ipa.addr16 112215bab79SShivank Garg #define addr32 ipa.addr32 113215bab79SShivank Garg }; 114215bab79SShivank Garg 115215bab79SShivank Garg struct ip_rule { 116215bab79SShivank Garg int jid; 117215bab79SShivank Garg bool allow; 118215bab79SShivank Garg bool subnet_apply; /* Apply rule on whole subnet. */ 119215bab79SShivank Garg char if_name[IFNAMSIZ]; 120215bab79SShivank Garg int af; /* Address family. */ 121215bab79SShivank Garg struct ipacl_addr addr; 122215bab79SShivank Garg struct ipacl_addr mask; 123215bab79SShivank Garg TAILQ_ENTRY(ip_rule) r_entries; 124215bab79SShivank Garg }; 125215bab79SShivank Garg 126215bab79SShivank Garg static struct mtx rule_mtx; 127215bab79SShivank Garg static TAILQ_HEAD(rulehead, ip_rule) rule_head; 128215bab79SShivank Garg static char rule_string[MAC_RULE_STRING_LEN]; 129215bab79SShivank Garg 130215bab79SShivank Garg static void 131215bab79SShivank Garg destroy_rules(struct rulehead *head) 132215bab79SShivank Garg { 133215bab79SShivank Garg struct ip_rule *rule; 134215bab79SShivank Garg 135215bab79SShivank Garg while ((rule = TAILQ_FIRST(head)) != NULL) { 136215bab79SShivank Garg TAILQ_REMOVE(head, rule, r_entries); 137215bab79SShivank Garg free(rule, M_IPACL); 138215bab79SShivank Garg } 139215bab79SShivank Garg } 140215bab79SShivank Garg 141215bab79SShivank Garg static void 142215bab79SShivank Garg ipacl_init(struct mac_policy_conf *conf) 143215bab79SShivank Garg { 144215bab79SShivank Garg mtx_init(&rule_mtx, "rule_mtx", NULL, MTX_DEF); 145215bab79SShivank Garg TAILQ_INIT(&rule_head); 146215bab79SShivank Garg } 147215bab79SShivank Garg 148215bab79SShivank Garg static void 149215bab79SShivank Garg ipacl_destroy(struct mac_policy_conf *conf) 150215bab79SShivank Garg { 151215bab79SShivank Garg mtx_destroy(&rule_mtx); 152215bab79SShivank Garg destroy_rules(&rule_head); 153215bab79SShivank Garg } 154215bab79SShivank Garg 155215bab79SShivank Garg /* 156215bab79SShivank Garg * Note: parsing routines are destructive on the passed string. 157215bab79SShivank Garg */ 158215bab79SShivank Garg static int 159215bab79SShivank Garg parse_rule_element(char *element, struct ip_rule *rule) 160215bab79SShivank Garg { 161215bab79SShivank Garg char *tok, *p; 162215bab79SShivank Garg int prefix; 163215bab79SShivank Garg #ifdef INET6 164215bab79SShivank Garg int i; 165215bab79SShivank Garg #endif 166215bab79SShivank Garg 167215bab79SShivank Garg /* Should we support a jail wildcard? */ 168215bab79SShivank Garg tok = strsep(&element, ","); 169215bab79SShivank Garg if (tok == NULL) 170215bab79SShivank Garg return (EINVAL); 171215bab79SShivank Garg rule->jid = strtol(tok, &p, 10); 172215bab79SShivank Garg if (*p != '\0') 173215bab79SShivank Garg return (EINVAL); 174215bab79SShivank Garg tok = strsep(&element, ","); 175215bab79SShivank Garg if (tok == NULL) 176215bab79SShivank Garg return (EINVAL); 177215bab79SShivank Garg rule->allow = strtol(tok, &p, 10); 178215bab79SShivank Garg if (*p != '\0') 179215bab79SShivank Garg return (EINVAL); 180215bab79SShivank Garg tok = strsep(&element, ","); 181215bab79SShivank Garg if (strlen(tok) + 1 > IFNAMSIZ) 182215bab79SShivank Garg return (EINVAL); 183215bab79SShivank Garg /* Empty interface name is wildcard to all interfaces. */ 184215bab79SShivank Garg strlcpy(rule->if_name, tok, strlen(tok) + 1); 185215bab79SShivank Garg tok = strsep(&element, ","); 186215bab79SShivank Garg if (tok == NULL) 187215bab79SShivank Garg return (EINVAL); 188215bab79SShivank Garg rule->af = (strcmp(tok, "AF_INET") == 0) ? AF_INET : 189215bab79SShivank Garg (strcmp(tok, "AF_INET6") == 0) ? AF_INET6 : -1; 190215bab79SShivank Garg if (rule->af == -1) 191215bab79SShivank Garg return (EINVAL); 192215bab79SShivank Garg tok = strsep(&element, "/"); 193215bab79SShivank Garg if (tok == NULL) 194215bab79SShivank Garg return (EINVAL); 195215bab79SShivank Garg if (inet_pton(rule->af, tok, rule->addr.addr32) != 1) 196215bab79SShivank Garg return (EINVAL); 197215bab79SShivank Garg tok = element; 198215bab79SShivank Garg if (tok == NULL) 199215bab79SShivank Garg return (EINVAL); 200215bab79SShivank Garg prefix = strtol(tok, &p, 10); 201215bab79SShivank Garg if (*p != '\0') 202215bab79SShivank Garg return (EINVAL); 203215bab79SShivank Garg /* Value -1 for prefix make policy applicable to individual IP only. */ 204215bab79SShivank Garg if (prefix == -1) 205215bab79SShivank Garg rule->subnet_apply = false; 206215bab79SShivank Garg else { 207215bab79SShivank Garg rule->subnet_apply = true; 208215bab79SShivank Garg switch (rule->af) { 209215bab79SShivank Garg #ifdef INET 210215bab79SShivank Garg case AF_INET: 211215bab79SShivank Garg if (prefix < 0 || prefix > 32) 212215bab79SShivank Garg return (EINVAL); 213215bab79SShivank Garg 214215bab79SShivank Garg if (prefix == 0) 215215bab79SShivank Garg rule->mask.addr32[0] = htonl(0); 216215bab79SShivank Garg else 217215bab79SShivank Garg rule->mask.addr32[0] = 218215bab79SShivank Garg htonl(~((1 << (32 - prefix)) - 1)); 219215bab79SShivank Garg rule->addr.addr32[0] &= rule->mask.addr32[0]; 220215bab79SShivank Garg break; 221215bab79SShivank Garg #endif 222215bab79SShivank Garg #ifdef INET6 223215bab79SShivank Garg case AF_INET6: 224215bab79SShivank Garg if (prefix < 0 || prefix > 128) 225215bab79SShivank Garg return (EINVAL); 226215bab79SShivank Garg 227215bab79SShivank Garg for (i = 0; prefix > 0; prefix -= 8, i++) 228215bab79SShivank Garg rule->mask.addr8[i] = prefix >= 8 ? 0xFF : 229215bab79SShivank Garg (u_int8_t)((0xFFU << (8 - prefix)) & 0xFFU); 230215bab79SShivank Garg for (i = 0; i < 16; i++) 231215bab79SShivank Garg rule->addr.addr8[i] &= rule->mask.addr8[i]; 232215bab79SShivank Garg break; 233215bab79SShivank Garg #endif 234215bab79SShivank Garg } 235215bab79SShivank Garg } 236215bab79SShivank Garg return (0); 237215bab79SShivank Garg } 238215bab79SShivank Garg 239215bab79SShivank Garg /* 240215bab79SShivank Garg * Format of Rule- jid,allow,interface_name,addr_family,ip_addr/subnet_mask 241215bab79SShivank Garg * Example: sysctl security.mac.ipacl.rules=1,1,epair0b,AF_INET,192.0.2.2/24 242215bab79SShivank Garg */ 243215bab79SShivank Garg static int 244215bab79SShivank Garg parse_rules(char *string, struct rulehead *head) 245215bab79SShivank Garg { 246215bab79SShivank Garg struct ip_rule *new; 247215bab79SShivank Garg char *element; 248215bab79SShivank Garg int error; 249215bab79SShivank Garg 250215bab79SShivank Garg error = 0; 251215bab79SShivank Garg while ((element = strsep(&string, "@")) != NULL) { 252215bab79SShivank Garg if (strlen(element) == 0) 253215bab79SShivank Garg continue; 254215bab79SShivank Garg 255215bab79SShivank Garg new = malloc(sizeof(*new), M_IPACL, M_ZERO | M_WAITOK); 256215bab79SShivank Garg error = parse_rule_element(element, new); 257215bab79SShivank Garg if (error != 0) { 258215bab79SShivank Garg free(new, M_IPACL); 259215bab79SShivank Garg goto out; 260215bab79SShivank Garg } 261215bab79SShivank Garg TAILQ_INSERT_TAIL(head, new, r_entries); 262215bab79SShivank Garg } 263215bab79SShivank Garg out: 264215bab79SShivank Garg if (error != 0) 265215bab79SShivank Garg destroy_rules(head); 266215bab79SShivank Garg return (error); 267215bab79SShivank Garg } 268215bab79SShivank Garg 269215bab79SShivank Garg static int 270215bab79SShivank Garg sysctl_rules(SYSCTL_HANDLER_ARGS) 271215bab79SShivank Garg { 272215bab79SShivank Garg char *string, *copy_string, *new_string; 273215bab79SShivank Garg struct rulehead head, save_head; 274215bab79SShivank Garg int error; 275215bab79SShivank Garg 276215bab79SShivank Garg new_string = NULL; 277215bab79SShivank Garg if (req->newptr != NULL) { 278215bab79SShivank Garg new_string = malloc(MAC_RULE_STRING_LEN, M_IPACL, 279215bab79SShivank Garg M_WAITOK | M_ZERO); 280215bab79SShivank Garg mtx_lock(&rule_mtx); 281215bab79SShivank Garg strcpy(new_string, rule_string); 282215bab79SShivank Garg mtx_unlock(&rule_mtx); 283215bab79SShivank Garg string = new_string; 284215bab79SShivank Garg } else 285215bab79SShivank Garg string = rule_string; 286215bab79SShivank Garg 287215bab79SShivank Garg error = sysctl_handle_string(oidp, string, MAC_RULE_STRING_LEN, req); 288215bab79SShivank Garg if (error) 289215bab79SShivank Garg goto out; 290215bab79SShivank Garg 291215bab79SShivank Garg if (req->newptr != NULL) { 292215bab79SShivank Garg copy_string = strdup(string, M_IPACL); 293215bab79SShivank Garg TAILQ_INIT(&head); 294215bab79SShivank Garg error = parse_rules(copy_string, &head); 295215bab79SShivank Garg free(copy_string, M_IPACL); 296215bab79SShivank Garg if (error) 297215bab79SShivank Garg goto out; 298215bab79SShivank Garg 299215bab79SShivank Garg TAILQ_INIT(&save_head); 300215bab79SShivank Garg mtx_lock(&rule_mtx); 301215bab79SShivank Garg TAILQ_CONCAT(&save_head, &rule_head, r_entries); 302215bab79SShivank Garg TAILQ_CONCAT(&rule_head, &head, r_entries); 303215bab79SShivank Garg strcpy(rule_string, string); 304215bab79SShivank Garg mtx_unlock(&rule_mtx); 305215bab79SShivank Garg destroy_rules(&save_head); 306215bab79SShivank Garg } 307215bab79SShivank Garg out: 308215bab79SShivank Garg if (new_string != NULL) 309215bab79SShivank Garg free(new_string, M_IPACL); 310215bab79SShivank Garg return (error); 311215bab79SShivank Garg } 312215bab79SShivank Garg SYSCTL_PROC(_security_mac_ipacl, OID_AUTO, rules, 313215bab79SShivank Garg CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 314215bab79SShivank Garg 0, sysctl_rules, "A", "IP ACL Rules"); 315215bab79SShivank Garg 316215bab79SShivank Garg static int 317215bab79SShivank Garg rules_check(struct ucred *cred, 318*b820820eSJustin Hibbits struct ipacl_addr *ip_addr, if_t ifp) 319215bab79SShivank Garg { 320215bab79SShivank Garg struct ip_rule *rule; 321215bab79SShivank Garg int error; 322215bab79SShivank Garg #ifdef INET6 323215bab79SShivank Garg int i; 324215bab79SShivank Garg bool same_subnet; 325215bab79SShivank Garg #endif 326215bab79SShivank Garg 327215bab79SShivank Garg error = EPERM; 328215bab79SShivank Garg 329215bab79SShivank Garg mtx_lock(&rule_mtx); 330215bab79SShivank Garg 331215bab79SShivank Garg /* 332215bab79SShivank Garg * In the case where multiple rules are applicable to an IP address or 333215bab79SShivank Garg * a set of IP addresses, the rule that is defined later in the list 334215bab79SShivank Garg * determines the outcome, disregarding any previous rule for that IP 335215bab79SShivank Garg * address. 336215bab79SShivank Garg * Walk the policy rules list in reverse order until rule applicable 337215bab79SShivank Garg * to the requested IP address is found. 338215bab79SShivank Garg */ 339215bab79SShivank Garg TAILQ_FOREACH_REVERSE(rule, &rule_head, rulehead, r_entries) { 340215bab79SShivank Garg /* Skip if current rule applies to different jail. */ 341215bab79SShivank Garg if (cred->cr_prison->pr_id != rule->jid) 342215bab79SShivank Garg continue; 343215bab79SShivank Garg 344215bab79SShivank Garg if (strcmp(rule->if_name, "\0") && 345*b820820eSJustin Hibbits strcmp(rule->if_name, if_name(ifp))) 346215bab79SShivank Garg continue; 347215bab79SShivank Garg 348215bab79SShivank Garg switch (rule->af) { 349215bab79SShivank Garg #ifdef INET 350215bab79SShivank Garg case AF_INET: 351215bab79SShivank Garg if (rule->subnet_apply) { 352215bab79SShivank Garg if (rule->addr.v4.s_addr != 353215bab79SShivank Garg (ip_addr->v4.s_addr & rule->mask.v4.s_addr)) 354215bab79SShivank Garg continue; 355215bab79SShivank Garg } else 356215bab79SShivank Garg if (ip_addr->v4.s_addr != rule->addr.v4.s_addr) 357215bab79SShivank Garg continue; 358215bab79SShivank Garg break; 359215bab79SShivank Garg #endif 360215bab79SShivank Garg #ifdef INET6 361215bab79SShivank Garg case AF_INET6: 362215bab79SShivank Garg if (rule->subnet_apply) { 363215bab79SShivank Garg same_subnet = true; 364215bab79SShivank Garg for (i = 0; i < 16; i++) 365215bab79SShivank Garg if (rule->addr.v6.s6_addr[i] != 366215bab79SShivank Garg (ip_addr->v6.s6_addr[i] & 367215bab79SShivank Garg rule->mask.v6.s6_addr[i])) { 368215bab79SShivank Garg same_subnet = false; 369215bab79SShivank Garg break; 370215bab79SShivank Garg } 371215bab79SShivank Garg if (!same_subnet) 372215bab79SShivank Garg continue; 373215bab79SShivank Garg } else 374215bab79SShivank Garg if (bcmp(&rule->addr, ip_addr, 375215bab79SShivank Garg sizeof(*ip_addr))) 376215bab79SShivank Garg continue; 377215bab79SShivank Garg break; 378215bab79SShivank Garg #endif 379215bab79SShivank Garg } 380215bab79SShivank Garg 381215bab79SShivank Garg if (rule->allow) 382215bab79SShivank Garg error = 0; 383215bab79SShivank Garg break; 384215bab79SShivank Garg } 385215bab79SShivank Garg 386215bab79SShivank Garg mtx_unlock(&rule_mtx); 387215bab79SShivank Garg 388215bab79SShivank Garg return (error); 389215bab79SShivank Garg } 390215bab79SShivank Garg 391215bab79SShivank Garg /* 392215bab79SShivank Garg * Feature request: Can we make this sysctl policy apply to jails by default, 393215bab79SShivank Garg * but also allow it to be changed to apply to the base system? 394215bab79SShivank Garg */ 395215bab79SShivank Garg #ifdef INET 396215bab79SShivank Garg static int 397215bab79SShivank Garg ipacl_ip4_check_jail(struct ucred *cred, 398*b820820eSJustin Hibbits const struct in_addr *ia, if_t ifp) 399215bab79SShivank Garg { 400215bab79SShivank Garg struct ipacl_addr ip4_addr; 401215bab79SShivank Garg 402215bab79SShivank Garg ip4_addr.v4 = *ia; 403215bab79SShivank Garg 404215bab79SShivank Garg if (!jailed(cred)) 405215bab79SShivank Garg return (0); 406215bab79SShivank Garg 407215bab79SShivank Garg /* Checks with the policy only when it is enforced for ipv4. */ 408215bab79SShivank Garg if (ipacl_ipv4) 409215bab79SShivank Garg return rules_check(cred, &ip4_addr, ifp); 410215bab79SShivank Garg 411215bab79SShivank Garg return (0); 412215bab79SShivank Garg } 413215bab79SShivank Garg #endif 414215bab79SShivank Garg 415215bab79SShivank Garg #ifdef INET6 416215bab79SShivank Garg static int 417215bab79SShivank Garg ipacl_ip6_check_jail(struct ucred *cred, 418*b820820eSJustin Hibbits const struct in6_addr *ia6, if_t ifp) 419215bab79SShivank Garg { 420215bab79SShivank Garg struct ipacl_addr ip6_addr; 421215bab79SShivank Garg 422215bab79SShivank Garg ip6_addr.v6 = *ia6; /* Make copy to not alter the original. */ 423215bab79SShivank Garg in6_clearscope(&ip6_addr.v6); /* Clear the scope id. */ 424215bab79SShivank Garg 425215bab79SShivank Garg if (!jailed(cred)) 426215bab79SShivank Garg return (0); 427215bab79SShivank Garg 428215bab79SShivank Garg /* Checks with the policy when it is enforced for ipv6. */ 429215bab79SShivank Garg if (ipacl_ipv6) 430215bab79SShivank Garg return rules_check(cred, &ip6_addr, ifp); 431215bab79SShivank Garg 432215bab79SShivank Garg return (0); 433215bab79SShivank Garg } 434215bab79SShivank Garg #endif 435215bab79SShivank Garg 436215bab79SShivank Garg static struct mac_policy_ops ipacl_ops = 437215bab79SShivank Garg { 438215bab79SShivank Garg .mpo_init = ipacl_init, 439215bab79SShivank Garg .mpo_destroy = ipacl_destroy, 440215bab79SShivank Garg #ifdef INET 441215bab79SShivank Garg .mpo_ip4_check_jail = ipacl_ip4_check_jail, 442215bab79SShivank Garg #endif 443215bab79SShivank Garg #ifdef INET6 444215bab79SShivank Garg .mpo_ip6_check_jail = ipacl_ip6_check_jail, 445215bab79SShivank Garg #endif 446215bab79SShivank Garg }; 447215bab79SShivank Garg 448215bab79SShivank Garg MAC_POLICY_SET(&ipacl_ops, mac_ipacl, "TrustedBSD MAC/ipacl", 449215bab79SShivank Garg MPC_LOADTIME_FLAG_UNLOADOK, NULL); 450