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; }
/* * 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; }
/* * 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; }
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++; }