X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/ff6e181ae92fc6f1e89841290f461d1f2f9badd9..5c9f46613a83ebfc29a5b1f099448259e96a98f0:/bsd/netinet6/ip6_fw.c diff --git a/bsd/netinet6/ip6_fw.c b/bsd/netinet6/ip6_fw.c index 8b715849a..99d3e8c02 100644 --- a/bsd/netinet6/ip6_fw.c +++ b/bsd/netinet6/ip6_fw.c @@ -1,14 +1,19 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2012 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -18,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* $FreeBSD: src/sys/netinet6/ip6_fw.c,v 1.2.2.9 2002/04/28 05:40:27 suz Exp $ */ @@ -81,8 +86,6 @@ #endif #include -#include - #include #include #include @@ -94,6 +97,8 @@ #include #include #include +#include + #include #include #include @@ -121,7 +126,7 @@ MALLOC_DEFINE(M_IP6FW, "Ip6Fw/Ip6Acct", "Ip6Fw/Ip6Acct chain's"); -static int fw6_debug = 1; +static int fw6_debug = 0; #ifdef IPV6FIREWALL_VERBOSE static int fw6_verbose = 1; #else @@ -135,14 +140,35 @@ static int fw6_verbose_limit = 0; LIST_HEAD (ip6_fw_head, ip6_fw_chain) ip6_fw_chain; +static void ip6fw_kev_post_msg(u_int32_t ); + #ifdef SYSCTL_NODE +static int ip6fw_sysctl SYSCTL_HANDLER_ARGS; + SYSCTL_DECL(_net_inet6_ip6); -SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall"); -SYSCTL_INT(_net_inet6_ip6_fw, OID_AUTO, enable, CTLFLAG_RW, - &ip6_fw_enable, 0, "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_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 | CTLFLAG_LOCKED, + &ip6_fw_enable, 0, ip6fw_sysctl, "I", "Enable ip6fw"); +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 +{ +#pragma unused(arg1, arg2) + int error; + + error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); + if (error || !req->newptr) + return (error); + + ip6fw_kev_post_msg(KEV_IP6FW_ENABLE); + + return error; +} + #endif #define dprintf(a) do { \ @@ -168,9 +194,12 @@ static void ip6fw_report __P((struct ip6_fw *f, struct ip6_hdr *ip6, static int ip6_fw_chk __P((struct ip6_hdr **pip6, struct ifnet *oif, u_int16_t *cookie, struct mbuf **m)); static int ip6_fw_ctl __P((struct sockopt *)); +static void cp_to_user_64( struct ip6_fw_64 *userrule_64, struct ip6_fw *rule); +static void cp_from_user_64( struct ip6_fw_64 *userrule_64, struct ip6_fw *rule); +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 @@ -358,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); } @@ -387,7 +420,7 @@ ip6fw_report(struct ip6_fw *f, struct ip6_hdr *ip6, struct udphdr *const udp = (struct udphdr *) ((caddr_t) ip6+ off); struct icmp6_hdr *const icmp6 = (struct icmp6_hdr *) ((caddr_t) ip6+ off); int count; - char *action; + const char *action; char action2[32], proto[102], name[18]; int len; @@ -526,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_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; @@ -536,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); @@ -837,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); + *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; } @@ -872,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); @@ -889,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); } @@ -930,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); } @@ -938,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; @@ -955,7 +980,6 @@ del_entry6(struct ip6_fw_head *chainptr, u_short number) } } - splx(s); return (EINVAL); } @@ -963,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) @@ -1109,147 +1130,183 @@ check_ip6fw_struct(struct ip6_fw *frwl) return frwl; } -/*#####*/ -#if 0 -static int -ip6_fw_ctl(int stage, struct mbuf **mm) +static void +ip6fw_kev_post_msg(u_int32_t event_code) { - int error; - struct mbuf *m; - - if (stage == IPV6_FW_GET) { - struct ip6_fw_chain *fcp = ip6_fw_chain.lh_first; - *mm = m = m_get(M_WAIT, MT_DATA); /* XXX */ - if (!m) - return(ENOBUFS); - if (sizeof *(fcp->rule) > MLEN) { - MCLGET(m, M_WAIT); - if ((m->m_flags & M_EXT) == 0) { - m_free(m); - return(ENOBUFS); - } - } - for (; fcp; fcp = fcp->chain.le_next) { - bcopy(fcp->rule, m->m_data, sizeof *(fcp->rule)); - m->m_len = sizeof *(fcp->rule); - m->m_next = m_get(M_WAIT, MT_DATA); /* XXX */ - if (!m->m_next) { - m_freem(*mm); - return(ENOBUFS); - } - m = m->m_next; - if (sizeof *(fcp->rule) > MLEN) { - MCLGET(m, M_WAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(*mm); - return(ENOBUFS); - } - } - m->m_len = 0; - } - return (0); - } - m = *mm; - /* only allow get calls if secure mode > 2 */ - if (securelevel > 2) { - if (m) { - (void)m_freem(m); - *mm = 0; - } - return(EPERM); - } - if (stage == IPV6_FW_FLUSH) { - while (ip6_fw_chain.lh_first != NULL && - ip6_fw_chain.lh_first->rule->fw_number != (u_short)-1) { - struct ip6_fw_chain *fcp = ip6_fw_chain.lh_first; - int s = splnet(); - LIST_REMOVE(ip6_fw_chain.lh_first, chain); - splx(s); - FREE(fcp->rule, M_IP6FW); - FREE(fcp, M_IP6FW); - } - if (m) { - (void)m_freem(m); - *mm = 0; - } - return (0); - } - if (stage == IPV6_FW_ZERO) { - error = zero_entry6(m); - if (m) { - (void)m_freem(m); - *mm = 0; - } - return (error); - } - if (m == NULL) { - printf("%s NULL mbuf ptr\n", err_prefix); - return (EINVAL); - } + struct kev_msg ev_msg; - if (stage == IPV6_FW_ADD) { - struct ip6_fw *frwl = check_ip6fw_mbuf(m); + bzero(&ev_msg, sizeof(struct kev_msg)); + + ev_msg.vendor_code = KEV_VENDOR_APPLE; + ev_msg.kev_class = KEV_FIREWALL_CLASS; + ev_msg.kev_subclass = KEV_IP6FW_SUBCLASS; + ev_msg.event_code = event_code; - if (!frwl) - error = EINVAL; - else - error = add_entry6(&ip6_fw_chain, frwl); - if (m) { - (void)m_freem(m); - *mm = 0; - } - return error; - } - if (stage == IPV6_FW_DEL) { - if (m->m_len != sizeof(struct ip6_fw)) { - dprintf(("%s len=%ld, want %lu\n", err_prefix, m->m_len, - sizeof(struct ip6_fw))); - error = EINVAL; - } else if (mtod(m, struct ip6_fw *)->fw_number == (u_short)-1) { - dprintf(("%s can't delete rule 65535\n", err_prefix)); - error = EINVAL; - } else - error = del_entry6(&ip6_fw_chain, - mtod(m, struct ip6_fw *)->fw_number); - if (m) { - (void)m_freem(m); - *mm = 0; - } - return error; - } + kev_post_msg(&ev_msg); - dprintf(("%s unknown request %d\n", err_prefix, stage)); - if (m) { - (void)m_freem(m); - *mm = 0; - } - return (EINVAL); } -#endif + + +static void +cp_to_user_64( struct ip6_fw_64 *userrule_64, struct ip6_fw *rule) +{ + userrule_64->version = rule->version; + userrule_64->context = CAST_USER_ADDR_T(rule->context); + userrule_64->fw_pcnt = rule->fw_pcnt; + userrule_64->fw_bcnt = rule->fw_bcnt; + userrule_64->fw_src = rule->fw_src; + userrule_64->fw_dst = rule->fw_dst; + userrule_64->fw_smsk = rule->fw_smsk; + userrule_64->fw_dmsk = rule->fw_dmsk; + userrule_64->fw_number = rule->fw_number; + userrule_64->fw_flg = rule->fw_flg; + userrule_64->fw_ipflg = rule->fw_ipflg; + bcopy( rule->fw_pts, userrule_64->fw_pts, IPV6_FW_MAX_PORTS); + userrule_64->fw_ip6opt= rule->fw_ip6opt; + userrule_64->fw_ip6nopt = rule->fw_ip6nopt; + userrule_64->fw_tcpf = rule->fw_tcpf; + userrule_64->fw_tcpnf = rule->fw_tcpnf; + bcopy( rule->fw_icmp6types, userrule_64->fw_icmp6types, sizeof(userrule_64->fw_icmp6types)); + userrule_64->fw_in_if = rule->fw_in_if; + userrule_64->fw_out_if = rule->fw_out_if; + userrule_64->timestamp = rule->timestamp; + userrule_64->fw_un.fu_divert_port = rule->fw_un.fu_divert_port; + userrule_64->fw_prot = rule->fw_prot; + userrule_64->fw_nports = rule->fw_nports; +} + + +static void +cp_from_user_64( struct ip6_fw_64 *userrule_64, struct ip6_fw *rule) +{ + rule->version = userrule_64->version; + rule->context = CAST_DOWN(void *, userrule_64->context); + rule->fw_pcnt = userrule_64->fw_pcnt; + rule->fw_bcnt = userrule_64->fw_bcnt; + rule->fw_src = userrule_64->fw_src; + rule->fw_dst = userrule_64->fw_dst; + rule->fw_smsk = userrule_64->fw_smsk; + rule->fw_dmsk = userrule_64->fw_dmsk; + rule->fw_number = userrule_64->fw_number; + rule->fw_flg = userrule_64->fw_flg; + rule->fw_ipflg = userrule_64->fw_ipflg; + bcopy( userrule_64->fw_pts, rule->fw_pts, IPV6_FW_MAX_PORTS); + rule->fw_ip6opt = userrule_64->fw_ip6opt; + rule->fw_ip6nopt = userrule_64->fw_ip6nopt; + rule->fw_tcpf = userrule_64->fw_tcpf; + rule->fw_tcpnf = userrule_64->fw_tcpnf; + bcopy( userrule_64->fw_icmp6types, rule->fw_icmp6types, sizeof(userrule_64->fw_icmp6types)); + rule->fw_in_if = userrule_64->fw_in_if; + rule->fw_out_if = userrule_64->fw_out_if; + rule->timestamp = CAST_DOWN( long, userrule_64->timestamp); + rule->fw_un.fu_divert_port = userrule_64->fw_un.fu_divert_port; + rule->fw_prot = userrule_64->fw_prot; + rule->fw_nports = userrule_64->fw_nports; +} + + +static void +cp_to_user_32( struct ip6_fw_32 *userrule_32, struct ip6_fw *rule) +{ + userrule_32->version = rule->version; + userrule_32->context = CAST_DOWN_EXPLICIT( user32_addr_t, rule->context); + userrule_32->fw_pcnt = rule->fw_pcnt; + userrule_32->fw_bcnt = rule->fw_bcnt; + userrule_32->fw_src = rule->fw_src; + userrule_32->fw_dst = rule->fw_dst; + userrule_32->fw_smsk = rule->fw_smsk; + userrule_32->fw_dmsk = rule->fw_dmsk; + userrule_32->fw_number = rule->fw_number; + userrule_32->fw_flg = rule->fw_flg; + userrule_32->fw_ipflg = rule->fw_ipflg; + bcopy( rule->fw_pts, userrule_32->fw_pts, IPV6_FW_MAX_PORTS); + userrule_32->fw_ip6opt = rule->fw_ip6opt ; + userrule_32->fw_ip6nopt = rule->fw_ip6nopt; + userrule_32->fw_tcpf = rule->fw_tcpf; + userrule_32->fw_tcpnf = rule->fw_tcpnf; + bcopy( rule->fw_icmp6types, userrule_32->fw_icmp6types, sizeof(rule->fw_icmp6types)); + userrule_32->fw_in_if = rule->fw_in_if; + userrule_32->fw_out_if = rule->fw_out_if; + userrule_32->timestamp = rule->timestamp; + userrule_32->fw_un.fu_divert_port = rule->fw_un.fu_divert_port; + userrule_32->fw_prot = rule->fw_prot; + userrule_32->fw_nports = rule->fw_nports; +} + + +static void +cp_from_user_32( struct ip6_fw_32 *userrule_32, struct ip6_fw *rule) +{ + rule->version = userrule_32->version; + rule->context = CAST_DOWN(void *, userrule_32->context); + rule->fw_pcnt = userrule_32->fw_pcnt; + rule->fw_bcnt = userrule_32->fw_bcnt; + rule->fw_src = userrule_32->fw_src; + rule->fw_dst = userrule_32->fw_dst; + rule->fw_smsk = userrule_32->fw_smsk; + rule->fw_dmsk = userrule_32->fw_dmsk; + rule->fw_number = userrule_32->fw_number; + rule->fw_flg = userrule_32->fw_flg; + rule->fw_ipflg = userrule_32->fw_ipflg; + bcopy( userrule_32->fw_pts, rule->fw_pts, IPV6_FW_MAX_PORTS); + rule->fw_ip6opt = userrule_32->fw_ip6opt; + rule->fw_ip6nopt = userrule_32->fw_ip6nopt; + rule->fw_tcpf = userrule_32->fw_tcpf; + rule->fw_tcpnf = userrule_32->fw_tcpnf; + bcopy( userrule_32->fw_icmp6types, rule->fw_icmp6types, sizeof(userrule_32->fw_icmp6types)); + rule->fw_in_if = userrule_32->fw_in_if; + rule->fw_out_if = userrule_32->fw_out_if; + rule->timestamp = CAST_DOWN(long, userrule_32->timestamp); + rule->fw_un.fu_divert_port = userrule_32->fw_un.fu_divert_port; + rule->fw_prot = userrule_32->fw_prot; + rule->fw_nports = userrule_32->fw_nports; +} static int ip6_fw_ctl(struct sockopt *sopt) { int error = 0; - int spl; int valsize; struct ip6_fw rule; + int is64user=0; + size_t userrulesize; if (securelevel >= 3 && (sopt->sopt_dir != SOPT_GET || sopt->sopt_name != IPV6_FW_GET)) return (EPERM); + if ( proc_is64bit(sopt->sopt_p) ){ + is64user = 1; + userrulesize = sizeof( struct ip6_fw_64 ); + } else + userrulesize = sizeof( struct ip6_fw_32 ); + /* We ALWAYS expect the client to pass in a rule structure so that we can * check the version of the API that they are using. In the case of a * IPV6_FW_GET operation, the first rule of the output buffer passed to us * must have the version set. */ - if (!sopt->sopt_val || sopt->sopt_valsize < sizeof rule) return EINVAL; + if (!sopt->sopt_val || sopt->sopt_valsize < userrulesize) return EINVAL; /* save sopt->sopt_valsize */ valsize = sopt->sopt_valsize; - if (error = sooptcopyin(sopt, &rule, sizeof(rule), sizeof(rule))) - return error; - + + if (is64user){ + struct ip6_fw_64 userrule_64; + + if ((error = sooptcopyin(sopt, &userrule_64, userrulesize, userrulesize))) + return error; + + cp_from_user_64( &userrule_64, &rule ); + } + else { + struct ip6_fw_32 userrule_32; + + if ((error = sooptcopyin(sopt, &userrule_32, userrulesize, userrulesize))) + return error; + + cp_from_user_32( &userrule_32, &rule ); + } + if (rule.version != IPV6_FW_CURRENT_API_VERSION) return EINVAL; rule.version = 0xFFFFFFFF; /* version is meaningless once rules "make it in the door". */ @@ -1260,25 +1317,39 @@ ip6_fw_ctl(struct sockopt *sopt) struct ip6_fw_chain *fcp; struct ip6_fw *buf; size_t size = 0; + size_t rulesize = 0; - spl = splnet(); + if ( is64user ) + rulesize = sizeof(struct ip6_fw_64 ); + else + rulesize = sizeof(struct ip6_fw_32 ); + LIST_FOREACH(fcp, &ip6_fw_chain, chain) - size += sizeof *buf; + size += rulesize; buf = _MALLOC(size, M_TEMP, M_WAITOK); if (!buf) error = ENOBUFS; else { - struct ip6_fw *bp = buf; + //struct ip6_fw *bp = buf; + caddr_t bp = (caddr_t)buf; + LIST_FOREACH(fcp, &ip6_fw_chain, chain) { - bcopy(fcp->rule, bp, sizeof *bp); - bp->version = IPV6_FW_CURRENT_API_VERSION; - bp++; + //bcopy(fcp->rule, bp, sizeof *bp); + if ( is64user ){ + cp_to_user_64( (struct ip6_fw_64*)bp, fcp->rule); + } + else { + cp_to_user_32( (struct ip6_fw_32*)bp, fcp->rule); + } + + ( (struct ip6_fw*)bp)->version = IPV6_FW_CURRENT_API_VERSION; + //bp++; + bp += rulesize; } } - splx(spl); if (buf) { sopt->sopt_valsize = valsize; @@ -1290,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) { @@ -1299,7 +1369,7 @@ 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; case IPV6_FW_ZERO: @@ -1307,10 +1377,23 @@ ip6_fw_ctl(struct sockopt *sopt) break; case IPV6_FW_ADD: - if (check_ip6fw_struct(&rule)) + if (check_ip6fw_struct(&rule)) { error = add_entry6(&ip6_fw_chain, &rule); - else + + 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: @@ -1319,8 +1402,11 @@ ip6_fw_ctl(struct sockopt *sopt) dprintf(("%s can't delete rule 65535\n", err_prefix)); error = EINVAL; } - else + else { error = del_entry6(&ip6_fw_chain, rule.fw_number); + + ip6fw_kev_post_msg(KEV_IP6FW_DEL); + } break; default: @@ -1351,7 +1437,7 @@ ip6_fw_init(void) default_rule.fw_flg |= IPV6_FW_F_IN | IPV6_FW_F_OUT; if (check_ip6fw_struct(&default_rule) == NULL || add_entry6(&ip6_fw_chain, &default_rule)) - panic(__FUNCTION__); + panic("%s", __FUNCTION__); printf("IPv6 packet filtering initialized, "); #ifdef IPV6FIREWALL_DEFAULT_TO_ACCEPT