static errno_t utun_detach_ip( ifnet_t interface, protocol_family_t protocol, socket_t pf_socket) { errno_t result = EPROTONOSUPPORT; /* Attempt a detach */ if (protocol == PF_INET) { struct ifreq ifr; bzero(&ifr, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", ifnet_name(interface), ifnet_unit(interface)); result = sock_ioctl(pf_socket, SIOCPROTODETACH, &ifr); } else if (protocol == PF_INET6) { struct in6_ifreq ifr6; bzero(&ifr6, sizeof(ifr6)); snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d", ifnet_name(interface), ifnet_unit(interface)); result = sock_ioctl(pf_socket, SIOCPROTODETACH_IN6, &ifr6); } return result; }
/* ----------------------------------------------------------------------------- Handle a CCP packet. `rcvd' is 1 if the packet was received, 0 if it is about to be transmitted. mbuf points to the ccp payload (doesn't include FF03 and 80FD) ----------------------------------------------------------------------------- */ void ppp_comp_ccp(struct ppp_if *wan, mbuf_t m, int rcvd) { u_char *p = mbuf_data(m); int slen; slen = CCP_LENGTH(p); if (slen > mbuf_pkthdr_len(m)) { LOGDBG(wan->net, ("ppp_comp_ccp: not enough data in mbuf (expected = %d, got = %d)\n", slen, mbuf_pkthdr_len(m))); return; } switch (CCP_CODE(p)) { case CCP_CONFREQ: case CCP_TERMREQ: case CCP_TERMACK: /* CCP must be going down - disable compression */ wan->sc_flags &= ~(rcvd ? SC_COMP_RUN : SC_DECOMP_RUN); break; case CCP_CONFACK: if (wan->sc_flags & SC_CCP_OPEN && !(wan->sc_flags & SC_CCP_UP) && slen >= CCP_HDRLEN + CCP_OPT_MINLEN && slen >= CCP_OPT_LENGTH(p + CCP_HDRLEN) + CCP_HDRLEN) { if (rcvd) { /* peer is agreeing to send compressed packets. */ if (wan->rc_state && (*wan->rcomp->decomp_init) (wan->rc_state, p + CCP_HDRLEN, slen - CCP_HDRLEN, ifnet_unit(wan->net), 0, wan->mru, ifnet_flags(wan->net) & IFF_DEBUG)) { wan->sc_flags |= SC_DECOMP_RUN; wan->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); } } else { /* we're agreeing to send compressed packets. */ if (wan->xc_state && (*wan->xcomp->comp_init) (wan->xc_state, p + CCP_HDRLEN, slen - CCP_HDRLEN, ifnet_unit(wan->net), 0, ifnet_mtu(wan->net), ifnet_flags(wan->net) & IFF_DEBUG)) { wan->sc_flags |= SC_COMP_RUN; } } } break; case CCP_RESETACK: if (wan->sc_flags & SC_CCP_UP) { if (rcvd) { if (wan->rc_state && (wan->sc_flags & SC_DECOMP_RUN)) { (*wan->rcomp->decomp_reset)(wan->rc_state); wan->sc_flags &= ~SC_DC_ERROR; } } else { if (wan->xc_state && (wan->sc_flags & SC_COMP_RUN)) (*wan->xcomp->comp_reset)(wan->xc_state); } } break; } }
static void utun_remove_address( ifnet_t interface, protocol_family_t protocol, ifaddr_t address, socket_t pf_socket) { errno_t result = 0; /* Attempt a detach */ if (protocol == PF_INET) { struct ifreq ifr; bzero(&ifr, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", ifnet_name(interface), ifnet_unit(interface)); result = ifaddr_address(address, &ifr.ifr_addr, sizeof(ifr.ifr_addr)); if (result != 0) { printf("utun_remove_address - ifaddr_address failed: %d", result); } else { result = sock_ioctl(pf_socket, SIOCDIFADDR, &ifr); if (result != 0) { printf("utun_remove_address - SIOCDIFADDR failed: %d", result); } } } else if (protocol == PF_INET6) { struct in6_ifreq ifr6; bzero(&ifr6, sizeof(ifr6)); snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d", ifnet_name(interface), ifnet_unit(interface)); result = ifaddr_address(address, (struct sockaddr*)&ifr6.ifr_addr, sizeof(ifr6.ifr_addr)); if (result != 0) { printf("utun_remove_address - ifaddr_address failed (v6): %d", result); } else { result = sock_ioctl(pf_socket, SIOCDIFADDR_IN6, &ifr6); if (result != 0) { printf("utun_remove_address - SIOCDIFADDR_IN6 failed: %d", result); } } } }
/* ----------------------------------------------------------------------------- attach the PPPx interface ifp to the network protocol IP, called when the ppp interface is ready for ppp traffic ----------------------------------------------------------------------------- */ errno_t ppp_ip_attach(ifnet_t ifp, protocol_family_t protocol) { int ret; struct ifnet_attach_proto_param reg; struct ppp_if *wan = (struct ppp_if *)ifnet_softc(ifp); LOGDBG(ifp, ("ppp_ip_attach: name = %s, unit = %d\n", ifnet_name(ifp), ifnet_unit(ifp))); if (wan->ip_attached) return 0; // already attached bzero(®, sizeof(struct ifnet_attach_proto_param)); reg.input = ppp_ip_input; reg.pre_output = ppp_ip_preoutput; reg.ioctl = ppp_ip_ioctl; ret = ifnet_attach_protocol(ifp, PF_INET, ®); LOGRETURN(ret, ret, "ppp_ip_attach: ifnet_attach_protocol error = 0x%x\n"); LOGDBG(ifp, ("ppp_i6_attach: ifnet_attach_protocol family = 0x%x\n", protocol)); ifnet_find_by_name("lo0", &wan->lo_ifp); wan->ip_attached = 1; return 0; }
/* * Set the data link type of a BPF instance. */ static int bpf_setdlt(struct bpf_d *d, uint32_t dlt) { int error, opromisc; struct ifnet *ifp; struct bpf_if *bp; if (d->bd_bif->bif_dlt == dlt) return (0); ifp = d->bd_bif->bif_ifp; for (bp = bpf_iflist; bp; bp = bp->bif_next) { if (bp->bif_ifp == ifp && bp->bif_dlt == dlt) break; } if (bp != NULL) { opromisc = d->bd_promisc; bpf_detachd(d); error = bpf_attachd(d, bp); if (error) { printf("bpf_setdlt: bpf_attachd %s%d failed (%d)\n", ifnet_name(bp->bif_ifp), ifnet_unit(bp->bif_ifp), error); return error; } reset_d(d); if (opromisc) { lck_mtx_unlock(bpf_mlock); error = ifnet_set_promiscuous(bp->bif_ifp, 1); lck_mtx_lock(bpf_mlock); if (error) printf("bpf_setdlt: ifpromisc %s%d failed (%d)\n", ifnet_name(bp->bif_ifp), ifnet_unit(bp->bif_ifp), error); else d->bd_promisc = 1; } } return (bp == NULL ? EINVAL : 0); }
static errno_t utun_ctl_getopt( __unused kern_ctl_ref kctlref, __unused u_int32_t unit, void *unitinfo, int opt, void *data, size_t *len) { struct utun_pcb *pcb = unitinfo; errno_t result = 0; switch (opt) { case UTUN_OPT_FLAGS: if (*len != sizeof(u_int32_t)) result = EMSGSIZE; else *(u_int32_t *)data = pcb->utun_flags; break; case UTUN_OPT_EXT_IFDATA_STATS: if (*len != sizeof(int)) result = EMSGSIZE; else *(int *)data = (pcb->utun_ext_ifdata_stats) ? 1 : 0; break; case UTUN_OPT_IFNAME: *len = snprintf(data, *len, "%s%d", ifnet_name(pcb->utun_ifp), ifnet_unit(pcb->utun_ifp)) + 1; break; case UTUN_OPT_GENERATE_CRYPTO_KEYS_IDX: result = utun_ctl_generate_crypto_keys_idx(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_MAX_PENDING_PACKETS: { *len = sizeof(u_int32_t); *((u_int32_t *)data) = pcb->utun_max_pending_packets; break; } default: result = ENOPROTOOPT; break; } return result; }
static errno_t ipsec_ctl_getopt(__unused kern_ctl_ref kctlref, __unused u_int32_t unit, void *unitinfo, int opt, void *data, size_t *len) { struct ipsec_pcb *pcb = unitinfo; errno_t result = 0; switch (opt) { case IPSEC_OPT_FLAGS: if (*len != sizeof(u_int32_t)) result = EMSGSIZE; else *(u_int32_t *)data = pcb->ipsec_flags; break; case IPSEC_OPT_EXT_IFDATA_STATS: if (*len != sizeof(int)) result = EMSGSIZE; else *(int *)data = (pcb->ipsec_ext_ifdata_stats) ? 1 : 0; break; case IPSEC_OPT_IFNAME: *len = snprintf(data, *len, "%s%d", ifnet_name(pcb->ipsec_ifp), ifnet_unit(pcb->ipsec_ifp)) + 1; break; case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: { if (*len != sizeof(int)) { result = EMSGSIZE; break; } *(int *)data = so_svc2tc(pcb->ipsec_output_service_class); break; } default: result = ENOPROTOOPT; break; } return result; }
IOReturn darwin_iwi3945::enable( IONetworkInterface * netif ) { if (!fifnet) { char ii[4]; sprintf(ii,"%s%d" ,fNetif->getNamePrefix(), fNetif->getUnitNumber()); ifnet_find_by_name(ii,&fifnet); IWI_DEBUG("ifnet_t %s%d = %x\n",ifnet_name(fifnet),ifnet_unit(fifnet),fifnet); struct ieee80211_local* loc=hw_to_local(priv->hw); memcpy(&loc->mdev->name,ii,sizeof(ii)); loc->mdev->ifindex=fNetif->getUnitNumber(); priv->interface_id=fNetif->getUnitNumber(); } if (firstifup==0) { firstifup=1; return -1; } IWI_DEBUG("ifconfig up\n"); if ((fNetif->getFlags() & IFF_RUNNING)==0) { IWI_DEBUG("ifconfig going up\n "); //super::enable(fNetif); //fNetif->setPoweredOnByUser(true); //fNetif->setLinkState(kIO80211NetworkLinkUp); //(if_flags & ~mask) | (new_flags & mask) if mask has IFF_UP if_updown fires up (kpi_interface.c in xnu) if (priv->status & STATUS_AUTH) ifnet_set_flags(fifnet, IFF_RUNNING, IFF_RUNNING ); //fNetif->inputEvent(kIONetworkEventTypeLinkUp,NULL); fTransmitQueue->setCapacity(1024); fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); fTransmitQueue->start(); return kIOReturnSuccess; } else { IWI_DEBUG("ifconfig already up\n"); return kIOReturnExclusiveAccess; } }
//////////////////////////////////////////////////////////////////////////////// // // firewire_attach_inet // // IN: ifnet_t ifp // // Invoked by: // firewire_attach_inet will be invoked from IOFWInterface::attachToDataLinkLayer // //////////////////////////////////////////////////////////////////////////////// int firewire_attach_inet(ifnet_t ifp, protocol_family_t protocol_family) { struct ifnet_attach_proto_param proto; struct ifnet_demux_desc demux[2]; u_short en_native=htons(FWTYPE_IP); u_short arp_native=htons(FWTYPE_ARP); errno_t error; bzero(&demux[0], sizeof(demux)); demux[0].type = DLIL_DESC_ETYPE2; demux[0].data = &en_native; demux[0].datalen = sizeof(en_native); demux[1].type = DLIL_DESC_ETYPE2; demux[1].data = &arp_native; demux[1].datalen = sizeof(arp_native); bzero(&proto, sizeof(proto)); proto.demux_list = demux; proto.demux_count = sizeof(demux) / sizeof(demux[0]); proto.input = inet_firewire_input; proto.pre_output = inet_firewire_pre_output; proto.ioctl = firewire_inet_prmod_ioctl; proto.event = firewire_inet_event; proto.resolve = firewire_inet_resolve_multi; proto.send_arp = firewire_inet_arp; error = ifnet_attach_protocol(ifp, protocol_family, &proto); if (error && error != EEXIST) { printf("WARNING: firewire_attach_inet can't attach ip to %s%d\n", ifnet_name(ifp), ifnet_unit(ifp)); } return error; }
static void utun_cleanup_family( ifnet_t interface, protocol_family_t protocol) { errno_t result = 0; socket_t pf_socket = NULL; ifaddr_t *addresses = NULL; int i; if (protocol != PF_INET && protocol != PF_INET6) { printf("utun_cleanup_family - invalid protocol family %d\n", protocol); return; } /* Create a socket for removing addresses and detaching the protocol */ result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket); if (result != 0) { if (result != EAFNOSUPPORT) printf("utun_cleanup_family - failed to create %s socket: %d\n", protocol == PF_INET ? "IP" : "IPv6", result); goto cleanup; } /* always set SS_PRIV, we want to close and detach regardless */ sock_setpriv(pf_socket, 1); result = utun_detach_ip(interface, protocol, pf_socket); if (result == 0 || result == ENXIO) { /* We are done! We either detached or weren't attached. */ goto cleanup; } else if (result != EBUSY) { /* Uh, not really sure what happened here... */ printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result); goto cleanup; } /* * At this point, we received an EBUSY error. This means there are * addresses attached. We should detach them and then try again. */ result = ifnet_get_address_list_family(interface, &addresses, protocol); if (result != 0) { printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n", ifnet_name(interface), ifnet_unit(interface), protocol == PF_INET ? "PF_INET" : "PF_INET6", result); goto cleanup; } for (i = 0; addresses[i] != 0; i++) { utun_remove_address(interface, protocol, addresses[i], pf_socket); } ifnet_free_address_list(addresses); addresses = NULL; /* * The addresses should be gone, we should try the remove again. */ result = utun_detach_ip(interface, protocol, pf_socket); if (result != 0 && result != ENXIO) { printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result); } cleanup: if (pf_socket != NULL) sock_close(pf_socket); if (addresses != NULL) ifnet_free_address_list(addresses); }
/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ int ppp_comp_setcompressor(struct ppp_if *wan, struct ppp_option_data *odp) { int error = 0; u_int32_t nb; struct ppp_comp *cp; u_char ccp_option[CCP_MAX_OPTION_LENGTH]; user_addr_t ptr; int transmit; if (proc_is64bit(current_proc())) { struct ppp_option_data64 *odp64 = (struct ppp_option_data64 *)odp; nb = odp64->length; ptr = odp64->ptr; transmit = odp64->transmit; } else { struct ppp_option_data32 *odp32 = (struct ppp_option_data32 *)odp; nb = odp32->length; ptr = CAST_USER_ADDR_T(odp32->ptr); transmit = odp32->transmit; } if (nb > sizeof(ccp_option)) nb = sizeof(ccp_option); if (error = copyin(ptr, ccp_option, nb)) return (error); if (ccp_option[1] < 2) /* preliminary check on the length byte */ return (EINVAL); cp = ppp_comp_find(ccp_option[0]); if (cp == 0) { LOGDBG(wan->net, ("ppp%d: no compressor for [%x %x %x], %x\n", ifnet_unit(wan->net), ccp_option[0], ccp_option[1], ccp_option[2], nb)); return EINVAL; /* no handler found */ } if (transmit) { if (wan->xc_state) (*wan->xcomp->comp_free)(wan->xc_state); wan->xcomp = cp; wan->xc_state = cp->comp_alloc(ccp_option, nb); if (!wan->xc_state) { error = ENOMEM; LOGDBG(wan->net, ("ppp%d: comp_alloc failed\n", ifnet_unit(wan->net))); } wan->sc_flags &= ~SC_COMP_RUN; } else { if (wan->rc_state) (*wan->rcomp->decomp_free)(wan->rc_state); wan->rcomp = cp; wan->rc_state = cp->decomp_alloc(ccp_option, nb); if (!wan->rc_state) { error = ENOMEM; LOGDBG(wan->net, ("ppp%d: decomp_alloc failed\n", ifnet_unit(wan->net))); } wan->sc_flags &= ~SC_DECOMP_RUN; } return error; }