📄 arp.c
字号:
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 + -