⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 3 页
字号:
328   arp2->ar_hrd = arp1->ar_hrd;
329   arp2->ar_pro = arp1->ar_pro;
330   arp2->ar_hln = arp1->ar_hln;
331   arp2->ar_pln = arp1->ar_pln;
332   arp2->ar_op = htons(ARPOP_REPLY);
333   if(addrtype==IS_MYADDR)
334           memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
335   else          /* Proxy arp, so pull from the table */
336           memcpy(ptr2, apt->ha, arp2->ar_hln);
337   ptr2 += arp2->ar_hln;
338   memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
339   ptr2 += arp2->ar_pln;
340   memcpy(ptr2, ptr1, arp2->ar_hln);
341   ptr2 += arp2->ar_hln;
342   memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
343 
344   skb->free = 1;
345   skb->arp = 1;
346   skb->sk = NULL;
347   skb->next = NULL;
348 
349   DPRINTF((DBG_ARP, ">>"));
350   arp_print(arp2);
351 
352   /* Queue the packet for transmission. */
353   dev->queue_xmit(skb, dev, 0);
354   return(0);
355 }
356 
357 
358 /* This will find an entry in the ARP table by looking at the IP address. */
359 static struct arp_table *
360 arp_lookup(unsigned long paddr)
361 {
362   struct arp_table *apt;
363   unsigned long hash;
364 
365   DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
366 
367   /* We don't want to ARP ourselves. */
368   if (chk_addr(paddr) == IS_MYADDR) {
369         printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
370         return(NULL);
371   }
372 
373   /* Loop through the table for the desired address. */
374   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
375   cli();
376   apt = arp_tables[hash];
377   while(apt != NULL) {
378         if (apt->ip == paddr) {
379                 sti();
380                 return(apt);
381         }
382         apt = apt->next;
383   }
384   sti();
385   return(NULL);
386 }
387 
388 
389 /* This will find a proxy in the ARP table by looking at the IP address. */
390 static struct arp_table *arp_lookup_proxy(unsigned long paddr)
391 {
392   struct arp_table *apt;
393   unsigned long hash;
394 
395   DPRINTF((DBG_ARP, "ARP: lookup proxy(%s)\n", in_ntoa(paddr)));
396 
397   /* Loop through the table for the desired address. */
398   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
399   cli();
400   apt = arp_tables[hash];
401   while(apt != NULL) {
402         if (apt->ip == paddr && (apt->flags & ATF_PUBL) ) {
403                 sti();
404                 return(apt);
405         }
406         apt = apt->next;
407   }
408   sti();
409   return(NULL);
410 }
411 
412 
413 /* Delete an ARP mapping entry in the cache. */
414 void
415 arp_destructor(unsigned long paddr, int force)
416 {
417   struct arp_table *apt;
418   struct arp_table **lapt;
419   unsigned long hash;
420 
421   DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
422 
423   /* We cannot destroy our own ARP entry. */
424   if (chk_addr(paddr) == IS_MYADDR) {
425         DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
426                                                         in_ntoa(paddr)));
427         return;
428   }
429   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
430 
431   cli();
432   lapt = &arp_tables[hash];
433   while ((apt = *lapt) != NULL) {
434         if (apt->ip == paddr) {
435                 if((apt->flags&ATF_PERM) && !force)
436                         return;
437                 *lapt = apt->next;
438                 if(apt->flags&ATF_PUBL)
439                         arp_proxies--;                  
440                 kfree_s(apt, sizeof(struct arp_table));
441                 sti();
442                 return;
443         }
444         lapt = &apt->next;
445   }
446   sti();
447 }
448 
449 /*
450  *      Kill an entry - eg for ioctl()
451  */
452 
453 void arp_destroy(unsigned long paddr)
454 {       
455         arp_destructor(paddr,1);
456 }
457 
458 /*
459  *      Delete a possibly invalid entry (see timer.c)
460  */
461 
462 void arp_destroy_maybe(unsigned long paddr)
463 {
464         arp_destructor(paddr,0);
465 }
466 
467 /* Create an ARP entry.  The caller should check for duplicates! */
468 static struct arp_table *
469 arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
470 {
471   struct arp_table *apt;
472   unsigned long hash;
473 
474   DPRINTF((DBG_ARP, "ARP: create(%s, ", in_ntoa(paddr)));
475   DPRINTF((DBG_ARP, "%s, ", eth_print(addr)));
476   DPRINTF((DBG_ARP, "%d, %d)\n", hlen, htype));
477 
478   apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
479   if (apt == NULL) {
480         printk("ARP: no memory available for new ARP entry!\n");
481         return(NULL);
482   }
483 
484   /* Fill in the allocated ARP cache entry. */
485   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
486   apt->ip = paddr;
487   apt->hlen = hlen;
488   apt->htype = htype;
489   apt->flags = (ATF_INUSE | ATF_COM);           /* USED and COMPLETED entry */
490   memcpy(apt->ha, addr, hlen);
491   apt->last_used = jiffies;
492   cli();
493   apt->next = arp_tables[hash];
494   arp_tables[hash] = apt;
495   sti();
496   return(apt);
497 }
498 
499 
500 /*
501  * An ARP REQUEST packet has arrived.
502  * We try to be smart here, and fetch the data of the sender of the
503  * packet- we might need it later, so fetching it now can save us a
504  * broadcast later.
505  * Then, if the packet was meant for us (i.e. the TARGET address was
506  * one of our own IP addresses), we set up and send out an ARP REPLY
507  * packet to the sender.
508  */
509 int
510 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
511 {
512   struct arphdr *arp;
513   struct arp_table *tbl;
514   unsigned long src, dst;
515   unsigned char *ptr;
516   int ret;
517   int addr_hint;
518 
519   DPRINTF((DBG_ARP, "<<\n"));
520   arp = skb->h.arp;
521   arp_print(arp);
522 
523   /* If this test doesn't pass, its not IP. Might be DECNET or friends */
524   if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd)) 
525   {
526         DPRINTF((DBG_ARP,"ARP: Bad packet received on device \"%s\" !\n", dev->name));
527         kfree_skb(skb, FREE_READ);
528         return(0);
529   }
530 
531   /* For now we will only deal with IP addresses. */
532   if (((arp->ar_pro != NET16(0x00CC) && dev->type==3) || (arp->ar_pro != NET16(ETH_P_IP) && dev->type!=3) ) || arp->ar_pln != 4) 
533   {
534         if (arp->ar_op != NET16(ARPOP_REQUEST))
535                 DPRINTF((DBG_ARP,"ARP: Non-IP request on device \"%s\" !\n", dev->name));
536         kfree_skb(skb, FREE_READ);
537         return(0);
538   }
539 
540   /*
541    * As said before, we try to be smart by using the
542    * info already present in the packet: the sender's
543    * IP and hardware address.
544    */
545   ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
546   memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
547   tbl = arp_lookup(src);
548   if (tbl != NULL) {
549         DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
550         memcpy(tbl->ha, ptr, arp->ar_hln);
551         tbl->hlen = arp->ar_hln;
552         tbl->flags |= ATF_COM;
553         tbl->last_used = jiffies;
554   } else {
555         memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
556         if (chk_addr(dst) != IS_MYADDR && arp_proxies == 0) {
557                 kfree_skb(skb, FREE_READ);
558                 return(0);
559         } else {
560                 tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
561                 if (tbl == NULL) {
562                         kfree_skb(skb, FREE_READ);
563                         return(0);
564                 }
565         }
566   }
567 
568   /*
569    * Since we updated the ARP cache, we might have enough
570    * information to send out some previously queued IP
571    * datagrams....
572    */
573   arp_send_q();
574 
575   /*
576    * OK, we used that part of the info.  Now check if the
577    * request was an ARP REQUEST for one of our own addresses..
578    */
579   if (arp->ar_op != NET16(ARPOP_REQUEST)) {
580         kfree_skb(skb, FREE_READ);
581         return(0);
582   }
583 
584 /*
585  * A broadcast arp, ignore it
586  */
587 
588   if(chk_addr(dst)==IS_BROADCAST)
589   {
590         kfree_skb(skb, FREE_READ);
591         return 0;
592   }
593   
594   memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
595   if ((addr_hint=chk_addr(dst)) != IS_MYADDR && arp_proxies==0) {
596         DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
597         kfree_skb(skb, FREE_READ);
598         return(0);
599   }
600 
601   /*
602    * Yes, it is for us.
603    * Allocate, fill in and send an ARP REPLY packet.
604    */
605   ret = arp_response(arp, dev, addr_hint);
606   kfree_skb(skb, FREE_READ);
607   return(ret);
608 }
609 
610 
611 /* Create and send an ARP REQUEST packet. */
612 void
613 arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
614 {
615   struct sk_buff *skb;
616   struct arphdr *arp;
617   unsigned char *ptr;
618   int tmp;
619 
620   DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
621   DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
622   DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
623 
624   skb = alloc_skb(sizeof(struct sk_buff) +
625                 sizeof(struct arphdr) + (2 * dev->addr_len) +
626                 dev->hard_header_len +
627                 (2 * 4 /* arp->plen */), GFP_ATOMIC);
628   if (skb == NULL) {
629         printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
630         return;
631   }
632   
633   /* Fill in the request. */
634   skb->sk = NULL;
635   skb->mem_addr = skb;
636   skb->len = sizeof(struct arphdr) +
637              dev->hard_header_len + (2 * dev->addr_len) + 8;
638   skb->mem_len = sizeof(struct sk_buff) + skb->len;
639   skb->arp = 1;
640   skb->dev = dev;
641   skb->next = NULL;
642   skb->free = 1;
643   tmp = dev->hard_header(skb->data, dev, ETH_P_ARP, 0, saddr, skb->len);
644   if (tmp < 0) {
645         kfree_skb(skb,FREE_WRITE);
646         return;
647   }
648   arp = (struct arphdr *) (skb->data + tmp);
649   arp->ar_hrd = htons(dev->type);
650   if(dev->type!=3)      /* AX.25 */
651         arp->ar_pro = htons(ETH_P_IP);
652   else
653         arp->ar_pro = htons(0xCC);
654   arp->ar_hln = dev->addr_len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -