FreeBSD/usr.sbin/bluetooth/btpand/bnep.c
/*
 * BNEP send packet routine
 * return true if packet can be removed from queue
 */
BNEP send packet routine
return true if packet can be removed from queue
BNEP send packet routine return true if packet can be removed from queue
bool
bnep_send(channel_t *chan, packet_t *pkt)
{
	struct iovec iov[2];
	uint8_t *p, *type, *proto;
	exthdr_t *eh;
	bool src, dst;
	size_t nw;
	if (pkt->type == NULL) {
		iov[0].iov_base = pkt->ptr;
		iov[0].iov_len = pkt->len;
		iov[1].iov_base = NULL;
		iov[1].iov_len = 0;
	} else {
		p = chan->sendbuf;
		dst = (memcmp(pkt->dst, chan->raddr, ETHER_ADDR_LEN) != 0);
		src = (memcmp(pkt->src, chan->laddr, ETHER_ADDR_LEN) != 0);
		type = p;
		p += 1;
		if (dst && src)
			*type = BNEP_GENERAL_ETHERNET;
		else if (dst && !src)
			*type = BNEP_COMPRESSED_ETHERNET_DST_ONLY;
		else if (!dst && src)
			*type = BNEP_COMPRESSED_ETHERNET_SRC_ONLY;
		else 
			*type = BNEP_COMPRESSED_ETHERNET;
		if (dst) {
			memcpy(p, pkt->dst, ETHER_ADDR_LEN);
			p += ETHER_ADDR_LEN;
		}
		if (src) {
			memcpy(p, pkt->src, ETHER_ADDR_LEN);
			p += ETHER_ADDR_LEN;
		}
		proto = p;
		memcpy(p, pkt->type, ETHER_TYPE_LEN);
		p += ETHER_TYPE_LEN;
		STAILQ_FOREACH(eh, &pkt->extlist, next) {
			if (p + eh->len > chan->sendbuf + chan->mtu)
				break;
			*type |= BNEP_EXT;
			type = p;
			memcpy(p, eh->ptr, eh->len);
			p += eh->len;
		}
		*type &= ~BNEP_EXT;
		iov[0].iov_base = chan->sendbuf;
		iov[0].iov_len = (p - chan->sendbuf);
		if ((chan->npfilter == 0 || bnep_pfilter(chan, pkt))
		    && (chan->nmfilter == 0 || bnep_mfilter(chan, pkt))) {
			iov[1].iov_base = pkt->ptr;
			iov[1].iov_len = pkt->len;
		} else if (be16dec(proto) == ETHERTYPE_VLAN
		    && pkt->len >= ETHER_VLAN_ENCAP_LEN) {
			iov[1].iov_base = pkt->ptr;
			iov[1].iov_len = ETHER_VLAN_ENCAP_LEN;
		} else {
			iov[1].iov_base = NULL;
			iov[1].iov_len = 0;
			memset(proto, 0, ETHER_TYPE_LEN);
		}
	}
	if (iov[0].iov_len + iov[1].iov_len > chan->mtu) {
		log_err("packet exceeded MTU (dropped)");
		return false;
	}
	nw = writev(chan->fd, iov, __arraycount(iov));
	return (nw > 0);
}
bool bnep_send ( channel_t * chan , packet_t * pkt ) { struct iovec iov [ 2 ] ; uint8_t * p , * type , * proto ; exthdr_t * eh ; bool src , dst ; size_t nw ; if ( pkt -> type == NULL ) { iov [ 0 ] . iov_base = pkt -> ptr ; iov [ 0 ] . iov_len = pkt -> len ; iov [ 1 ] . iov_base = NULL ; iov [ 1 ] . iov_len = 0 ; } else { p = chan -> sendbuf ; dst = ( memcmp ( pkt -> dst , chan -> raddr , ETHER_ADDR_LEN ) != 0 ) ; src = ( memcmp ( pkt -> src , chan -> laddr , ETHER_ADDR_LEN ) != 0 ) ; type = p ; p += 1 ; if ( dst && src ) * type = BNEP_GENERAL_ETHERNET ; else if ( dst && ! src ) * type = BNEP_COMPRESSED_ETHERNET_DST_ONLY ; else if ( ! dst && src ) * type = BNEP_COMPRESSED_ETHERNET_SRC_ONLY ; else * type = BNEP_COMPRESSED_ETHERNET ; if ( dst ) { memcpy ( p , pkt -> dst , ETHER_ADDR_LEN ) ; p += ETHER_ADDR_LEN ; } if ( src ) { memcpy ( p , pkt -> src , ETHER_ADDR_LEN ) ; p += ETHER_ADDR_LEN ; } proto = p ; memcpy ( p , pkt -> type , ETHER_TYPE_LEN ) ; p += ETHER_TYPE_LEN ; STAILQ_FOREACH ( eh , & pkt -> extlist , next ) { if ( p + eh -> len > chan -> sendbuf + chan -> mtu ) break ; * type |= BNEP_EXT ; type = p ; memcpy ( p , eh -> ptr , eh -> len ) ; p += eh -> len ; } * type &= ~ BNEP_EXT ; iov [ 0 ] . iov_base = chan -> sendbuf ; iov [ 0 ] . iov_len = ( p - chan -> sendbuf ) ; if ( ( chan -> npfilter == 0 || bnep_pfilter ( chan , pkt ) ) && ( chan -> nmfilter == 0 || bnep_mfilter ( chan , pkt ) ) ) { iov [ 1 ] . iov_base = pkt -> ptr ; iov [ 1 ] . iov_len = pkt -> len ; } else if ( be16dec ( proto ) == ETHERTYPE_VLAN && pkt -> len >= ETHER_VLAN_ENCAP_LEN ) { iov [ 1 ] . iov_base = pkt -> ptr ; iov [ 1 ] . iov_len = ETHER_VLAN_ENCAP_LEN ; } else { iov [ 1 ] . iov_base = NULL ; iov [ 1 ] . iov_len = 0 ; memset ( proto , 0 , ETHER_TYPE_LEN ) ; } } if ( iov [ 0 ] . iov_len + iov [ 1 ] . iov_len > chan -> mtu ) { log_err ( " " ) ; return false ; } nw = writev ( chan -> fd , iov , __arraycount ( iov ) ) ; return ( nw > 0 ) ; }
BNEP send packet routine
 return true if packet can be removed from queue
BNEP send packet routine return true if packet can be removed from queue
/* (!dst && !src) */