Ejemplo n.º 1
0
Archivo: ndp.c Proyecto: stefanct/ipxe
/**
 * Transmit NDP neighbour solicitation/advertisement packet
 *
 * @v netdev		Network device
 * @v sin6_src		Source socket address
 * @v sin6_dest		Destination socket address
 * @v target		Neighbour target address
 * @v icmp_type		ICMPv6 type
 * @v flags		NDP flags
 * @v option_type	NDP option type
 * @ret rc		Return status code
 */
static int ndp_tx_neighbour ( struct net_device *netdev,
			      struct sockaddr_in6 *sin6_src,
			      struct sockaddr_in6 *sin6_dest,
			      const struct in6_addr *target,
			      unsigned int icmp_type,
			      unsigned int flags,
			      unsigned int option_type ) {
	struct sockaddr_tcpip *st_src =
		( ( struct sockaddr_tcpip * ) sin6_src );
	struct sockaddr_tcpip *st_dest =
		( ( struct sockaddr_tcpip * ) sin6_dest );
	struct ll_protocol *ll_protocol = netdev->ll_protocol;
	struct io_buffer *iobuf;
	struct ndp_neighbour_header *neigh;
	struct ndp_ll_addr_option *ll_addr_opt;
	size_t option_len;
	size_t len;
	int rc;

	/* Allocate and populate buffer */
	option_len = ( ( sizeof ( *ll_addr_opt ) +
			 ll_protocol->ll_addr_len + NDP_OPTION_BLKSZ - 1 ) &
		       ~( NDP_OPTION_BLKSZ - 1 ) );
	len = ( sizeof ( *neigh ) + option_len );
	iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len );
	if ( ! iobuf )
		return -ENOMEM;
	iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
	neigh = iob_put ( iobuf, len );
	memset ( neigh, 0, len );
	neigh->icmp.type = icmp_type;
	neigh->flags = flags;
	memcpy ( &neigh->target, target, sizeof ( neigh->target ) );
	ll_addr_opt = &neigh->option[0].ll_addr;
	ll_addr_opt->header.type = option_type;
	ll_addr_opt->header.blocks = ( option_len / NDP_OPTION_BLKSZ );
	memcpy ( ll_addr_opt->ll_addr, netdev->ll_addr,
		 ll_protocol->ll_addr_len );
	neigh->icmp.chksum = tcpip_chksum ( neigh, len );

	/* Transmit packet */
	if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
			       netdev, &neigh->icmp.chksum ) ) != 0 ) {
		DBGC ( netdev, "NDP could not transmit packet: %s\n",
		       strerror ( rc ) );
		return rc;
	}

	return 0;
}
Ejemplo n.º 2
0
Archivo: gdbudp.c Proyecto: 3a9LL/panda
static void gdbudp_send ( const char *buf, size_t len ) {
	struct io_buffer *iob;
	struct ethhdr *ethhdr;
	struct iphdr *iphdr;
	struct udp_header *udphdr;

	/* Check that we are connected */
	if ( dest_addr.sin_port == 0 ) {
		return;
	}

	gdbudp_ensure_netdev_open ( netdev );

	iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
	if ( !iob ) {
		return;
	}

	/* Payload */
	iob_reserve ( iob, sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) );
	memcpy ( iob_put ( iob, len ), buf, len );

	/* UDP header */
	udphdr = iob_push ( iob, sizeof ( *udphdr ) );
	udphdr->src = source_addr.sin_port;
	udphdr->dest = dest_addr.sin_port;
	udphdr->len = htons ( iob_len ( iob ) );
	udphdr->chksum = 0; /* optional and we are not using it */

	/* IP header */
	iphdr = iob_push ( iob, sizeof ( *iphdr ) );
	memset ( iphdr, 0, sizeof ( *iphdr ) );
	iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
	iphdr->service = IP_TOS;
	iphdr->len = htons ( iob_len ( iob ) );	
	iphdr->ttl = IP_TTL;
	iphdr->protocol = IP_UDP;
	iphdr->dest.s_addr = dest_addr.sin_addr.s_addr;
	iphdr->src.s_addr = source_addr.sin_addr.s_addr;
	iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );

	/* Ethernet header */
	ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
	memcpy ( ethhdr->h_dest, dest_eth, ETH_ALEN );
	memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
	ethhdr->h_protocol = htons ( ETH_P_IP );

	netdev_tx ( netdev, iob );
}
Ejemplo n.º 3
0
/**
 * Transmit NDP packet with link-layer address option
 *
 * @v netdev		Network device
 * @v sin6_src		Source socket address
 * @v sin6_dest		Destination socket address
 * @v data		NDP header
 * @v len		Size of NDP header
 * @v option_type	NDP option type
 * @ret rc		Return status code
 */
static int ndp_tx_ll_addr ( struct net_device *netdev,
			    struct sockaddr_in6 *sin6_src,
			    struct sockaddr_in6 *sin6_dest,
			    const void *data, size_t len,
			    unsigned int option_type ) {
	struct sockaddr_tcpip *st_src =
		( ( struct sockaddr_tcpip * ) sin6_src );
	struct sockaddr_tcpip *st_dest =
		( ( struct sockaddr_tcpip * ) sin6_dest );
	struct ll_protocol *ll_protocol = netdev->ll_protocol;
	struct io_buffer *iobuf;
	struct ndp_ll_addr_option *ll_addr_opt;
	union ndp_header *ndp;
	size_t option_len;
	int rc;

	/* Allocate and populate buffer */
	option_len = ( ( sizeof ( *ll_addr_opt ) +
			 ll_protocol->ll_addr_len + NDP_OPTION_BLKSZ - 1 ) &
		       ~( NDP_OPTION_BLKSZ - 1 ) );
	iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len + option_len );
	if ( ! iobuf )
		return -ENOMEM;
	iob_reserve ( iobuf, MAX_LL_NET_HEADER_LEN );
	memcpy ( iob_put ( iobuf, len ), data, len );
	ll_addr_opt = iob_put ( iobuf, option_len );
	ll_addr_opt->header.type = option_type;
	ll_addr_opt->header.blocks = ( option_len / NDP_OPTION_BLKSZ );
	memcpy ( ll_addr_opt->ll_addr, netdev->ll_addr,
		 ll_protocol->ll_addr_len );
	ndp = iobuf->data;
	ndp->icmp.chksum = tcpip_chksum ( ndp, ( len + option_len ) );

	/* Transmit packet */
	if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
			       netdev, &ndp->icmp.chksum ) ) != 0 ) {
		DBGC ( netdev, "NDP could not transmit packet: %s\n",
		       strerror ( rc ) );
		return rc;
	}

	return 0;
}