Ejemplo n.º 1
0
/*
 * Ethernet output routine.
 * 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.
 */
int
ether_frameout(
	struct ifnet			*ifp,
	struct mbuf				**m,
	const struct sockaddr	*ndest,
	const char				*edst,
	const char				*ether_type)
{
	struct ether_header *eh;
	int hlen;	/* link layer header length */

	hlen = ETHER_HDR_LEN;

	/*
	 * 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 ((ifp->if_flags & IFF_SIMPLEX) &&
	    ((*m)->m_flags & M_LOOP)) {
	    if (lo_ifp) {
            if ((*m)->m_flags & M_BCAST) {
                struct mbuf *n = m_copy(*m, 0, (int)M_COPYALL);
                if (n != NULL)
                    dlil_output(lo_ifp, ndest->sa_family, n, NULL, ndest, 0);
            }
            else {
					if (_ether_cmp(edst, ifnet_lladdr(ifp)) == 0) {
                    dlil_output(lo_ifp, ndest->sa_family, *m, NULL, ndest, 0);
                    return EJUSTRETURN;
                }
            }
	    }
	}
    
	/*
	 * Add local net header.  If no space in first mbuf,
	 * allocate another.
	 */
	M_PREPEND(*m, sizeof (struct ether_header), M_DONTWAIT);
	if (*m == 0) {
	    return (EJUSTRETURN);
	}


	eh = mtod(*m, struct ether_header *);
	(void)memcpy(&eh->ether_type, ether_type,
		sizeof(eh->ether_type));
 	(void)memcpy(eh->ether_dhost, edst, ETHER_ADDR_LEN);
 	ifnet_lladdr_copy_bytes(ifp, eh->ether_shost, ETHER_ADDR_LEN);

	return 0;
}
Ejemplo n.º 2
0
Archivo: in_dhcp.c Proyecto: Prajna/xnu
/*
 * Function: send_packet
 * Purpose:
 *     Send the request directly on the interface, bypassing the routing code.
 */
static int
send_packet(struct ifnet * ifp, struct dhcp_packet * pkt, int pkt_size)
{
    struct mbuf	*	m;
    struct sockaddr_in	dest;
    
    dest = blank_sin;
    dest.sin_port = htons(IPPORT_BOOTPS);
    dest.sin_addr.s_addr = INADDR_BROADCAST;
    m = ip_pkt_to_mbuf((caddr_t)pkt, pkt_size);
    return dlil_output(ifp, PF_INET, m, 0, (struct sockaddr *)&dest, 0);
}
Ejemplo n.º 3
0
Archivo: bpf.c Proyecto: SbIm/xnu-env
int
bpfwrite(dev_t dev, struct uio *uio, __unused int ioflag)
{
	struct bpf_d *d;
	struct ifnet *ifp;
	struct mbuf *m = NULL;
	int error;
	char 		  dst_buf[SOCKADDR_HDR_LEN + MAX_DATALINK_HDR_LEN];
	int datlen = 0;

	lck_mtx_lock(bpf_mlock);

	d = bpf_dtab[minor(dev)];
	if (d == 0 || d == (void *)1) {
		lck_mtx_unlock(bpf_mlock);
		return (ENXIO);
	}
	if (d->bd_bif == 0) {
		lck_mtx_unlock(bpf_mlock);
		return (ENXIO);
	}

	ifp = d->bd_bif->bif_ifp;

	if (uio_resid(uio) == 0) {
		lck_mtx_unlock(bpf_mlock);
		return (0);
	}
	((struct sockaddr *)dst_buf)->sa_len = sizeof(dst_buf);
	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, 
			   d->bd_hdrcmplt ? NULL : (struct sockaddr *)dst_buf,
			   &datlen);
	if (error) {
		lck_mtx_unlock(bpf_mlock);
		return (error);
	}

	if ((unsigned)datlen > ifp->if_mtu) {
		lck_mtx_unlock(bpf_mlock);
		m_freem(m);
		return (EMSGSIZE);
	}
	
	if ((error = ifp_use(ifp, kIfNetUseCount_MustNotBeZero)) != 0) {
		lck_mtx_unlock(bpf_mlock);
		m_freem(m);
		return (error);
	}

#if CONFIG_MACF_NET
	mac_mbuf_label_associate_bpfdesc(d, m);
#endif
	lck_mtx_unlock(bpf_mlock);

	if (d->bd_hdrcmplt) {
		if (d->bd_bif->bif_send)
			error = d->bd_bif->bif_send(ifp, d->bd_bif->bif_dlt, m);
		else
			error = dlil_output(ifp, 0, m, NULL, NULL, 1);
	}
	else {
		error = dlil_output(ifp, PF_INET, m, NULL, (struct sockaddr *)dst_buf, 0);
	}
	
	if (ifp_unuse(ifp) != 0)
		ifp_use_reached_zero(ifp);
	
	/*
	 * The driver frees the mbuf.
	 */
	return (error);
}