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

📄 arp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 3 页
字号:
655   arp->ar_pln = 4;
656   arp->ar_op = htons(ARPOP_REQUEST);
657 
658   ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
659   memcpy(ptr, dev->dev_addr, arp->ar_hln);
660   ptr += arp->ar_hln;
661   memcpy(ptr, &saddr, arp->ar_pln);
662   ptr += arp->ar_pln;
663   /*memcpy(ptr, dev->broadcast, arp->ar_hln);*/
664   memset(ptr,0,arp->ar_hln);
665   ptr += arp->ar_hln;
666   memcpy(ptr, &paddr, arp->ar_pln);
667 
668   DPRINTF((DBG_ARP, ">>\n"));
669   arp_print(arp);
670   dev->queue_xmit(skb, dev, 0);
671 }
672 
673 
674 /* Find an ARP mapping in the cache. If not found, post a REQUEST. */
675 int
676 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
677            unsigned long saddr)
678 {
679   struct arp_table *apt;
680 
681   DPRINTF((DBG_ARP, "ARP: find(haddr=%s, ", eth_print(haddr)));
682   DPRINTF((DBG_ARP, "paddr=%s, ", in_ntoa(paddr)));
683   DPRINTF((DBG_ARP, "dev=%s, saddr=%s)\n", dev->name, in_ntoa(saddr)));
684 
685   switch(chk_addr(paddr)) {
686         case IS_MYADDR:
687                 memcpy(haddr, dev->dev_addr, dev->addr_len);
688                 return(0);
689         case IS_BROADCAST:
690                 memcpy(haddr, dev->broadcast, dev->addr_len);
691                 return(0);
692   }
693                 
694   apt = arp_lookup(paddr);
695   if (apt != NULL) {
696         /*
697          * Make sure it's not too old. If it is too old, we will
698          * just pretend we did not find it, and then arp_send will
699          * verify the address for us.
700          */
701         if ((apt->flags & ATF_PERM) ||
702             (apt->last_used < jiffies+ARP_TIMEOUT && apt->hlen != 0)) {
703                 apt->last_used = jiffies;
704                 memcpy(haddr, apt->ha, dev->addr_len);
705                 return(0);
706         } else {
707                 DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
708                                                         in_ntoa(apt->ip)));
709         }
710   }
711 
712   /*
713    * This assume haddr are at least 4 bytes.
714    * If this isn't true we can use a lookup table, one for every dev.
715    * NOTE: this bit of code still looks fishy to me- FvK
716    */
717   *(unsigned long *)haddr = paddr;
718 
719   /* If we didn't find an entry, we will try to send an ARP packet. */
720   arp_send(paddr, dev, saddr);
721 
722   return(1);
723 }
724 
725 
726 /* Add an entry to the ARP cache.  Check for dupes! */
727 void
728 arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
729 {
730   struct arp_table *apt;
731 
732   DPRINTF((DBG_ARP, "ARP: add(%s, ", in_ntoa(addr)));
733   DPRINTF((DBG_ARP, "%s, ", eth_print(haddr)));
734   DPRINTF((DBG_ARP, "%d, %d)\n", dev->hard_header_len, dev->type));
735 
736   /* This is probably a good check... */
737   if (addr == 0) {
738         printk("ARP: add: will not add entry for 0.0.0.0 !\n");
739         return;
740   }
741 
742   /* First see if the address is already in the table. */
743   apt = arp_lookup(addr);
744   if (apt != NULL) {
745         DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
746         apt->last_used = jiffies;
747         memcpy(apt->ha, haddr , dev->addr_len);
748         return;
749   }
750   arp_create(addr, haddr, dev->addr_len, dev->type);
751 }
752 
753 
754 /* Create an ARP entry for a device's broadcast address. */
755 void
756 arp_add_broad(unsigned long addr, struct device *dev)
757 {
758   struct arp_table *apt;
759 
760   arp_add(addr, dev->broadcast, dev);
761   apt = arp_lookup(addr);
762   if (apt != NULL) {
763         apt->flags |= ATF_PERM;
764   }
765 }
766 
767 
768 /* Queue an IP packet, while waiting for the ARP reply packet. */
769 void
770 arp_queue(struct sk_buff *skb)
771 {
772   cli();
773   skb->tries = ARP_MAX_TRIES;
774 
775   if (skb->next != NULL) {
776         sti();
777         printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
778         return;
779   }
780   if(arp_q==NULL)
781         arp_queue_kick();
782   skb_queue_tail(&arp_q,skb);
783   skb->magic = ARP_QUEUE_MAGIC;
784   sti();
785 }
786 
787 
788 /*
789  * Write the contents of the ARP cache to a PROCfs file.
790  * This is not by long perfect, as the internal ARP table doesn't
791  * have all the info we would like to have.  Oh well, it works for
792  * now, eh? - FvK
793  * Also note, that due to space limits, we cannot generate more than
794  * 4Kbyte worth of data.  This usually is enough, but I have seen
795  * machines die from under me because of a *very* large ARP cache.
796  * This can be simply tested by doing:
797  *
798  *      # ping 255.255.255.255
799  *      # arp -a
800  *
801  * Perhaps we should redo PROCfs to handle larger buffers?  Michael?
802  */
803 int
804 arp_get_info(char *buffer)
805 {
806   struct arpreq *req;
807   struct arp_table *apt;
808   int i;
809   char *pos;
810 
811   /* Loop over the ARP table and copy structures to the buffer. */
812   pos = buffer;
813   i = 0;
814   for (i = 0; i < ARP_TABLE_SIZE; i++) {
815         cli();
816         apt = arp_tables[i];
817         sti();
818         while (apt != NULL) {
819                 if (pos < (buffer + 4000)) {
820                         req = (struct arpreq *) pos;
821                         memset((char *) req, 0, sizeof(struct arpreq));
822                         req->arp_pa.sa_family = AF_INET;
823                         memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
824                                 req->arp_ha.sa_family = apt->htype;
825                         memcpy((char *) req->arp_ha.sa_data,
826                                 (char *) &apt->ha, apt->hlen);
827                         req->arp_flags = apt->flags;
828                 }
829                 pos += sizeof(struct arpreq);
830                 cli();
831                 apt = apt->next;
832                 sti();
833         }
834   }
835   return(pos - buffer);
836 }
837 
838 
839 /* Set (create) an ARP cache entry. */
840 static int
841 arp_req_set(struct arpreq *req)
842 {
843   struct arpreq r;
844   struct arp_table *apt;
845   struct sockaddr_in *si;
846   int htype, hlen;
847 
848   /* We only understand about IP addresses... */
849   memcpy_fromfs(&r, req, sizeof(r));
850   if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
851 
852   /*
853    * Find out about the hardware type.
854    * We have to be compatible with BSD UNIX, so we have to
855    * assume that a "not set" value (i.e. 0) means Ethernet.
856    */
857   si = (struct sockaddr_in *) &r.arp_pa;
858   switch(r.arp_ha.sa_family) {
859         case 0:
860         case ARPHRD_ETHER:
861                 htype = ARPHRD_ETHER;
862                 hlen = ETH_ALEN;
863                 break;
864                 case ARPHRD_AX25:
865                         htype = ARPHRD_AX25;
866                         hlen = 7;
867                         break;
868                 
869         default:
870                 return(-EPFNOSUPPORT);
871   }
872 
873   /* Is there an existing entry for this address? */
874   if (si->sin_addr.s_addr == 0) {
875         printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
876         return(-EINVAL);
877   }
878   apt = arp_lookup(si->sin_addr.s_addr);
879   if (apt == NULL) {
880         apt = arp_create(si->sin_addr.s_addr,
881                 (unsigned char *) r.arp_ha.sa_data, hlen, htype);
882         if (apt == NULL) return(-ENOMEM);
883   }
884 
885   /* We now have a pointer to an ARP entry.  Update it! */
886   memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
887   apt->last_used = jiffies;
888   apt->flags = r.arp_flags;
889   if(apt->flags&ATF_PUBL)
890         arp_proxies++;          /* Count proxy arps so we know if to use it */
891 
892   return(0);
893 }
894 
895 
896 /* Get an ARP cache entry. */
897 static int
898 arp_req_get(struct arpreq *req)
899 {
900   struct arpreq r;
901   struct arp_table *apt;
902   struct sockaddr_in *si;
903 
904   /* We only understand about IP addresses... */
905   memcpy_fromfs(&r, req, sizeof(r));
906   if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
907 
908   /* Is there an existing entry for this address? */
909   si = (struct sockaddr_in *) &r.arp_pa;
910   apt = arp_lookup(si->sin_addr.s_addr);
911   if (apt == NULL) return(-ENXIO);
912 
913   /* We found it; copy into structure. */
914   memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
915   r.arp_ha.sa_family = apt->htype;
916 
917   /* Copy the information back */
918   memcpy_tofs(req, &r, sizeof(r));
919   return(0);
920 }
921 
922 
923 /* Delete an ARP cache entry. */
924 static int
925 arp_req_del(struct arpreq *req)
926 {
927   struct arpreq r;
928   struct sockaddr_in *si;
929 
930   /* We only understand about IP addresses... */
931   memcpy_fromfs(&r, req, sizeof(r));
932   if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
933 
934   si = (struct sockaddr_in *) &r.arp_pa;
935   
936   /* The system cope with this but splats up a nasty kernel message 
937      We trap it beforehand and tell the user off */
938   if(chk_addr(si->sin_addr.s_addr)==IS_MYADDR)
939         return -EINVAL;
940         
941   arp_destroy(si->sin_addr.s_addr);
942 
943   return(0);
944 }
945 
946 
947 /* Handle an ARP layer I/O control request. */
948 int
949 arp_ioctl(unsigned int cmd, void *arg)
950 {
951   int err;
952   switch(cmd) {
953         case DDIOCSDBG:
954                 return(dbg_ioctl(arg, DBG_ARP));
955         case SIOCDARP:
956                 if (!suser()) return(-EPERM);
957                 err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
958                 if(err)
959                         return err;
960                 return(arp_req_del((struct arpreq *)arg));
961         case SIOCGARP:
962                 err=verify_area(VERIFY_WRITE,arg,sizeof(struct arpreq));
963                 if(err)
964                         return err;
965                 return(arp_req_get((struct arpreq *)arg));
966         case SIOCSARP:
967                 if (!suser()) return(-EPERM);
968                 err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
969                 if(err)
970                         return err;
971                 return(arp_req_set((struct arpreq *)arg));
972         default:
973                 return(-EINVAL);
974   }
975   /*NOTREACHED*/
976   return(0);
977 }
978 

⌨️ 快捷键说明

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