////////////////////////////////////////////////////////////////////////////////
//
// firewire_demux
//
// IN: ifnet_t ifp,struct mbuf  *m,char *frame_header,
//	   u_long *protocol_family
// 
// Invoked by : 
//  dlil_input_packet()
// 
////////////////////////////////////////////////////////////////////////////////
__private_extern__ int firewire_demux(ifnet_t ifp, mbuf_t m, char *frame_header, protocol_family_t *protocol_family)
{
    register struct firewire_header *eh = (struct firewire_header *)frame_header;

	IOFWInterface					*fwIf		= (IOFWInterface*)ifnet_softc(ifp);
	
	if(fwIf == NULL)
		return EINVAL;
	
	struct firewire_desc_blk_str	*desc_blk	= (struct firewire_desc_blk_str *)fwIf->getFamilyCookie();

	if (desc_blk == NULL)
		return EINVAL;

	u_short			fw_type = eh->fw_type;
    u_int16_t		type = DLIL_DESC_ETYPE2;
    u_long			maxd = desc_blk->n_max_used;
    struct fw_desc	*ed = desc_blk->block_ptr;

    /* 
     * Search through the connected protocols for a match. 
     */
	for (u_long i = 0; i < maxd; i++) 
	{
		if ((ed[i].type == type) && (ed[i].data[0] == fw_type)) 
		{
			*protocol_family = ed[i].protocol_family;
			return 0;
		}
	}
    
    return ENOENT;
}
示例#2
0
文件: ppp_ip.c 项目: Deanzou/ppp
/* -----------------------------------------------------------------------------
pre_output function
----------------------------------------------------------------------------- */
errno_t ppp_ip_preoutput(ifnet_t ifp, protocol_family_t protocol,
									mbuf_t *packet, const struct sockaddr *dest, 
									void *route, char *frame_type, char *link_layer_dest)
{
    errno_t				err;
    struct ppp_if		*wan = (struct ppp_if *)ifnet_softc(ifp);
    u_int16_t           ftype = PPP_IP;

    LOGMBUF("ppp_ip_preoutput", *packet);
	
	lck_mtx_lock(ppp_domain_mutex);

#if 0
    (*packet)->m_flags &= ~M_HIGHPRI;

    /* If this packet has the "low delay" bit set in the IP header,
     set priority bit for the packet. */
    ip = mtod(*packet, struct ip *);
    if (ip->ip_tos & IPTOS_LOWDELAY)
        (*packet)->m_flags |= M_HIGHPRI;
#endif

    if ((wan->sc_flags & SC_LOOP_LOCAL)
        && (!memcmp(&((struct sockaddr_in *)(void*)dest)->sin_addr.s_addr, &wan->ip_src.s_addr, sizeof(struct in_addr)))    // Wcast-align fix - memcmp for unaligned compare
		&& wan->lo_ifp) {
        err = ifnet_output(wan->lo_ifp, PF_INET, *packet, 0, (struct sockaddr *)dest);
		lck_mtx_unlock(ppp_domain_mutex);
        return (err ? err : EJUSTRETURN);
    }
	lck_mtx_unlock(ppp_domain_mutex);
    memcpy(frame_type, &ftype, sizeof(u_int16_t));     // Wcast-align fix - memcpy for unaligned move
    return 0;
}
示例#3
0
文件: ppp_ip.c 项目: Deanzou/ppp
/* -----------------------------------------------------------------------------
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(&reg, 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, &reg);
    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;
}
示例#4
0
/* Network Interface functions */
static void
utun_start(ifnet_t interface)
{
	mbuf_t data;
	struct utun_pcb*pcb = ifnet_softc(interface);
	for (;;) {
		bool can_accept_packets = true;
		ifnet_lock_shared(pcb->utun_ifp);
		can_accept_packets = (pcb->utun_pending_packets < pcb->utun_max_pending_packets);
		if (!can_accept_packets && pcb->utun_ctlref) {
			u_int32_t difference = 0;
			if (ctl_getenqueuereadable(pcb->utun_ctlref, pcb->utun_unit, &difference) == 0) {
				if (difference > 0) {
					// If the low-water mark has not yet been reached, we still need to enqueue data
					// into the buffer
					can_accept_packets = true;
				}
			}
		}
		if (!can_accept_packets) {
			errno_t error = ifnet_disable_output(interface);
			if (error != 0) {
				printf("utun_start: ifnet_disable_output returned error %d\n", error);
			}
			ifnet_lock_done(pcb->utun_ifp);
			break;
		}
		ifnet_lock_done(pcb->utun_ifp);
		if (ifnet_dequeue(interface, &data) != 0)
			break;
		if (utun_output(interface, data) != 0)
			break;
	}
}
示例#5
0
文件: if_utun.c 项目: onlynone/xnu
static errno_t
utun_framer(
		   __unused ifnet_t				interface,
		   mbuf_t				*packet,
			__unused const struct sockaddr *dest, 
			__unused const char *desk_linkaddr,
			const char *frame_type,
			u_int32_t *prepend_len, 
			u_int32_t *postpend_len)
{
	struct utun_pcb	*pcb = ifnet_softc(interface);
	VERIFY(interface == pcb->utun_ifp);

	u_int32_t header_length = UTUN_HEADER_SIZE(pcb);
    if (mbuf_prepend(packet, header_length, MBUF_DONTWAIT) != 0) {
		printf("utun_framer - ifnet_output prepend failed\n");

		ifnet_stat_increment_out(interface, 0, 0, 1);

		// just	return, because the buffer was freed in mbuf_prepend
        return EJUSTRETURN;	
    }
	if (prepend_len != NULL)
		*prepend_len = header_length;
	if (postpend_len != NULL)
		*postpend_len = 0;
	
    // place protocol number at the beginning of the mbuf
    *(protocol_family_t *)mbuf_data(*packet) = *(protocol_family_t *)(uintptr_t)(size_t)frame_type;


    return 0;
}
示例#6
0
文件: ppp_ip.c 项目: Deanzou/ppp
/* -----------------------------------------------------------------------------
Compare the source address of the packet with the dst address of the interface
----------------------------------------------------------------------------- */
int ppp_ip_af_src_in(ifnet_t ifp, char *pkt)
{
    struct ppp_if	*wan = (struct ppp_if *)ifnet_softc(ifp);
    struct ip 		*ip;
        
    // Wcast-align fixes - use memcmp for unaligned accesses
    ip = (struct ip *)(void*)pkt;
    return (memcmp(&ip->ip_src.s_addr, &wan->ip_dst.s_addr, sizeof(struct in_addr)) == 0 ? 0 : 1);
}
示例#7
0
文件: if_utun.c 项目: onlynone/xnu
static void
utun_detached(
	ifnet_t	interface)
{
	struct utun_pcb	*pcb = ifnet_softc(interface);
	
	FREE(pcb, M_DEVBUF);
	/* Release reference acquired via ifnet_allocate_extended() */
	(void) ifnet_release(interface);
}
示例#8
0
文件: if_utun.c 项目: Bitesher/xnu
static void
utun_detached(
	ifnet_t	interface)
{
	struct utun_pcb	*pcb = ifnet_softc(interface);
	
	utun_free(pcb);
	
	OSDecrementAtomic(&utun_ifcount);
}
示例#9
0
////////////////////////////////////////////////////////////////////////////////
//
// in_firewire_arp_input
//
// IN: register struct mbuf *m
//
// Invoked by :
// firewire_arpintr calls it from the context of dlil_input_thread queue
//
// ARP for Internet protocols on 10 Mb/s Ethernet.
// Algorithm is that given in RFC 826.
// In addition, a sanity check is performed on the sender
// protocol address, to catch impersonators.
// We no longer handle negotiations for use of trailer protocol:
// Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
// along with IP replies if we wanted trailers sent to us,
// and also sent them in response to IP replies.
// This allowed either end to announce the desire to receive trailer packets.
// We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
// but formerly didn't normally send requests.
//
////////////////////////////////////////////////////////////////////////////////
static void
inet_firewire_arp_input(
    mbuf_t m)
{
    IP1394_ARP *fwa;
    struct sockaddr_dl	sender_hw;
    struct sockaddr_in	sender_ip;
    struct sockaddr_in	target_ip;

    ifnet_t		  ifp		= mbuf_pkthdr_rcvif((mbuf_t)m);

    IOFWInterface *fwIf		= (IOFWInterface*)ifnet_softc(ifp);

    if(fwIf == NULL)
        return;

    IOFireWireIP  *fwIpObj	= (IOFireWireIP*)fwIf->getController();

    if(fwIpObj == NULL)
        return;

    if (mbuf_len(m) < (int)sizeof(IP1394_ARP) &&
            mbuf_pullup(&m, sizeof(IP1394_ARP)) != 0)
        return;

    fwa = (IP1394_ARP*)mbuf_data(m);

    // Verify this is an firewire/ip arp and address lengths are correct
    if (fwa->hardwareType != htons(ARP_HDW_TYPE) || fwa->protocolType != htons(FWTYPE_IP)
            || fwa->hwAddrLen != sizeof(IP1394_HDW_ADDR) || fwa->ipAddrLen != IPV4_ADDR_SIZE)
    {
        mbuf_free(m);
        return;
    }

    bzero(&sender_ip, sizeof(sender_ip));
    sender_ip.sin_len = sizeof(sender_ip);
    sender_ip.sin_family = AF_INET;
    sender_ip.sin_addr.s_addr = fwa->senderIpAddress;
    target_ip = sender_ip;
    target_ip.sin_addr.s_addr = fwa->targetIpAddress;

    bzero(&sender_hw, sizeof(sender_hw));
    sender_hw.sdl_len = sizeof(sender_hw);
    sender_hw.sdl_family = AF_LINK;
    sender_hw.sdl_type = IFT_IEEE1394;
    sender_hw.sdl_alen = FIREWIRE_ADDR_LEN;
    bcopy(&fwa->senderUniqueID, LLADDR(&sender_hw), FIREWIRE_ADDR_LEN);

    if(fwIpObj->arpCacheHandler(fwa))
        inet_arp_handle_input(ifp, ntohs(fwa->opcode), &sender_hw, &sender_ip, &target_ip);

    mbuf_free((mbuf_t)m);
}
示例#10
0
static void
ipsec_detached(
			   ifnet_t	interface)
{
	struct ipsec_pcb	*pcb = ifnet_softc(interface);
    
	ifnet_release(pcb->ipsec_ifp);
	ipsec_free(pcb);
    
	OSDecrementAtomic(&ipsec_ifcount);
}
示例#11
0
文件: if_utun.c 项目: Bitesher/xnu
/* Network Interface functions */
static errno_t
utun_output(
			   ifnet_t	interface,
			   mbuf_t	data)
{
	struct utun_pcb	*pcb = ifnet_softc(interface);
	errno_t			result;
	
	if (m_pktlen(data) >= 4) {
		bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0);
	}
	
	if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) {
		/* flush data */
		mbuf_freem(data);
		return 0;
	}

	// otherwise, fall thru to ctl_enqueumbuf
	if (pcb->utun_ctlref) {
		int	length;

		// only pass packets to utun-crypto if crypto is enabled and 'suspend data traffic' is not.
		if ((pcb->utun_flags & (UTUN_FLAGS_CRYPTO | UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC)) == UTUN_FLAGS_CRYPTO) {
			if (utun_pkt_crypto_output(pcb, &data) == 0) {
				return 0;
			}
		}

		/*
		 * The ABI requires the protocol in network byte order
		 */
		if (m_pktlen(data) >= 4)
			*(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data));

		length = mbuf_pkthdr_len(data);
		result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR);
		if (result != 0) {
			mbuf_freem(data);
			printf("utun_output - ctl_enqueuembuf failed: %d\n", result);

			ifnet_stat_increment_out(interface, 0, 0, 1);
		}
		else {
			if (!pcb->utun_ext_ifdata_stats)
				ifnet_stat_increment_out(interface, 1, length, 0);
		}
	}
	else 
		mbuf_freem(data);
	
	return 0;
}
示例#12
0
文件: if_utun.c 项目: onlynone/xnu
static errno_t
utun_output(ifnet_t	interface,
			mbuf_t data)
{
	struct utun_pcb	*pcb = ifnet_softc(interface);
	errno_t			result;

	VERIFY(interface == pcb->utun_ifp);
	
	if (m_pktlen(data) >= (int32_t)UTUN_HEADER_SIZE(pcb)) {
		bpf_tap_out(pcb->utun_ifp, DLT_NULL, data, 0, 0);
	}
	
	if (pcb->utun_flags & UTUN_FLAGS_NO_OUTPUT) {
		/* flush data */
		mbuf_freem(data);
		return 0;
	}

	// otherwise, fall thru to ctl_enqueumbuf
	if (pcb->utun_ctlref) {
		int	length;

		/*
		 * The ABI requires the protocol in network byte order
		 */
		if (m_pktlen(data) >= (int32_t)UTUN_HEADER_SIZE(pcb)) {
			*(u_int32_t *)mbuf_data(data) = htonl(*(u_int32_t *)mbuf_data(data));
		}

		length = mbuf_pkthdr_len(data);
		result = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, data, CTL_DATA_EOR);
		if (result != 0) {
			mbuf_freem(data);
			printf("utun_output - ctl_enqueuembuf failed: %d\n", result);

			ifnet_stat_increment_out(interface, 0, 0, 1);
		}
		else {
			if (!pcb->utun_ext_ifdata_stats)
				ifnet_stat_increment_out(interface, 1, length, 0);
		}
	}
	else 
		mbuf_freem(data);
	
	return 0;
}
示例#13
0
文件: ppp_ipv6.c 项目: Deanzou/ppp
/* -----------------------------------------------------------------------------
detach the PPPx interface ifp from the network protocol IPv6,
called when the ppp interface stops ip traffic
----------------------------------------------------------------------------- */
void ppp_ipv6_detach(ifnet_t ifp, protocol_family_t protocol)
{
    int 		ret;
    struct ppp_if		*wan = (struct ppp_if *)ifnet_softc(ifp);

    LOGDBG(ifp, ("ppp_ipv6_detach\n"));

    if (!wan->ipv6_attached)
        return;	// already detached

    ret = ifnet_detach_protocol(ifp, PF_INET6);
	if (ret)
        IOLog("ppp_ipv6_detach: ifnet_detach_protocol error = 0x%x\n", ret);

    wan->ipv6_attached = 0;
}
示例#14
0
文件: ppp_ip.c 项目: Deanzou/ppp
/* -----------------------------------------------------------------------------
called from dlil when an ioctl is sent to the interface
----------------------------------------------------------------------------- */
errno_t ppp_ip_ioctl(ifnet_t ifp, protocol_family_t protocol,
									 u_long command, void* argument)
{
    struct ppp_if		*wan = (struct ppp_if *)ifnet_softc(ifp);
    struct sockaddr_in  addr, dstaddr;
    int 		error = 0;
    
    switch (command) {

        case SIOCSIFADDR:
        case SIOCAIFADDR:
            LOGDBG(ifp, ("ppp_ip_ioctl: cmd = SIOCSIFADDR/SIOCAIFADDR\n"));

	    error = ifaddr_address(argument, (struct sockaddr *)&addr, sizeof (addr));
	    if (error != 0) {
                error = EAFNOSUPPORT;
                break;
	    }

            // only an IPv4 address should arrive here
            if (addr.sin_family != AF_INET) {
                error = EAFNOSUPPORT;
                break;
            }

	    error = ifaddr_dstaddress(argument, (struct sockaddr *)&dstaddr, sizeof (dstaddr));
	    if (error != 0) {
                error = EAFNOSUPPORT;
                break;
	    }

            // only an IPv4 address should arrive here
            if (dstaddr.sin_family != AF_INET) {
                error = EAFNOSUPPORT;
                break;
            }

            wan->ip_src.s_addr = addr.sin_addr.s_addr;
            wan->ip_dst.s_addr = dstaddr.sin_addr.s_addr;
            break;

        default :
            error = EOPNOTSUPP;
    }
    
    return error;
}
示例#15
0
文件: ppp_ip.c 项目: Deanzou/ppp
/* -----------------------------------------------------------------------------
Check if the packet is a bootp packet for us
----------------------------------------------------------------------------- */
int ppp_ip_bootp_client_in(ifnet_t ifp, char *pkt)
{
    struct ppp_if	*wan = (struct ppp_if *)ifnet_softc(ifp);
    struct ip 		*ip;
	struct udphdr	udp;
	
    // Wcast-align fixes - use memcmp and memcpy for unaligned accesses
    ip = (struct ip *)(void*)pkt;
    if (!memcmp(&ip->ip_dst.s_addr, &wan->ip_src.s_addr, sizeof(struct in_addr)) && ip->ip_p == IPPROTO_UDP) {
	
		memcpy(&udp, pkt + sizeof(struct ip), sizeof(struct udphdr));
		if (udp.uh_sport == htons(IPPORT_BOOTPS) && udp.uh_dport == htons(IPPORT_BOOTPC)) {
				return 1;
		}
	}

	return 0;
}
示例#16
0
文件: if_utun.c 项目: onlynone/xnu
static errno_t
utun_proto_input(
	ifnet_t	interface,
	protocol_family_t	protocol,
	mbuf_t				m,
	__unused char		*frame_header)
{
	
	// remove protocol family first
	struct utun_pcb	*pcb = ifnet_softc(interface);
	mbuf_adj(m, UTUN_HEADER_SIZE(pcb));
	
	if (proto_input(protocol, m) != 0) {
		m_freem(m);
	}
	
	return 0;
}
示例#17
0
/* Helpers */
int
ipsec_interface_isvalid (ifnet_t interface)
{
    struct ipsec_pcb *pcb = NULL;
    
    if (interface == NULL)
        return 0;
    
    pcb = ifnet_softc(interface);
    
    if (pcb == NULL)
        return 0;
    
    /* When ctl disconnects, ipsec_unit is set to 0 */
    if (pcb->ipsec_unit == 0)
        return 0;
    
    return 1;
}
示例#18
0
void
ipsec_set_pkthdr_for_interface(ifnet_t interface, mbuf_t packet, int family)
{
	if (packet != NULL && interface != NULL) {
		struct ipsec_pcb *pcb = ifnet_softc(interface);
		if (pcb != NULL) {
			/* Set traffic class, set flow */
			m_set_service_class(packet, pcb->ipsec_output_service_class);
			packet->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET;
			packet->m_pkthdr.pkt_flowid = interface->if_flowhash;
			if (family == AF_INET) {
				struct ip *ip = mtod(packet, struct ip *);
				packet->m_pkthdr.pkt_proto = ip->ip_p;
			} else if (family == AF_INET) {
				struct ip6_hdr *ip6 = mtod(packet, struct ip6_hdr *);
				packet->m_pkthdr.pkt_proto = ip6->ip6_nxt;
			}
			packet->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC);
		}
////////////////////////////////////////////////////////////////////////////////
//
// firewire_del_proto
//
// IN: ifnet_t ifp, u_long protocol_family 
// 
// Invoked by : 
//  dlil_detach_protocol calls this funcion
// 
// Release all descriptor entries owned by this ifp/protocol_family (there may be several).
// Setting the type to 0 releases the entry. Eventually we should compact-out
// the unused entries.
//
////////////////////////////////////////////////////////////////////////////////
__private_extern__
int  firewire_del_proto(ifnet_t ifp, protocol_family_t protocol_family)
{
	IOFWInterface					*fwIf		= (IOFWInterface*)ifnet_softc(ifp);

	if(fwIf == NULL)
		return EINVAL;
		
	struct firewire_desc_blk_str	*desc_blk	= (struct firewire_desc_blk_str *)fwIf->getFamilyCookie();

	if (desc_blk == NULL)
		return EINVAL;
		
	int		found = 0;
	
	for (u_long current = desc_blk->n_max_used; current > 0; current--) 
	{
		if (desc_blk->block_ptr[current - 1].protocol_family == protocol_family) 
		{
			found = 1;
			desc_blk->block_ptr[current - 1].type = 0;
			desc_blk->n_used--;
		}
	}
	
	if (desc_blk->n_used == 0) 
	{
		FREE(fwIf->getFamilyCookie(), M_IFADDR);
		fwIf->setFamilyCookie(NULL);
	}
	else 
	{
		/* Decrement n_max_used */
		for (; desc_blk->n_max_used > 0 && desc_blk->block_ptr[desc_blk->n_max_used - 1].type == 0; desc_blk->n_max_used--)
			;
	}
	
	return found;
 }
////////////////////////////////////////////////////////////////////////////////
//
// firewire_add_proto
//
// IN: ifnet_t ifp, u_long protocol_family, struct ddesc_head_str *desc_head
// 
// Invoked by : 
//  dlil_attach_protocol calls this funcion
// 
//
////////////////////////////////////////////////////////////////////////////////
__private_extern__ int
firewire_add_proto_internal(ifnet_t ifp, u_long protocol_family, const struct ifnet_demux_desc	*demux)
{
	IOFWInterface					*fwIf		= (IOFWInterface*)ifnet_softc(ifp);

	if(fwIf == NULL)
		return EINVAL;
	
	struct firewire_desc_blk_str	*desc_blk	= (struct firewire_desc_blk_str *)fwIf->getFamilyCookie();

	struct fw_desc	*ed;
	u_long		   i;
   
	switch (demux->type) 
	{
		case DLIL_DESC_ETYPE2:
			if (demux->datalen != 2) 
				return EINVAL;
			break;

		default:
			return EOPNOTSUPP;
	}

	// Check for case where all of the descriptor blocks are in use
	if (desc_blk == NULL || desc_blk->n_used == desc_blk->n_count) 
	{
		struct firewire_desc_blk_str *tmp;
		u_long	new_count = FIREWIRE_DESC_BLK_SIZE;
		u_long	new_size;
		u_long	old_size = 0;

		i = 0;
		if (desc_blk) 
		{
			new_count += desc_blk->n_count;
			old_size = desc_blk->n_count * sizeof(struct fw_desc) + FIREWIRE_DESC_HEADER_SIZE;
			i = desc_blk->n_used;
		}
		
		new_size = new_count * sizeof(struct fw_desc) + FIREWIRE_DESC_HEADER_SIZE;

		tmp = (struct firewire_desc_blk_str*)_MALLOC(new_size, M_IFADDR, MBUF_WAITOK);
		if (tmp  == 0) 
			return ENOMEM;
		
		bzero(tmp + old_size, new_size - old_size);
		if (desc_blk) 
		{
			bcopy(desc_blk, tmp, old_size);
			FREE(desc_blk, M_IFADDR);
		}
		desc_blk = tmp;
		fwIf->setFamilyCookie(desc_blk);
		desc_blk->n_count = new_count;
	}
	else
	{
		// Find a free entry
		for (i = 0; i < desc_blk->n_count; i++) 
		{
			if (desc_blk->block_ptr[i].type == 0) 
				break;
		}
	}
		
	// Bump n_max_used if appropriate
	if (i + 1 > desc_blk->n_max_used) {
		desc_blk->n_max_used = i + 1;
	}
	
	ed = &desc_blk->block_ptr[i];
	ed->protocol_family = protocol_family;
	ed->data[0] = 0;
	ed->data[1] = 0;
	
	switch (demux->type) {
		case DLIL_DESC_ETYPE2:
			/* 2 byte ethernet raw protocol type is at native_type */
			/* prtocol must be in network byte order */
			ed->type = DLIL_DESC_ETYPE2;
			ed->data[0] = *(u_int16_t*)demux->data;
			break;
	}
    
	desc_blk->n_used++;

    return 0;
} 
示例#21
0
/* Network Interface functions */
static errno_t
ipsec_output(ifnet_t	interface,
             mbuf_t     data)
{
	struct ipsec_pcb	*pcb = ifnet_softc(interface);
    struct ipsec_output_state ipsec_state;
    struct route ro;
    struct route_in6 ro6;
    int	length;
    struct ip *ip;
    struct ip6_hdr *ip6;
    struct ip_out_args ipoa;
    struct ip6_out_args ip6oa;
    int error = 0;
    u_int ip_version = 0;
    uint32_t af;
    int flags = 0;
    struct flowadv *adv = NULL;
    
	// Make sure this packet isn't looping through the interface
	if (necp_get_last_interface_index_from_packet(data) == interface->if_index) {
		error = -1;
		goto ipsec_output_err;
	}
	
	// Mark the interface so NECP can evaluate tunnel policy
	necp_mark_packet_from_interface(data, interface);
	
    ip = mtod(data, struct ip *);
    ip_version = ip->ip_v;
	
    switch (ip_version) {
        case 4:
            /* Tap */
            af = AF_INET;
            bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af));
			
            /* Apply encryption */
            bzero(&ipsec_state, sizeof(ipsec_state));
            ipsec_state.m = data;
            ipsec_state.dst = (struct sockaddr *)&ip->ip_dst;
            bzero(&ipsec_state.ro, sizeof(ipsec_state.ro));
			
			error = ipsec4_interface_output(&ipsec_state, interface);
            data = ipsec_state.m;
            if (error || data == NULL) {
                printf("ipsec_output: ipsec4_output error %d.\n", error);
                goto ipsec_output_err;
            }
            
            /* Set traffic class, set flow */
            m_set_service_class(data, pcb->ipsec_output_service_class);
            data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET;
            data->m_pkthdr.pkt_flowid = interface->if_flowhash;
            data->m_pkthdr.pkt_proto = ip->ip_p;
            data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC);
            
            /* Flip endian-ness for ip_output */
            ip = mtod(data, struct ip *);
            NTOHS(ip->ip_len);
            NTOHS(ip->ip_off);
            
            /* Increment statistics */
            length = mbuf_pkthdr_len(data);
            ifnet_stat_increment_out(interface, 1, length, 0);
			
            /* Send to ip_output */
            bzero(&ro, sizeof(ro));
			
            flags = IP_OUTARGS |	/* Passing out args to specify interface */
			IP_NOIPSEC;				/* To ensure the packet doesn't go through ipsec twice */
			
            bzero(&ipoa, sizeof(ipoa));
            ipoa.ipoa_flowadv.code = 0;
            ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR;
            if (ipsec_state.outgoing_if) {
                ipoa.ipoa_boundif = ipsec_state.outgoing_if;
                ipoa.ipoa_flags |= IPOAF_BOUND_IF;
            }
            
            adv = &ipoa.ipoa_flowadv;
            
            (void) ip_output(data, NULL, &ro, flags, NULL, &ipoa);
            data = NULL;
            
            if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) {
                error = ENOBUFS;
                ifnet_disable_output(interface);
            }
            
            goto done;
        case 6:
            af = AF_INET6;
            bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af));
            
            data = ipsec6_splithdr(data);
            ip6 = mtod(data, struct ip6_hdr *);
			
            bzero(&ipsec_state, sizeof(ipsec_state));
            ipsec_state.m = data;
            ipsec_state.dst = (struct sockaddr *)&ip6->ip6_dst;
            bzero(&ipsec_state.ro, sizeof(ipsec_state.ro));
            
            error = ipsec6_interface_output(&ipsec_state, interface, &ip6->ip6_nxt, ipsec_state.m);
            if (error == 0 && ipsec_state.tunneled == 4)	/* tunneled in IPv4 - packet is gone */
				goto done;
            data = ipsec_state.m;
            if (error || data == NULL) {
                printf("ipsec_output: ipsec6_output error %d.\n", error);
                goto ipsec_output_err;
            }
            
            /* Set traffic class, set flow */
            m_set_service_class(data, pcb->ipsec_output_service_class);
            data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET;
            data->m_pkthdr.pkt_flowid = interface->if_flowhash;
            data->m_pkthdr.pkt_proto = ip6->ip6_nxt;
            data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC);
            
            /* Increment statistics */
            length = mbuf_pkthdr_len(data);
            ifnet_stat_increment_out(interface, 1, length, 0);
            
            /* Send to ip6_output */
            bzero(&ro6, sizeof(ro6));
            
            flags = IPV6_OUTARGS;
            
            bzero(&ip6oa, sizeof(ip6oa));
            ip6oa.ip6oa_flowadv.code = 0;
            ip6oa.ip6oa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR;
            if (ipsec_state.outgoing_if) {
                ip6oa.ip6oa_boundif = ipsec_state.outgoing_if;
                ip6oa.ip6oa_flags |= IPOAF_BOUND_IF;
            }
            
            adv = &ip6oa.ip6oa_flowadv;
            
            (void) ip6_output(data, NULL, &ro6, flags, NULL, NULL, &ip6oa);
            data = NULL;
            
            if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) {
                error = ENOBUFS;
                ifnet_disable_output(interface);
            }
            
            goto done;
        default:
            printf("ipsec_output: Received unknown packet version %d.\n", ip_version);
            error = -1;
            goto ipsec_output_err;
    }
	
done:
    return error;
    
ipsec_output_err:
    if (data)
        mbuf_freem(data);
	goto done;
}
示例#22
0
errno_t
firewire_inet_arp(
    ifnet_t								ifp,
    u_short								arpop,
    const struct sockaddr_dl*			sender_hw,
    const struct sockaddr*				sender_proto,
    const struct sockaddr_dl*			target_hw,
    const struct sockaddr*				target_proto)
{
    mbuf_t	m;
    errno_t	result;
    register struct firewire_header *fwh;
    register IP1394_ARP *fwa;
    const struct sockaddr_in* sender_ip = (const struct sockaddr_in*)sender_proto;
    const struct sockaddr_in* target_ip = (const struct sockaddr_in*)target_proto;
    char *datap;

    IOFWInterface *fwIf	   = (IOFWInterface*)ifnet_softc(ifp);

    if(fwIf == NULL)
        return EINVAL;

    IOFireWireIP  *fwIpObj = (IOFireWireIP*)fwIf->getController();

    if(fwIpObj == NULL)
        return EINVAL;

    LCB	*lcb = fwIpObj->getLcb();

    if (target_ip == NULL)
        return EINVAL;

    if ((sender_ip && sender_ip->sin_family != AF_INET) ||
            (target_ip && target_ip->sin_family != AF_INET))
        return EAFNOSUPPORT;

    result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m);
    if (result != 0)
        return result;

    mbuf_setlen(m, sizeof(*fwa));
    mbuf_pkthdr_setlen(m, sizeof(*fwa));

    /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */
    datap = (char*)mbuf_datastart(m);
    datap += mbuf_trailingspace(m);
    datap -= (((u_long)datap) & 0x3);
    mbuf_setdata(m, datap, sizeof(*fwa));
    fwa = (IP1394_ARP*)mbuf_data(m);
    bzero((caddr_t)fwa, sizeof(*fwa));

    /* Prepend the ethernet header, we will send the raw frame */
    result = mbuf_prepend(&m, sizeof(*fwh), MBUF_DONTWAIT);
    if(result != 0)
        return result;

    fwh = (struct firewire_header*)mbuf_data(m);
    fwh->fw_type = htons(FWTYPE_ARP);

    /* Fill out the arp packet */
    fwa->hardwareType = htons(ARP_HDW_TYPE);
    fwa->protocolType = htons(FWTYPE_IP);
    fwa->hwAddrLen = sizeof(IP1394_HDW_ADDR);
    fwa->ipAddrLen = IPV4_ADDR_SIZE;
    fwa->opcode = htons(arpop);
    fwa->senderMaxRec = lcb->ownHardwareAddress.maxRec;
    fwa->sspd = lcb->ownHardwareAddress.spd;
    fwa->senderUnicastFifoHi = htons(lcb->ownHardwareAddress.unicastFifoHi);
    fwa->senderUnicastFifoLo = htonl(lcb->ownHardwareAddress.unicastFifoLo);

    /* Sender Hardware */
    if (sender_hw != NULL)
        bcopy(CONST_LLADDR(sender_hw), &fwa->senderUniqueID, sizeof(fwa->senderUniqueID));
    else
        ifnet_lladdr_copy_bytes(ifp, &fwa->senderUniqueID, FIREWIRE_ADDR_LEN);

    ifnet_lladdr_copy_bytes(ifp, fwh->fw_shost, sizeof(fwh->fw_shost));

    /* Sender IP */
    if (sender_ip != NULL)
        fwa->senderIpAddress = sender_ip->sin_addr.s_addr;
    else
    {
        ifaddr_t	*addresses;
        struct sockaddr sa;

        if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0)
        {
            ifaddr_address( addresses[0], &sa, 16 );
            fwa->senderIpAddress  = ((UInt32)(sa.sa_data[5] & 0xFF)) << 24;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[4] & 0xFF)) << 16;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[3] & 0xFF)) << 8;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[2] & 0xFF));

            ifnet_free_address_list(addresses);
        }
        else
        {
            mbuf_free(m);
            return ENXIO;
        }
    }

    /* Target Hardware */
    if (target_hw == 0)
        bcopy(fwbroadcastaddr, fwh->fw_dhost, sizeof(fwh->fw_dhost));
    else
        bcopy(CONST_LLADDR(target_hw), fwh->fw_dhost, sizeof(fwh->fw_dhost));

    /* Target IP */
    fwa->targetIpAddress = target_ip->sin_addr.s_addr;

    ifnet_output_raw(ifp, PF_INET, m);

    return 0;
}