int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) { struct arp *arp; struct arp_table *tbl; int ret; PRINTK ("<<\n"); arp = skb->h.arp; print_arp(arp); /* if this test doesn't pass, something fishy is going on. */ if (arp->hlen != dev->addr_len || dev->type !=NET16( arp->hrd)) { free_skb(skb, FREE_READ); return (0); } /* for now we will only deal with ip addresses. */ if (arp->pro != NET16(ARP_IP_PROT) || arp->plen != 4) { free_skb (skb, FREE_READ); return (0); } /* now look up the ip address in the table. */ tbl = arp_lookup (*arp_sourcep(arp)); if (tbl != NULL) { memcpy (tbl->hard, arp+1, arp->hlen); tbl->hlen = arp->hlen; tbl->last_used = timer_seq; } if (!my_ip_addr(*arp_targetp(arp))) { free_skb (skb, FREE_READ); return (0); } if (tbl == NULL) create_arp (*arp_sourcep(arp), arp_sourceh(arp), arp->hlen); /* now see if we can send anything. */ send_arp_q(); if (arp->op != NET16(ARP_REQUEST)) { free_skb (skb, FREE_READ); return (0); } /* now we need to create a new packet. */ ret = arp_response(arp, dev); free_skb (skb, FREE_READ); return (ret); }
void arp_snd (unsigned long paddr, struct device *dev, unsigned long saddr) { struct sk_buff *skb; struct arp *arp; struct arp_table *apt; int tmp; PRINTK ("arp_snd (paddr=%X, dev=%X, saddr=%X)\n",paddr, dev, saddr); /* first we build a dummy arp table entry. */ apt = create_arp (paddr, NULL, 0); if (apt == NULL) return; skb = arp_malloc (sizeof (*arp) + sizeof (*skb) + dev->hard_header_len + 2*dev->addr_len+8); if (skb == NULL) return; skb->sk = NULL; skb->mem_addr = skb; skb->mem_len = sizeof (*arp) + sizeof (*skb) + dev->hard_header_len + 2*dev->addr_len+8; skb->arp = 1; skb->dev = dev; skb->len = sizeof (*arp) + dev->hard_header_len + 2*dev->addr_len+8; skb->next = NULL; tmp = dev->hard_header ((unsigned char *)(skb+1), dev, ETHERTYPE_ARP, 0, saddr, skb->len); if (tmp < 0) { arp_free (skb->mem_addr, skb->mem_len); return; } arp =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp ); arp->hrd = net16(dev->type); arp->pro = NET16(ARP_IP_PROT); arp->hlen = dev->addr_len; arp->plen = 4; arp->op = NET16(ARP_REQUEST); *arp_sourcep(arp) = saddr; *arp_targetp(arp) = paddr; memcpy (arp_sourceh(arp), dev->dev_addr, dev->addr_len); memcpy (arp_targeth(arp), dev->broadcast, dev->addr_len); PRINTK(">>\n"); print_arp(arp); dev->queue_xmit (skb, dev, 0); }
static int arp_response (struct arp *arp1, struct device *dev) { struct arp *arp2; struct sk_buff *skb; int tmp; /* get some mem and initialize it for the return trip. */ skb = arp_malloc (sizeof (*skb) + sizeof (*arp2) + 2*arp1->hlen + 2*arp1->plen + dev->hard_header_len); if (skb == NULL) return (1); skb->mem_addr = skb; skb->mem_len = sizeof (*skb) + sizeof (*arp2) + 2*arp1->hlen + 2*arp1->plen + dev->hard_header_len; skb->len = sizeof (*arp2) + 2*arp1->hlen + 2*arp1->plen + dev->hard_header_len; tmp = dev->hard_header((unsigned char *)(skb+1), dev, ETHERTYPE_ARP, *arp_sourcep(arp1), *arp_targetp(arp1),skb->len); if (tmp < 0) return (1); arp2 =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp ); memcpy (arp2, arp1, sizeof (*arp2)); /* now swap the addresses. */ *arp_sourcep(arp2) = *arp_targetp(arp1); memcpy(arp_sourceh(arp2), dev->dev_addr, arp1->hlen); *arp_targetp(arp2) = *arp_sourcep(arp1); memcpy(arp_targeth(arp2), arp_sourceh(arp1), arp1->hlen); arp2->op = NET16(ARP_REPLY); skb->free = 1; skb->arp = 1; /* so the code will know it's not waiting on an arp. */ skb->sk = NULL; skb->next = NULL; PRINTK (">>"); print_arp(arp2); /* send it. */ dev->queue_xmit (skb, dev, 0); return (0); }
* * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 * Changed malloc to kmalloc and added Id and Log * */ #include <linux/stddef.h> #include "dev.h" #include "eth.h" extern int arp_rcv (struct sk_buff *skb, struct device *dev, struct packet_type *pt); static struct packet_type arp_packet_type= { NET16(ETHERTYPE_ARP), 0, /* copy */ arp_rcv, NULL, NULL /* next */ }; extern int ip_rcv (struct sk_buff *skb, struct device *dev, struct packet_type *pt); static struct packet_type ip_packet_type= { NET16(ETHERTYPE_IP), 0, /* copy */ ip_rcv, NULL,