X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b0d623f7f2ae71ed96e60569f61f9a9a27016e80..5c9f46613a83ebfc29a5b1f099448259e96a98f0:/bsd/netinet6/ip6_fw.c diff --git a/bsd/netinet6/ip6_fw.c b/bsd/netinet6/ip6_fw.c index f1b9f0508..99d3e8c02 100644 --- a/bsd/netinet6/ip6_fw.c +++ b/bsd/netinet6/ip6_fw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008 Apple Inc. All rights reserved. + * Copyright (c) 2003-2012 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -86,8 +86,6 @@ #endif #include -#include - #include #include #include @@ -150,11 +148,11 @@ static int ip6fw_sysctl SYSCTL_HANDLER_ARGS; SYSCTL_DECL(_net_inet6_ip6); SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Firewall"); SYSCTL_PROC(_net_inet6_ip6_fw, OID_AUTO, enable, - CTLTYPE_INT | CTLFLAG_RW, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_fw_enable, 0, ip6fw_sysctl, "I", "Enable ip6fw"); -SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, debug, CTLFLAG_RW, &fw6_debug, 0, ""); -SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw6_verbose, 0, ""); -SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw6_verbose_limit, 0, ""); +SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_LOCKED, &fw6_debug, 0, ""); +SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, verbose, CTLFLAG_RW | CTLFLAG_LOCKED, &fw6_verbose, 0, ""); +SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, verbose_limit, CTLFLAG_RW | CTLFLAG_LOCKED, &fw6_verbose_limit, 0, ""); static int ip6fw_sysctl SYSCTL_HANDLER_ARGS @@ -202,7 +200,6 @@ static void cp_to_user_32( struct ip6_fw_32 *userrule_32, struct ip6_fw *rule); static void cp_from_user_32( struct ip6_fw_32 *userrule_32, struct ip6_fw *rule); static char err_prefix[] = "ip6_fw_ctl:"; -extern lck_mtx_t *ip6_mutex; /* * Returns 1 if the port is matched by the vector, 0 otherwise @@ -390,17 +387,21 @@ iface_match(struct ifnet *ifp, union ip6_fw_if *ifu, int byname) struct ifaddr *ia; ifnet_lock_shared(ifp); - for (ia = ifp->if_addrlist.tqh_first; ia; ia = ia->ifa_list.tqe_next) + for (ia = ifp->if_addrlist.tqh_first; ia; + ia = ia->ifa_list.tqe_next) { - - if (ia->ifa_addr == NULL) - continue; - if (ia->ifa_addr->sa_family != AF_INET6) + IFA_LOCK_SPIN(ia); + if (ia->ifa_addr->sa_family != AF_INET6) { + IFA_UNLOCK(ia); continue; + } if (!IN6_ARE_ADDR_EQUAL(&ifu->fu_via_ip6, &(((struct sockaddr_in6 *) - (ia->ifa_addr))->sin6_addr))) + (ia->ifa_addr))->sin6_addr))) { + IFA_UNLOCK(ia); continue; + } + IFA_UNLOCK(ia); ifnet_lock_done(ifp); return(1); } @@ -558,7 +559,7 @@ ip6_fw_chk(struct ip6_hdr **pip6, struct ip6_fw_chain *chain; struct ip6_fw *rule = NULL; struct ip6_hdr *ip6 = *pip6; - struct ifnet *const rif = ((*m)->m_flags & M_LOOP) ? ifunit("lo0") : (*m)->m_pkthdr.rcvif; + struct ifnet *const rif = ((*m)->m_flags & M_LOOP) ? lo_ifp : (*m)->m_pkthdr.rcvif; u_short offset = 0; int off = sizeof(struct ip6_hdr), nxt = ip6->ip6_nxt; u_short src_port, dst_port; @@ -568,6 +569,7 @@ ip6_fw_chk(struct ip6_hdr **pip6, u_int16_t ignport = ntohs(*cookie); #endif struct timeval timenow; + struct tcp_respond_args tra; getmicrotime(&timenow); @@ -869,19 +871,19 @@ got_match: flags = TH_RST|TH_ACK; } bcopy(&ti, ip6, sizeof(ti)); + bzero(&tra, sizeof(tra)); + tra.ifscope = IFSCOPE_NONE; + tra.awdl_unrestricted = 1; tcp_respond(NULL, ip6, (struct tcphdr *)(ip6 + 1), - *m, ack, seq, flags, IFSCOPE_NONE); + *m, ack, seq, flags, &tra); *m = NULL; break; } default: /* Send an ICMP unreachable using code */ if (oif) (*m)->m_pkthdr.rcvif = oif; - lck_mtx_assert(ip6_mutex, LCK_MTX_ASSERT_OWNED); - lck_mtx_unlock(ip6_mutex); icmp6_error(*m, ICMP6_DST_UNREACH, rule->fw_reject_code, 0); - lck_mtx_lock(ip6_mutex); *m = NULL; break; } @@ -904,7 +906,6 @@ add_entry6(struct ip6_fw_head *chainptr, struct ip6_fw *frwl) struct ip6_fw *ftmp = 0; struct ip6_fw_chain *fwc = 0, *fcp, *fcpl = 0; u_short nbr = 0; - int s; fwc = _MALLOC(sizeof *fwc, M_IP6FW, M_WAITOK); ftmp = _MALLOC(sizeof *ftmp, M_IP6FW, M_WAITOK); @@ -921,16 +922,12 @@ add_entry6(struct ip6_fw_head *chainptr, struct ip6_fw *frwl) ftmp->fw_bcnt = 0L; fwc->rule = ftmp; - s = splnet(); - if (!chainptr->lh_first) { LIST_INSERT_HEAD(chainptr, fwc, chain); - splx(s); return(0); } else if (ftmp->fw_number == (u_short)-1) { if (fwc) FREE(fwc, M_IP6FW); if (ftmp) FREE(ftmp, M_IP6FW); - splx(s); dprintf(("%s bad rule number\n", err_prefix)); return (EINVAL); } @@ -962,7 +959,7 @@ add_entry6(struct ip6_fw_head *chainptr, struct ip6_fw *frwl) } } - splx(s); + bcopy(ftmp, frwl, sizeof(struct ip6_fw)); return (0); } @@ -970,16 +967,12 @@ static int del_entry6(struct ip6_fw_head *chainptr, u_short number) { struct ip6_fw_chain *fcp; - int s; - - s = splnet(); fcp = chainptr->lh_first; if (number != (u_short)-1) { for (; fcp; fcp = fcp->chain.le_next) { if (fcp->rule->fw_number == number) { LIST_REMOVE(fcp, chain); - splx(s); FREE(fcp->rule, M_IP6FW); FREE(fcp, M_IP6FW); return 0; @@ -987,7 +980,6 @@ del_entry6(struct ip6_fw_head *chainptr, u_short number) } } - splx(s); return (EINVAL); } @@ -995,20 +987,17 @@ static int zero_entry6(struct ip6_fw *frwl) { struct ip6_fw_chain *fcp; - int s; /* * It's possible to insert multiple chain entries with the * same number, so we don't stop after finding the first * match if zeroing a specific entry. */ - s = splnet(); for (fcp = ip6_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next) if (!frwl || frwl->fw_number == 0 || frwl->fw_number == fcp->rule->fw_number) { fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0; fcp->rule->timestamp = 0; } - splx(s); if (fw6_verbose) { if (frwl) @@ -1277,7 +1266,6 @@ static int ip6_fw_ctl(struct sockopt *sopt) { int error = 0; - int spl; int valsize; struct ip6_fw rule; int is64user=0; @@ -1331,8 +1319,6 @@ ip6_fw_ctl(struct sockopt *sopt) size_t size = 0; size_t rulesize = 0; - spl = splnet(); - if ( is64user ) rulesize = sizeof(struct ip6_fw_64 ); else @@ -1364,7 +1350,6 @@ ip6_fw_ctl(struct sockopt *sopt) } } - splx(spl); if (buf) { sopt->sopt_valsize = valsize; @@ -1376,7 +1361,6 @@ ip6_fw_ctl(struct sockopt *sopt) } case IPV6_FW_FLUSH: - spl = splnet(); while (ip6_fw_chain.lh_first && ip6_fw_chain.lh_first->rule->fw_number != (u_short)-1) { @@ -1385,7 +1369,6 @@ ip6_fw_ctl(struct sockopt *sopt) FREE(fcp->rule, M_IP6FW); FREE(fcp, M_IP6FW); } - splx(spl); ip6fw_kev_post_msg(KEV_IP6FW_FLUSH); break; @@ -1400,6 +1383,17 @@ ip6_fw_ctl(struct sockopt *sopt) ip6fw_kev_post_msg(KEV_IP6FW_ADD); } else error = EINVAL; + + if (is64user){ + struct ip6_fw_64 userrule_64; + cp_to_user_64( &userrule_64, &rule); + error = sooptcopyout(sopt, &userrule_64, userrulesize); + } + else { + struct ip6_fw_32 userrule_32; + cp_to_user_32( &userrule_32, &rule); + error = sooptcopyout(sopt, &userrule_32, userrulesize); + } break; case IPV6_FW_DEL: