X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4a2492630c73add3c3aa8a805ba4ff343d4a58ea..6601e61aa18bf4f09af135ff61fc7f4771d23b06:/bsd/net/if_loop.c?ds=sidebyside diff --git a/bsd/net/if_loop.c b/bsd/net/if_loop.c index 3cc9143a3..1ec4f8e50 100644 --- a/bsd/net/if_loop.c +++ b/bsd/net/if_loop.c @@ -3,22 +3,19 @@ * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. * - * 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. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -73,7 +70,6 @@ #include #include -#include #include #include #include @@ -97,6 +93,7 @@ #endif #include +#include #if NETAT extern struct ifqueue atalkintrq; @@ -110,14 +107,14 @@ extern struct ifqueue atalkintrq; #define NLOOP_ATTACHMENTS (NLOOP * 12) struct lo_statics_str { - int bpf_mode; - int (*bpf_callback)(struct ifnet *, struct mbuf *); + int bpf_mode; + bpf_packet_func bpf_callback; }; -static struct if_proto *lo_array[NLOOP_ATTACHMENTS]; -static struct lo_statics_str lo_statics[NLOOP]; -static lo_count = 0; +void loopattach(void *dummy); +static struct lo_statics_str lo_statics[NLOOP]; +int loopattach_done = 0; /* used to sync ip6_init2 loopback configuration */ #ifdef TINY_LOMTU #define LOMTU (1024+512) @@ -126,102 +123,70 @@ static lo_count = 0; #endif struct ifnet loif[NLOOP]; +struct ifnet *lo_ifp = &loif[0]; -void lo_reg_if_mods(); - +struct loopback_header { + u_long protocol; +}; +void lo_reg_if_mods(void); +/* Local forward declerations */ -int lo_demux(ifp, m, frame_header, proto) - struct ifnet *ifp; - struct mbuf *m; - char *frame_header; - struct if_proto **proto; +static errno_t +lo_demux( + __unused ifnet_t ifp, + __unused mbuf_t m, + char *frame_header, + protocol_family_t *protocol_family) { - int i; - struct if_proto **proto_ptr; - - proto_ptr = mtod(m, struct if_proto **); - *proto = *proto_ptr; - m_adj(m, sizeof(u_long)); - return 0; + struct loopback_header *header = (struct loopback_header *)frame_header; + + *protocol_family = header->protocol; + + return 0; } -int lo_framer(ifp, m, dest, dest_linkaddr, frame_type) - struct ifnet *ifp; - struct mbuf **m; - struct sockaddr *dest; - char *dest_linkaddr; - char *frame_type; - +static errno_t +lo_framer( + __unused ifnet_t ifp, + mbuf_t *m, + __unused const struct sockaddr *dest, + __unused const char *dest_linkaddr, + const char *frame_type) { - char *to_ptr; + struct loopback_header *header; - M_PREPEND(*m, (4 * sizeof(u_long)), M_WAITOK); - to_ptr = mtod(*m, char *); - bcopy(dest_linkaddr, to_ptr, (4 * sizeof(u_long))); + M_PREPEND(*m, sizeof(struct loopback_header), M_WAITOK); + header = mtod(*m, struct loopback_header*); + header->protocol = *(const u_long*)frame_type; return 0; } -static -int lo_add_if(struct ifnet *ifp) -{ - ifp->if_demux = lo_demux; - ifp->if_framer = lo_framer; - ifp->if_event = 0; - return 0; -} - -static -int lo_del_if(struct ifnet *ifp) +static errno_t +lo_add_proto( + __unused struct ifnet *ifp, + __unused u_long protocol_family, + __unused struct ddesc_head_str *demux_desc_head) { return 0; } - - -static -int lo_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag) -{ - int i; - - for (i=0; i < lo_count; i++) - if (lo_array[i] == 0) { - lo_array[lo_count] = proto; - return 0; - } - - if ((i == lo_count) && (lo_count == NLOOP_ATTACHMENTS)) - panic("lo_add_proto -- Too many attachments\n"); - - lo_array[lo_count++] = proto; - return 0; -} - - -static -int lo_del_proto(struct if_proto *proto, u_long dl_tag) +static errno_t +lo_del_proto( + __unused ifnet_t ifp, + __unused protocol_family_t protocol) { - int i; - - for (i=0; i < lo_count; i++) - if (lo_array[i] == proto) { - lo_array[i] = 0; - return 0; - } - - return ENOENT; + return 0; } static int -lo_output(ifp, m) - struct ifnet *ifp; - register struct mbuf *m; -{ u_int *prepend_ptr; - u_int af; - u_long saved_header[3]; +lo_output( + struct ifnet *ifp, + struct mbuf *m) +{ if ((m->m_flags & M_PKTHDR) == 0) panic("lo_output: no HDR"); @@ -233,20 +198,26 @@ lo_output(ifp, m) */ if (m->m_pkthdr.rcvif == NULL) m->m_pkthdr.rcvif = ifp; - prepend_ptr = mtod(m, u_int *); - af = *prepend_ptr; - m_adj(m, sizeof(u_int)); + ifp->if_ibytes += m->m_pkthdr.len; + ifp->if_obytes += m->m_pkthdr.len; + + ifp->if_opackets++; + ifp->if_ipackets++; + + m->m_pkthdr.header = mtod(m, char *); + m->m_pkthdr.csum_data = 0xffff; /* loopback checksums are always OK */ + m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_PSEUDO_HDR | + CSUM_IP_CHECKED | CSUM_IP_VALID; + m_adj(m, sizeof(struct loopback_header)); #if NBPFILTER > 0 if (lo_statics[ifp->if_unit].bpf_mode != BPF_TAP_DISABLE) { struct mbuf m0, *n; - bcopy(mtod(m, caddr_t), &saved_header[0], (3 * sizeof(u_long))); - m_adj(m, (3 * sizeof(u_long))); - n = m; if (ifp->if_bpf->bif_dlt == DLT_NULL) { + struct loopback_header *header; /* * We need to prepend the address family as * a four byte field. Cons up a dummy header @@ -254,156 +225,70 @@ lo_output(ifp, m) * will only read from the mbuf (i.e., it won't * try to free it or keep a pointer a to it). */ + header = (struct loopback_header*)m->m_pkthdr.header; m0.m_next = m; m0.m_len = 4; - m0.m_data = (char *)⁡ + m0.m_data = (char *)&header->protocol; n = &m0; } - (*lo_statics[ifp->if_unit].bpf_callback)(ifp, n); - - M_PREPEND(m, (3 * sizeof(u_long)), M_WAITOK); - bcopy(&saved_header[0], mtod(m, caddr_t), (3 * sizeof(u_long))); - + lo_statics[ifp->if_unit].bpf_callback(ifp, n); } #endif - ifp->if_ibytes += m->m_pkthdr.len; - ifp->if_obytes += m->m_pkthdr.len; - - ifp->if_opackets++; - ifp->if_ipackets++; - - m->m_pkthdr.header = mtod(m, char *); - m->m_pkthdr.csum_data = 0xffff; /* loopback checksums are always OK */ - m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_PSEUDO_HDR | - CSUM_IP_CHECKED | CSUM_IP_VALID; return dlil_input(ifp, m, m); } /* - * This is a common pre-output route used by INET, AT, etc. This could + * This is a common pre-output route used by INET and INET6. This could * (should?) be split into separate pre-output routines for each protocol. */ static int -lo_pre_output(ifp, m, dst, route, frame_type, dst_addr, dl_tag) - struct ifnet *ifp; - register struct mbuf **m; - struct sockaddr *dst; - void *route; - char *frame_type; - char *dst_addr; - u_long dl_tag; +lo_pre_output( + __unused struct ifnet *ifp, + u_long protocol_family, + struct mbuf **m, + __unused const struct sockaddr *dst, + caddr_t route, + char *frame_type, + __unused char *dst_addr) { - int s, isr; - register struct ifqueue *ifq = 0; - u_long *prepend_ptr; register struct rtentry *rt = (struct rtentry *) route; - prepend_ptr = (u_long *) dst_addr; if (((*m)->m_flags & M_PKTHDR) == 0) panic("looutput no HDR"); if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { - if (rt->rt_flags & RTF_BLACKHOLE) { - m_freem(*m); - return EJUSTRETURN; - } - else - return ((rt->rt_flags & RTF_HOST) ? EHOSTUNREACH : ENETUNREACH); - } - - switch (dst->sa_family) { -#if INET - case AF_INET: - ifq = &ipintrq; - isr = NETISR_IP; - break; -#endif -#if INET6 - case AF_INET6: - (*m)->m_flags |= M_LOOP; - ifq = &ip6intrq; - isr = NETISR_IPV6; - break; -#endif -#if IPX - case AF_IPX: - ifq = &ipxintrq; - isr = NETISR_IPX; - break; -#endif -#if NS - case AF_NS: - ifq = &nsintrq; - isr = NETISR_NS; - break; -#endif -#if ISO - case AF_ISO: - ifq = &clnlintrq; - isr = NETISR_ISO; - break; -#endif -#if NETAT - case AF_APPLETALK: - ifq = &atalkintrq; - isr = NETISR_APPLETALK; - break; -#endif /* NETAT */ - default: - return (EAFNOSUPPORT); + if (rt->rt_flags & RTF_BLACKHOLE) { + m_freem(*m); + return EJUSTRETURN; + } + else + return ((rt->rt_flags & RTF_HOST) ? EHOSTUNREACH : ENETUNREACH); } - - *prepend_ptr++ = dst->sa_family; /* For lo_output(BPF) */ - *prepend_ptr++ = dlttoproto(dl_tag); /* For lo_demux */ - *prepend_ptr++ = (u_long) ifq; /* For lo_input */ - *prepend_ptr = isr; /* For lo_input */ + + *(u_long *)frame_type = protocol_family; return 0; } - - - /* * lo_input - This should work for all attached protocols that use the * ifq/schednetisr input mechanism. */ - - -int -lo_input(m, fh, ifp, dl_tag, sync_ok) - register struct mbuf *m; - char *fh; - struct ifnet *ifp; - u_long dl_tag; - int sync_ok; - +static int +lo_input( + struct mbuf *m, + __unused char *fh, + __unused struct ifnet *ifp, + __unused u_long protocol_family, + __unused int sync_ok) { - u_long *prepend_ptr; - int s, isr; - register struct ifqueue *ifq = 0; - - prepend_ptr = mtod(m, u_long *); - ifq = (struct ifqueue *) *prepend_ptr++; - isr = *prepend_ptr; - m_adj(m, (2 * sizeof(u_long))); - - s = splimp(); - if (IF_QFULL(ifq)) { - IF_DROP(ifq); + if (proto_input(protocol_family, m) != 0) m_freem(m); - splx(s); - return (EJUSTRETURN); - } - - IF_ENQUEUE(ifq, m); - schednetisr(isr); - splx(s); return (0); } @@ -412,10 +297,10 @@ lo_input(m, fh, ifp, dl_tag, sync_ok) /* ARGSUSED */ static void -lortrequest(cmd, rt, sa) - int cmd; - struct rtentry *rt; - struct sockaddr *sa; +lortrequest( + __unused int cmd, + struct rtentry *rt, + __unused struct sockaddr *sa) { if (rt) { rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ @@ -432,8 +317,11 @@ lortrequest(cmd, rt, sa) /* * Process an ioctl request. */ -static int -lo_if_ioctl(struct ifnet *ifp, u_long cmd, void * data) +static errno_t +loioctl( + ifnet_t ifp, + u_int32_t cmd, + void* data) { register struct ifaddr *ifa; register struct ifreq *ifr = (struct ifreq *)data; @@ -442,7 +330,7 @@ lo_if_ioctl(struct ifnet *ifp, u_long cmd, void * data) switch (cmd) { case SIOCSIFADDR: - ifp->if_flags |= IFF_UP | IFF_RUNNING; + ifnet_set_flags(ifp, IFF_UP | IFF_RUNNING, IFF_UP | IFF_RUNNING); ifa = (struct ifaddr *)data; ifa->ifa_rtrequest = lortrequest; /* @@ -486,140 +374,49 @@ lo_if_ioctl(struct ifnet *ifp, u_long cmd, void * data) } return (error); } - -static int -loioctl(u_long dl_tag, struct ifnet *ifp, u_long cmd, caddr_t data) -{ - return (lo_if_ioctl(ifp, cmd, data)); -} - #endif /* NLOOP > 0 */ -int lo_shutdown() -{ - return 0; -} - -int lo_attach_inet(struct ifnet *ifp, u_long *dl_tag) +static int lo_attach_proto(struct ifnet *ifp, u_long protocol_family) { - struct dlil_proto_reg_str reg; - struct dlil_demux_desc desc; - short native=0; - int stat =0 ; - int i; - - for (i=0; i < lo_count; i++) { - if ((lo_array[i]) && (lo_array[i]->ifp == ifp)) { - if (lo_array[i]->protocol_family == PF_INET) { - *dl_tag = lo_array[i]->dl_tag; - return (0); - } - } - } - - TAILQ_INIT(®.demux_desc_head); - desc.type = DLIL_DESC_RAW; - desc.variants.bitmask.proto_id_length = 0; - desc.variants.bitmask.proto_id = 0; - desc.variants.bitmask.proto_id_mask = 0; - desc.native_type = (char *) &native; - TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next); - reg.interface_family = ifp->if_family; - reg.unit_number = ifp->if_unit; - reg.input = lo_input; - reg.pre_output = lo_pre_output; - reg.event = 0; - reg.offer = 0; - reg.ioctl = loioctl; - reg.default_proto = 0; - reg.protocol_family = PF_INET; - - stat = dlil_attach_protocol(®, dl_tag); - - if (stat) - printf("lo_attach_inet: dlil_attach_protocol returned=%d\n", stat); - - return stat; -} + struct dlil_proto_reg_str reg; + int stat =0 ; + + bzero(®, sizeof(reg)); + TAILQ_INIT(®.demux_desc_head); + reg.interface_family = ifp->if_family; + reg.unit_number = ifp->if_unit; + reg.input = lo_input; + reg.pre_output = lo_pre_output; + reg.protocol_family = protocol_family; + + stat = dlil_attach_protocol(®); -int lo_attach_inet6(struct ifnet *ifp, u_long *dl_tag) -{ - struct dlil_proto_reg_str reg; - struct dlil_demux_desc desc; - short native=0; - int stat; - int i; - - for (i=0; i < lo_count; i++) { - if ((lo_array[i]) && (lo_array[i]->ifp == ifp)) { - if (lo_array[i]->protocol_family == PF_INET6) { - *dl_tag = lo_array[i]->dl_tag; - return (0); - } + if (stat && stat != EEXIST) { + printf("lo_attach_proto: dlil_attach_protocol for %d returned=%d\n", + protocol_family, stat); } - } - - TAILQ_INIT(®.demux_desc_head); - desc.type = DLIL_DESC_RAW; - desc.variants.bitmask.proto_id_length = 0; - desc.variants.bitmask.proto_id = 0; - desc.variants.bitmask.proto_id_mask = 0; - desc.native_type = (char *) &native; - TAILQ_INSERT_TAIL(®.demux_desc_head, &desc, next); - reg.interface_family = ifp->if_family; - reg.unit_number = ifp->if_unit; - reg.input = lo_input; - reg.pre_output = lo_pre_output; - reg.event = 0; - reg.offer = 0; - reg.ioctl = loioctl; - reg.default_proto = 0; - reg.protocol_family = PF_INET6; - - stat = dlil_attach_protocol(®, dl_tag); - - if (stat) - printf("lo_attach_inet6: dlil_attach_protocol returned=%d\n", stat); - - return stat; + + return stat; } void lo_reg_if_mods() { - struct dlil_ifmod_reg_str lo_ifmod; - struct dlil_protomod_reg_str lo_protoreg; int error; - bzero(&lo_ifmod, sizeof(lo_ifmod)); - lo_ifmod.add_if = lo_add_if; - lo_ifmod.del_if = lo_del_if; - lo_ifmod.add_proto = lo_add_proto; - lo_ifmod.del_proto = lo_del_proto; - lo_ifmod.ifmod_ioctl = 0; - lo_ifmod.shutdown = lo_shutdown; - - if (dlil_reg_if_modules(APPLE_IF_FAM_LOOPBACK, &lo_ifmod)) - panic("Couldn't register lo modules\n"); - /* Register protocol registration functions */ - - bzero(&lo_protoreg, sizeof(lo_protoreg)); - lo_protoreg.attach_proto = lo_attach_inet; - lo_protoreg.detach_proto = NULL; /* no detach function for loopback */ - - if ( error = dlil_reg_proto_module(PF_INET, APPLE_IF_FAM_LOOPBACK, &lo_protoreg) != 0) + if ((error = dlil_reg_proto_module(PF_INET, APPLE_IF_FAM_LOOPBACK, lo_attach_proto, NULL)) != 0) printf("dlil_reg_proto_module failed for AF_INET error=%d\n", error); - lo_protoreg.attach_proto = lo_attach_inet6; - lo_protoreg.detach_proto = NULL; - - if ( error = dlil_reg_proto_module(PF_INET6, APPLE_IF_FAM_LOOPBACK, &lo_protoreg) != 0) + if ((error = dlil_reg_proto_module(PF_INET6, APPLE_IF_FAM_LOOPBACK, lo_attach_proto, NULL)) != 0) printf("dlil_reg_proto_module failed for AF_INET6 error=%d\n", error); - } -int lo_set_bpf_tap(struct ifnet *ifp, int mode, int (*bpf_callback)(struct ifnet *, struct mbuf *)) +static errno_t +lo_set_bpf_tap( + ifnet_t ifp, + bpf_tap_mode mode, + bpf_packet_func bpf_callback) { /* @@ -640,32 +437,40 @@ int lo_set_bpf_tap(struct ifnet *ifp, int mode, int (*bpf_callback)(struct ifnet /* ARGSUSED */ void -loopattach(dummy) - void *dummy; +loopattach( + __unused void *dummy) { - register struct ifnet *ifp; - register int i = 0; + struct ifnet *ifp; + int i = 0; - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); lo_reg_if_mods(); for (ifp = loif; i < NLOOP; ifp++) { lo_statics[i].bpf_callback = 0; lo_statics[i].bpf_mode = BPF_TAP_DISABLE; + bzero(ifp, sizeof(struct ifnet)); ifp->if_name = "lo"; ifp->if_family = APPLE_IF_FAM_LOOPBACK; ifp->if_unit = i++; ifp->if_mtu = LOMTU; ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST; - ifp->if_ioctl = lo_if_ioctl; + ifp->if_ioctl = loioctl; + ifp->if_demux = lo_demux; + ifp->if_framer = lo_framer; + ifp->if_add_proto = lo_add_proto; + ifp->if_del_proto = lo_del_proto; ifp->if_set_bpf_tap = lo_set_bpf_tap; ifp->if_output = lo_output; ifp->if_type = IFT_LOOP; - ifp->if_hwassist = 0; /* HW cksum on send side breaks Classic loopback */ + ifp->if_hwassist = IF_HWASSIST_CSUM_IP | IF_HWASSIST_CSUM_TCP | + IF_HWASSIST_CSUM_UDP | IF_HWASSIST_CSUM_IP_FRAGS | + IF_HWASSIST_CSUM_FRAGMENT; + ifp->if_hdrlen = sizeof(struct loopback_header); + lo_ifp = ifp; dlil_if_attach(ifp); #if NBPFILTER > 0 bpfattach(ifp, DLT_NULL, sizeof(u_int)); #endif } - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); + loopattach_done = 1; }