static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
{
	__be32 paddr = skb_rtable(skb)->rt_gateway;
        struct ddpehdr *ddp;
        struct ipddp_route *rt;
        struct atalk_addr *our_addr;

	spin_lock(&ipddp_route_lock);

        for(rt = ipddp_route_list; rt != NULL; rt = rt->next)
        {
                if(rt->ip == paddr)
                        break;
        }
        if(rt == NULL) {
		spin_unlock(&ipddp_route_lock);
                return NETDEV_TX_OK;
	}

        our_addr = atalk_find_dev_addr(rt->dev);

	if(ipddp_mode == IPDDP_DECAP)
		skb_pull(skb, 35-(sizeof(struct ddpehdr)+1));

	
	ddp = (struct ddpehdr *)skb->data;
        ddp->deh_len_hops = htons(skb->len + (1<<10));
        ddp->deh_sum = 0;

        if(rt->dev->type == ARPHRD_LOCALTLK)
        {
                ddp->deh_dnet  = 0;   
                ddp->deh_snet  = 0;
        }
        else
        {
                ddp->deh_dnet  = rt->at.s_net;   
                ddp->deh_snet  = our_addr->s_net;
        }
        ddp->deh_dnode = rt->at.s_node;
        ddp->deh_snode = our_addr->s_node;
        ddp->deh_dport = 72;
        ddp->deh_sport = 72;

        *((__u8 *)(ddp+1)) = 22;        	

        skb->protocol = htons(ETH_P_ATALK);     

	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;

	aarp_send_ddp(rt->dev, skb, &rt->at, NULL);

	spin_unlock(&ipddp_route_lock);

        return NETDEV_TX_OK;
}
Example #2
0
/*
 *	Send an aarp queue entry request
 *
 *	Must run under aarp_lock.
 */
static void __aarp_send_query(struct aarp_entry *a)
{
	static unsigned char aarp_eth_multicast[ETH_ALEN] =
					{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
	struct net_device *dev = a->dev;
	struct elapaarp *eah;
	int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length;
	struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
	struct atalk_addr *sat = atalk_find_dev_addr(dev);

	if (!skb)
		return;

	if (!sat) {
		kfree_skb(skb);
		return;
	}

	/* Set up the buffer */
	skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
	skb_reset_network_header(skb);
	skb_reset_transport_header(skb);
	skb_put(skb, sizeof(*eah));
	skb->protocol    = htons(ETH_P_ATALK);
	skb->dev	 = dev;
	eah		 = aarp_hdr(skb);

	/* Set up the ARP */
	eah->hw_type	 = htons(AARP_HW_TYPE_ETHERNET);
	eah->pa_type	 = htons(ETH_P_ATALK);
	eah->hw_len	 = ETH_ALEN;
	eah->pa_len	 = AARP_PA_ALEN;
	eah->function	 = htons(AARP_REQUEST);

	memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);

	eah->pa_src_zero = 0;
	eah->pa_src_net	 = sat->s_net;
	eah->pa_src_node = sat->s_node;

	memset(eah->hw_dst, '\0', ETH_ALEN);

	eah->pa_dst_zero = 0;
	eah->pa_dst_net	 = a->target_addr.s_net;
	eah->pa_dst_node = a->target_addr.s_node;

	/* Send it */
	aarp_dl->request(aarp_dl, skb, aarp_eth_multicast);
	/* Update the sending count */
	a->xmit_count++;
	a->last_sent = jiffies;
}
static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
{
	__be32 paddr = skb_rtable(skb)->rt_gateway;
        struct ddpehdr *ddp;
        struct ipddp_route *rt;
        struct atalk_addr *our_addr;

	spin_lock(&ipddp_route_lock);

	/*
         * Find appropriate route to use, based only on IP number.
         */
        for(rt = ipddp_route_list; rt != NULL; rt = rt->next)
        {
                if(rt->ip == paddr)
                        break;
        }
        if(rt == NULL) {
		spin_unlock(&ipddp_route_lock);
                return NETDEV_TX_OK;
	}

        our_addr = atalk_find_dev_addr(rt->dev);

	if(ipddp_mode == IPDDP_DECAP)
		/* 
		 * Pull off the excess room that should not be there.
		 * This is due to a hard-header problem. This is the
		 * quick fix for now though, till it breaks.
		 */
		skb_pull(skb, 35-(sizeof(struct ddpehdr)+1));

	/* Create the Extended DDP header */
	ddp = (struct ddpehdr *)skb->data;
        ddp->deh_len_hops = htons(skb->len + (1<<10));
        ddp->deh_sum = 0;

	/*
         * For Localtalk we need aarp_send_ddp to strip the
         * long DDP header and place a shot DDP header on it.
         */
        if(rt->dev->type == ARPHRD_LOCALTLK)
        {
                ddp->deh_dnet  = 0;   /* FIXME more hops?? */
                ddp->deh_snet  = 0;
        }
        else
        {
                ddp->deh_dnet  = rt->at.s_net;   /* FIXME more hops?? */
                ddp->deh_snet  = our_addr->s_net;
        }
        ddp->deh_dnode = rt->at.s_node;
        ddp->deh_snode = our_addr->s_node;
        ddp->deh_dport = 72;
        ddp->deh_sport = 72;

        *((__u8 *)(ddp+1)) = 22;        	/* ddp type = IP */

        skb->protocol = htons(ETH_P_ATALK);     /* Protocol has changed */

	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;

	aarp_send_ddp(rt->dev, skb, &rt->at, NULL);

	spin_unlock(&ipddp_route_lock);

        return NETDEV_TX_OK;
}
Example #4
0
/*
 * Transmit LLAP/ELAP frame using aarp_send_ddp.
 */
static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
{
    u32 paddr = ((struct rtable*)skb->dst)->rt_gateway;
    struct ddpehdr *ddp;
    struct ipddp_route *rt;
    struct atalk_addr *our_addr;

    /*
         * Find appropriate route to use, based only on IP number.
         */
    for(rt = ipddp_route_list; rt != NULL; rt = rt->next)
    {
        if(rt->ip == paddr)
            break;
    }
    if(rt == NULL)
        return 0;

    our_addr = atalk_find_dev_addr(rt->dev);

    if(ipddp_mode == IPDDP_DECAP)
        /*
         * Pull off the excess room that should not be there.
         * This is due to a hard-header problem. This is the
         * quick fix for now though, till it breaks.
         */
        skb_pull(skb, 35-(sizeof(struct ddpehdr)+1));

    /* Create the Extended DDP header */
    ddp = (struct ddpehdr *)skb->data;
    ddp->deh_len = skb->len;
    ddp->deh_hops = 1;
    ddp->deh_pad = 0;
    ddp->deh_sum = 0;

    /*
         * For Localtalk we need aarp_send_ddp to strip the
         * long DDP header and place a shot DDP header on it.
         */
    if(rt->dev->type == ARPHRD_LOCALTLK)
    {
        ddp->deh_dnet  = 0;   /* FIXME more hops?? */
        ddp->deh_snet  = 0;
    }
    else
    {
        ddp->deh_dnet  = rt->at.s_net;   /* FIXME more hops?? */
        ddp->deh_snet  = our_addr->s_net;
    }
    ddp->deh_dnode = rt->at.s_node;
    ddp->deh_snode = our_addr->s_node;
    ddp->deh_dport = 72;
    ddp->deh_sport = 72;

    *((__u8 *)(ddp+1)) = 22;        	/* ddp type = IP */
    *((__u16 *)ddp)=ntohs(*((__u16 *)ddp));	/* fix up length field */

    skb->protocol = htons(ETH_P_ATALK);     /* Protocol has changed */

    ((struct net_device_stats *) dev->priv)->tx_packets++;
    ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len;

    if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
        dev_kfree_skb(skb);

    return 0;
}
Example #5
0
static void aarp_send_query(struct aarp_entry *a)
{
	static char aarp_eth_multicast[ETH_ALEN]={ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
	struct device *dev=a->dev;
	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
	struct elapaarp *eah;
	struct at_addr *sat=atalk_find_dev_addr(dev);
	
	if(skb==NULL || sat==NULL)
		return;
	
	/*
	 *	Set up the buffer.
	 */		

	skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
	eah		=	(struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
	skb->protocol   =       htons(ETH_P_ATALK);
	skb->nh.raw     =       skb->h.raw = (void *) eah;
	skb->dev	=	dev;
	
	/*
	 *	Set up the ARP.
	 */
	 
	eah->hw_type	=	htons(AARP_HW_TYPE_ETHERNET);
	eah->pa_type	=	htons(ETH_P_ATALK);
	eah->hw_len	=	ETH_ALEN;	
	eah->pa_len	=	AARP_PA_ALEN;
	eah->function	=	htons(AARP_REQUEST);
	
	memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
	
	eah->pa_src_zero=	0;
	eah->pa_src_net	=	sat->s_net;
	eah->pa_src_node=	sat->s_node;
	
	memset(eah->hw_dst, '\0', ETH_ALEN);
	
	eah->pa_dst_zero=	0;
	eah->pa_dst_net	=	a->target_addr.s_net;
	eah->pa_dst_node=	a->target_addr.s_node;
	
	/*
	 *	Add ELAP headers and set target to the AARP multicast.
	 */
	 
	aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);	

	/*
	 *	Send it.
	 */	
	
	dev_queue_xmit(skb);
	
	/*
	 *	Update the sending count
	 */
	 
	a->xmit_count++;
}