/* ----------------------------------------------------------------------------- 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; }
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; } }
/*--------------------------------------------------------------------------- * Enable the interface. There is some handling to ensure we use the correct MTU size based on all the interfaces that are enabled. * We have to consider the case where the MTU value is not consistant across interfaces. In this case we use the minimum ---------------------------------------------------------------------------*/ kern_return_t EInterfaces::enable_interface(int nEthernetNumber) { char acBSDName[20]; kern_return_t retval; ifnet_t enetifnet; if ( nEthernetNumber>=MAX_SUPPORTED_ETHERNET_CONNETIONS ) { debugError("Invalid ethernet port\n"); return -1; } debug("AOE_KEXT_NAME::enable_interface(port=%d)\n", nEthernetNumber); // Create our BSD name to locate ifnet_t snprintf(acBSDName, sizeof(acBSDName), "en%d", nEthernetNumber); retval = ifnet_find_by_name(acBSDName, &enetifnet); if (retval == KERN_SUCCESS) enable_filtering(nEthernetNumber, enetifnet); // Incremement the number of interfaces in use if it isn't already being used if ( !m_aInterfaces[nEthernetNumber].m_fEnabled ) ++m_nInterfacesInUse; m_aInterfaces[nEthernetNumber].m_ifnet = enetifnet; m_aInterfaces[nEthernetNumber].m_fEnabled = TRUE; // Reset our CC/SS parameters set_cwnd(m_aInterfaces[nEthernetNumber].m_ifnet, 1); set_ssthresh(m_aInterfaces[nEthernetNumber].m_ifnet, m_aInterfaces[nEthernetNumber].get_max_outstanding_all_shelves()/2); m_aInterfaces[nEthernetNumber].m_nOutstandingCount = 0; debug("enable_interface(%d), %d interface(s) now in use\n", nEthernetNumber, m_nInterfacesInUse); // Check the packet size based on the MTU of all the connected interfaces recalculate_mtu(); // Set the properties to show the available interfaces update_interface_property(); return retval; }
static errno_t utun_ctl_setopt( __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; /* check for privileges for privileged options */ switch (opt) { case UTUN_OPT_FLAGS: case UTUN_OPT_EXT_IFDATA_STATS: case UTUN_OPT_SET_DELEGATE_INTERFACE: if (kauth_cred_issuser(kauth_cred_get()) == 0) { return EPERM; } break; } switch (opt) { case UTUN_OPT_FLAGS: if (len != sizeof(u_int32_t)) result = EMSGSIZE; else pcb->utun_flags = *(u_int32_t *)data; break; case UTUN_OPT_ENABLE_CRYPTO: result = utun_ctl_enable_crypto(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_CONFIG_CRYPTO_KEYS: result = utun_ctl_config_crypto_keys(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_UNCONFIG_CRYPTO_KEYS: result = utun_ctl_unconfig_crypto_keys(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_DISABLE_CRYPTO: result = utun_ctl_disable_crypto(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_STOP_CRYPTO_DATA_TRAFFIC: result = utun_ctl_stop_crypto_data_traffic(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_START_CRYPTO_DATA_TRAFFIC: result = utun_ctl_start_crypto_data_traffic(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_CONFIG_CRYPTO_FRAMER: result = utun_ctl_config_crypto_framer(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_UNCONFIG_CRYPTO_FRAMER: result = utun_ctl_unconfig_crypto_framer(kctlref, unit, unitinfo, opt, data, len); break; case UTUN_OPT_EXT_IFDATA_STATS: if (len != sizeof(int)) { result = EMSGSIZE; break; } pcb->utun_ext_ifdata_stats = (*(int *)data) ? 1 : 0; break; case UTUN_OPT_INC_IFDATA_STATS_IN: case UTUN_OPT_INC_IFDATA_STATS_OUT: { struct utun_stats_param *utsp = (struct utun_stats_param *)data; if (utsp == NULL || len < sizeof(struct utun_stats_param)) { result = EINVAL; break; } if (!pcb->utun_ext_ifdata_stats) { result = EINVAL; break; } if (opt == UTUN_OPT_INC_IFDATA_STATS_IN) ifnet_stat_increment_in(pcb->utun_ifp, utsp->utsp_packets, utsp->utsp_bytes, utsp->utsp_errors); else ifnet_stat_increment_out(pcb->utun_ifp, utsp->utsp_packets, utsp->utsp_bytes, utsp->utsp_errors); break; } case UTUN_OPT_SET_DELEGATE_INTERFACE: { ifnet_t del_ifp = NULL; char name[IFNAMSIZ]; if (len > IFNAMSIZ - 1) { result = EMSGSIZE; break; } if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */ bcopy(data, name, len); name[len] = 0; result = ifnet_find_by_name(name, &del_ifp); } if (result == 0) { result = ifnet_set_delegate(pcb->utun_ifp, del_ifp); if (del_ifp) ifnet_release(del_ifp); } break; } default: result = ENOPROTOOPT; break; } return result; }
static errno_t utun_ctl_setopt( __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; /* check for privileges for privileged options */ switch (opt) { case UTUN_OPT_FLAGS: case UTUN_OPT_EXT_IFDATA_STATS: case UTUN_OPT_SET_DELEGATE_INTERFACE: if (kauth_cred_issuser(kauth_cred_get()) == 0) { return EPERM; } break; } switch (opt) { case UTUN_OPT_FLAGS: if (len != sizeof(u_int32_t)) { result = EMSGSIZE; } else { u_int32_t old_flags = pcb->utun_flags; pcb->utun_flags = *(u_int32_t *)data; if (((old_flags ^ pcb->utun_flags) & UTUN_FLAGS_ENABLE_PROC_UUID)) { // If UTUN_FLAGS_ENABLE_PROC_UUID flag changed, update bpf bpfdetach(pcb->utun_ifp); bpfattach(pcb->utun_ifp, DLT_NULL, UTUN_HEADER_SIZE(pcb)); } } break; case UTUN_OPT_EXT_IFDATA_STATS: if (len != sizeof(int)) { result = EMSGSIZE; break; } pcb->utun_ext_ifdata_stats = (*(int *)data) ? 1 : 0; break; case UTUN_OPT_INC_IFDATA_STATS_IN: case UTUN_OPT_INC_IFDATA_STATS_OUT: { struct utun_stats_param *utsp = (struct utun_stats_param *)data; if (utsp == NULL || len < sizeof(struct utun_stats_param)) { result = EINVAL; break; } if (!pcb->utun_ext_ifdata_stats) { result = EINVAL; break; } if (opt == UTUN_OPT_INC_IFDATA_STATS_IN) ifnet_stat_increment_in(pcb->utun_ifp, utsp->utsp_packets, utsp->utsp_bytes, utsp->utsp_errors); else ifnet_stat_increment_out(pcb->utun_ifp, utsp->utsp_packets, utsp->utsp_bytes, utsp->utsp_errors); break; } case UTUN_OPT_SET_DELEGATE_INTERFACE: { ifnet_t del_ifp = NULL; char name[IFNAMSIZ]; if (len > IFNAMSIZ - 1) { result = EMSGSIZE; break; } if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */ bcopy(data, name, len); name[len] = 0; result = ifnet_find_by_name(name, &del_ifp); } if (result == 0) { result = ifnet_set_delegate(pcb->utun_ifp, del_ifp); if (del_ifp) ifnet_release(del_ifp); } break; } case UTUN_OPT_MAX_PENDING_PACKETS: { u_int32_t max_pending_packets = 0; if (len != sizeof(u_int32_t)) { result = EMSGSIZE; break; } max_pending_packets = *(u_int32_t *)data; if (max_pending_packets == 0) { result = EINVAL; break; } pcb->utun_max_pending_packets = max_pending_packets; break; } default: { result = ENOPROTOOPT; break; } } return result; }
/** * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered. * * @returns VBox status code. * @param pThis The instance. * @param fRediscovery If set we're doing a rediscovery attempt, so, don't * flood the release log. */ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery) { LogFlow(("vboxNetFltDarwinAttachToInterface: pThis=%p (%s)\n", pThis, pThis->szName)); /* * Locate the interface first. * * The pIfNet member is updated before iflt_attach is called and used * to deal with the hypothetical case where someone rips out the * interface immediately after our iflt_attach call. */ ifnet_t pIfNet = NULL; errno_t err = ifnet_find_by_name(pThis->szName, &pIfNet); if (err) { Assert(err == ENXIO); if (!fRediscovery) LogRel(("VBoxFltDrv: failed to find ifnet '%s' (err=%d)\n", pThis->szName, err)); else Log(("VBoxFltDrv: failed to find ifnet '%s' (err=%d)\n", pThis->szName, err)); return VERR_INTNET_FLT_IF_NOT_FOUND; } RTSpinlockAcquire(pThis->hSpinlock); ASMAtomicUoWritePtr(&pThis->u.s.pIfNet, pIfNet); RTSpinlockReleaseNoInts(pThis->hSpinlock); /* * Get the mac address while we still have a valid ifnet reference. */ err = ifnet_lladdr_copy_bytes(pIfNet, &pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); if (!err) { /* * Try attach the filter. */ struct iff_filter RegRec; RegRec.iff_cookie = pThis; RegRec.iff_name = "VBoxNetFlt"; RegRec.iff_protocol = 0; RegRec.iff_input = vboxNetFltDarwinIffInput; RegRec.iff_output = vboxNetFltDarwinIffOutput; RegRec.iff_event = vboxNetFltDarwinIffEvent; RegRec.iff_ioctl = vboxNetFltDarwinIffIoCtl; RegRec.iff_detached = vboxNetFltDarwinIffDetached; interface_filter_t pIfFilter = NULL; err = iflt_attach(pIfNet, &RegRec, &pIfFilter); Assert(err || pIfFilter); RTSpinlockAcquire(pThis->hSpinlock); pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t); if (pIfNet && !err) { ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); ASMAtomicUoWritePtr(&pThis->u.s.pIfFilter, pIfFilter); pIfNet = NULL; /* don't dereference it */ } RTSpinlockReleaseNoInts(pThis->hSpinlock); /* Report capabilities. */ if ( !pIfNet && vboxNetFltTryRetainBusyNotDisconnected(pThis)) { Assert(pThis->pSwitchPort); pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltDarwinIsPromiscuous(pThis)); pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); vboxNetFltRelease(pThis, true /*fBusy*/); } } /* Release the interface on failure. */ if (pIfNet) ifnet_release(pIfNet); int rc = RTErrConvertFromErrno(err); if (RT_SUCCESS(rc)) LogRel(("VBoxFltDrv: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); else LogRel(("VBoxFltDrv: failed to attach to ifnet '%s' (err=%d)\n", pThis->szName, err)); return rc; }
static errno_t ipsec_ctl_setopt(__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; /* check for privileges for privileged options */ switch (opt) { case IPSEC_OPT_FLAGS: case IPSEC_OPT_EXT_IFDATA_STATS: case IPSEC_OPT_SET_DELEGATE_INTERFACE: case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: if (kauth_cred_issuser(kauth_cred_get()) == 0) { return EPERM; } break; } switch (opt) { case IPSEC_OPT_FLAGS: if (len != sizeof(u_int32_t)) result = EMSGSIZE; else pcb->ipsec_flags = *(u_int32_t *)data; break; case IPSEC_OPT_EXT_IFDATA_STATS: if (len != sizeof(int)) { result = EMSGSIZE; break; } pcb->ipsec_ext_ifdata_stats = (*(int *)data) ? 1 : 0; break; case IPSEC_OPT_INC_IFDATA_STATS_IN: case IPSEC_OPT_INC_IFDATA_STATS_OUT: { struct ipsec_stats_param *utsp = (struct ipsec_stats_param *)data; if (utsp == NULL || len < sizeof(struct ipsec_stats_param)) { result = EINVAL; break; } if (!pcb->ipsec_ext_ifdata_stats) { result = EINVAL; break; } if (opt == IPSEC_OPT_INC_IFDATA_STATS_IN) ifnet_stat_increment_in(pcb->ipsec_ifp, utsp->utsp_packets, utsp->utsp_bytes, utsp->utsp_errors); else ifnet_stat_increment_out(pcb->ipsec_ifp, utsp->utsp_packets, utsp->utsp_bytes, utsp->utsp_errors); break; } case IPSEC_OPT_SET_DELEGATE_INTERFACE: { ifnet_t del_ifp = NULL; char name[IFNAMSIZ]; if (len > IFNAMSIZ - 1) { result = EMSGSIZE; break; } if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */ bcopy(data, name, len); name[len] = 0; result = ifnet_find_by_name(name, &del_ifp); } if (result == 0) { result = ifnet_set_delegate(pcb->ipsec_ifp, del_ifp); if (del_ifp) ifnet_release(del_ifp); } break; } case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: { if (len != sizeof(int)) { result = EMSGSIZE; break; } mbuf_svc_class_t output_service_class = so_tc2msc(*(int *)data); if (output_service_class == MBUF_SC_UNSPEC) { pcb->ipsec_output_service_class = MBUF_SC_OAM; } else { pcb->ipsec_output_service_class = output_service_class; } break; } default: result = ENOPROTOOPT; break; } return result; }
//////////////////////////////////////////////////////////////////////////////// // // firewire_frameout // // IN: ifnet_t ifp,struct mbuf **m // IN: struct sockaddr *ndest - contains the destination IP Address // IN: char *edst - filled by firewire_arpresolve function in if_firewire.c // IN: char *fw_type // // Invoked by : // dlil.c for dlil_output, Its called after inet_firewire_pre_output // // Encapsulate a packet of type family for the local net. // Use trailer local net encapsulation if enough data in first // packet leaves a multiple of 512 bytes of data in remainder. // //////////////////////////////////////////////////////////////////////////////// __private_extern__ int firewire_frameout(ifnet_t ifp, mbuf_t *m, const struct sockaddr *ndest, const char *edst, const char *fw_type) { register struct firewire_header *fwh; /* * If a simplex interface, and the packet is being sent to our * Ethernet address or a broadcast address, loopback a copy. * XXX To make a simplex device behave exactly like a duplex * device, we should copy in the case of sending to our own * ethernet address (thus letting the original actually appear * on the wire). However, we don't do that here for security * reasons and compatibility with the original behavior. */ if ((ifnet_flags(ifp) & IFF_SIMPLEX) && (mbuf_flags(*m) & MBUF_LOOP)) { if (loop_ifp == NULL) { ifnet_find_by_name("lo0", &loop_ifp); /* * We make an assumption here that lo0 will never go away. This * means we don't have to worry about releasing the reference * later and we don't have to worry about leaking a reference * every time we are loaded. */ ifnet_release(loop_ifp); } if (loop_ifp) { if (mbuf_flags(*m) & MBUF_BCAST) { mbuf_t n; if (mbuf_copym(*m, 0, MBUF_COPYALL, MBUF_WAITOK, &n) == 0) ifnet_output(loop_ifp, PF_INET, n, 0, ndest); } else { if (bcmp(edst, ifnet_lladdr(ifp), FIREWIRE_ADDR_LEN) == 0) { ifnet_output(loop_ifp, PF_INET, *m, 0, ndest); return EJUSTRETURN; } } } } // // Add local net header. If no space in first mbuf, // allocate another. // if (mbuf_prepend(m, sizeof(struct firewire_header), MBUF_DONTWAIT) != 0) return (EJUSTRETURN); // // Lets put this intelligent here into the mbuf // so we can demux on our output path // fwh = (struct firewire_header*)mbuf_data(*m); (void)memcpy(&fwh->fw_type, fw_type,sizeof(fwh->fw_type)); memcpy(fwh->fw_dhost, edst, FIREWIRE_ADDR_LEN); (void)memcpy(fwh->fw_shost, ifnet_lladdr(ifp), sizeof(fwh->fw_shost)); return 0; }