📄 dev.c
字号:
699 {
700 int i;
701 struct sk_buff *skb;
702
703 for(i = 0;i < DEV_NUMBUFFS; i++) {
704 while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)
705 {
706 skb->magic = 0;
707 skb->next = NULL;
708 skb->prev = NULL;
709 dev->queue_xmit(skb,dev,-i - 1);
710 if (dev->tbusy)
711 return;
712 }
713 }
714 }
715
716
717 /* Perform a SIOCGIFCONF call. */
718 static int
719 dev_ifconf(char *arg)
720 {
721 struct ifconf ifc;
722 struct ifreq ifr;
723 struct device *dev;
724 char *pos;
725 int len;
726 int err;
727
728 /* Fetch the caller's info block. */
729 err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));
730 if(err)
731 return err;
732 memcpy_fromfs(&ifc, arg, sizeof(struct ifconf));
733 len = ifc.ifc_len;
734 pos = ifc.ifc_buf;
735
736 /* Loop over the interfaces, and write an info block for each. */
737 for (dev = dev_base; dev != NULL; dev = dev->next) {
738 if(!(dev->flags & IFF_UP))
739 continue;
740 memset(&ifr, 0, sizeof(struct ifreq));
741 strcpy(ifr.ifr_name, dev->name);
742 (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family;
743 (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
744
745 /* Write this block to the caller's space. */
746 memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
747 pos += sizeof(struct ifreq);
748 len -= sizeof(struct ifreq);
749 if (len < sizeof(struct ifreq)) break;
750 }
751
752 /* All done. Write the updated control block back to the caller. */
753 ifc.ifc_len = (pos - ifc.ifc_buf);
754 ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;
755 memcpy_tofs(arg, &ifc, sizeof(struct ifconf));
756 return(pos - arg);
757 }
758
759 /* Print device statistics. */
760 char *sprintf_stats(char *buffer, struct device *dev)
761 {
762 char *pos = buffer;
763 struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
764
765 if (stats)
766 pos += sprintf(pos, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n",
767 dev->name,
768 stats->rx_packets, stats->rx_errors,
769 stats->rx_dropped + stats->rx_missed_errors,
770 stats->rx_fifo_errors,
771 stats->rx_length_errors + stats->rx_over_errors
772 + stats->rx_crc_errors + stats->rx_frame_errors,
773 stats->tx_packets, stats->tx_errors, stats->tx_dropped,
774 stats->tx_fifo_errors, stats->collisions,
775 stats->tx_carrier_errors + stats->tx_aborted_errors
776 + stats->tx_window_errors + stats->tx_heartbeat_errors);
777 else
778 pos += sprintf(pos, "%6s: No statistics available.\n", dev->name);
779
780 return pos;
781 }
782
783 /* Called from the PROCfs module. */
784 int
785 dev_get_info(char *buffer)
786 {
787 char *pos = buffer;
788 struct device *dev;
789
790 pos +=
791 sprintf(pos,
792 "Inter-| Receive | Transmit\n"
793 " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n");
794 for (dev = dev_base; dev != NULL; dev = dev->next) {
795 pos = sprintf_stats(pos, dev);
796 }
797 return pos - buffer;
798 }
799
800 static inline int bad_mask(unsigned long mask, unsigned long addr)
801 {
802 if (addr & (mask = ~mask))
803 return 1;
804 mask = ntohl(mask);
805 if (mask & (mask+1))
806 return 1;
807 return 0;
808 }
809
810
811 /* Perform the SIOCxIFxxx calls. */
812 static int
813 dev_ifsioc(void *arg, unsigned int getset)
814 {
815 struct ifreq ifr;
816 struct device *dev;
817 int ret;
818
819 /* Fetch the caller's info block. */
820 int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq));
821 if(err)
822 return err;
823 memcpy_fromfs(&ifr, arg, sizeof(struct ifreq));
824
825 /* See which interface the caller is talking about. */
826 if ((dev = dev_get(ifr.ifr_name)) == NULL) return(-EINVAL);
827
828 switch(getset) {
829 case SIOCGIFFLAGS:
830 ifr.ifr_flags = dev->flags;
831 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
832 ret = 0;
833 break;
834 case SIOCSIFFLAGS:
835 {
836 int old_flags = dev->flags;
837 dev->flags = ifr.ifr_flags & (
838 IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
839 IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
840 IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI);
841
842 if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))
843 dev->set_multicast_list(dev,0,NULL);
844 if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0))
845 dev->set_multicast_list(dev,-1,NULL);
846 if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0)) {
847 ret = dev_close(dev);
848 } else
849 {
850 ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP))
851 ? dev_open(dev) : 0;
852 if(ret<0)
853 dev->flags&=~IFF_UP; /* Didnt open so down the if */
854 }
855 }
856 break;
857 case SIOCGIFADDR:
858 (*(struct sockaddr_in *)
859 &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
860 (*(struct sockaddr_in *)
861 &ifr.ifr_addr).sin_family = dev->family;
862 (*(struct sockaddr_in *)
863 &ifr.ifr_addr).sin_port = 0;
864 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
865 ret = 0;
866 break;
867 case SIOCSIFADDR:
868 dev->pa_addr = (*(struct sockaddr_in *)
869 &ifr.ifr_addr).sin_addr.s_addr;
870 dev->family = ifr.ifr_addr.sa_family;
871 dev->pa_mask = get_mask(dev->pa_addr);
872 dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
873 ret = 0;
874 break;
875 case SIOCGIFBRDADDR:
876 (*(struct sockaddr_in *)
877 &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr;
878 (*(struct sockaddr_in *)
879 &ifr.ifr_broadaddr).sin_family = dev->family;
880 (*(struct sockaddr_in *)
881 &ifr.ifr_broadaddr).sin_port = 0;
882 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
883 ret = 0;
884 break;
885 case SIOCSIFBRDADDR:
886 dev->pa_brdaddr = (*(struct sockaddr_in *)
887 &ifr.ifr_broadaddr).sin_addr.s_addr;
888 ret = 0;
889 break;
890 case SIOCGIFDSTADDR:
891 (*(struct sockaddr_in *)
892 &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr;
893 (*(struct sockaddr_in *)
894 &ifr.ifr_broadaddr).sin_family = dev->family;
895 (*(struct sockaddr_in *)
896 &ifr.ifr_broadaddr).sin_port = 0;
897 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
898 ret = 0;
899 break;
900 case SIOCSIFDSTADDR:
901 dev->pa_dstaddr = (*(struct sockaddr_in *)
902 &ifr.ifr_dstaddr).sin_addr.s_addr;
903 ret = 0;
904 break;
905 case SIOCGIFNETMASK:
906 (*(struct sockaddr_in *)
907 &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask;
908 (*(struct sockaddr_in *)
909 &ifr.ifr_netmask).sin_family = dev->family;
910 (*(struct sockaddr_in *)
911 &ifr.ifr_netmask).sin_port = 0;
912 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
913 ret = 0;
914 break;
915 case SIOCSIFNETMASK: {
916 unsigned long mask = (*(struct sockaddr_in *)
917 &ifr.ifr_netmask).sin_addr.s_addr;
918 ret = -EINVAL;
919 if (bad_mask(mask,0))
920 break;
921 dev->pa_mask = mask;
922 ret = 0;
923 break;
924 }
925 case SIOCGIFMETRIC:
926 ifr.ifr_metric = dev->metric;
927 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
928 ret = 0;
929 break;
930 case SIOCSIFMETRIC:
931 dev->metric = ifr.ifr_metric;
932 ret = 0;
933 break;
934 case SIOCGIFMTU:
935 ifr.ifr_mtu = dev->mtu;
936 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
937 ret = 0;
938 break;
939 case SIOCSIFMTU:
940 dev->mtu = ifr.ifr_mtu;
941 ret = 0;
942 break;
943 case SIOCGIFMEM:
944 printk("NET: ioctl(SIOCGIFMEM, 0x%08X)\n", (int)arg);
945 ret = -EINVAL;
946 break;
947 case SIOCSIFMEM:
948 printk("NET: ioctl(SIOCSIFMEM, 0x%08X)\n", (int)arg);
949 ret = -EINVAL;
950 break;
951 case SIOCGIFHWADDR:
952 memcpy(ifr.ifr_hwaddr,dev->dev_addr, MAX_ADDR_LEN);
953 memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
954 ret=0;
955 break;
956 default:
957 ret = -EINVAL;
958 }
959 return(ret);
960 }
961
962
963 /* This function handles all "interface"-type I/O control requests. */
964 int
965 dev_ioctl(unsigned int cmd, void *arg)
966 {
967 struct iflink iflink;
968 struct ddi_device *dev;
969
970 switch(cmd) {
971 case IP_SET_DEV:
972 printk("Your network configuration program needs upgrading.\n");
973 return -EINVAL;
974
975 case SIOCGIFCONF:
976 (void) dev_ifconf((char *) arg);
977 return 0;
978
979 case SIOCGIFFLAGS:
980 case SIOCGIFADDR:
981 case SIOCGIFDSTADDR:
982 case SIOCGIFBRDADDR:
983 case SIOCGIFNETMASK:
984 case SIOCGIFMETRIC:
985 case SIOCGIFMTU:
986 case SIOCGIFMEM:
987 case SIOCGIFHWADDR:
988 return dev_ifsioc(arg, cmd);
989
990 case SIOCSIFFLAGS:
991 case SIOCSIFADDR:
992 case SIOCSIFDSTADDR:
993 case SIOCSIFBRDADDR:
994 case SIOCSIFNETMASK:
995 case SIOCSIFMETRIC:
996 case SIOCSIFMTU:
997 case SIOCSIFMEM:
998 if (!suser())
999 return -EPERM;
1000 return dev_ifsioc(arg, cmd);
1001
1002 case SIOCSIFLINK:
1003 if (!suser())
1004 return -EPERM;
1005 memcpy_fromfs(&iflink, arg, sizeof(iflink));
1006 dev = ddi_map(iflink.id);
1007 if (dev == NULL)
1008 return -EINVAL;
1009
1010 /* Now allocate an interface and connect it. */
1011 printk("AF_INET: DDI \"%s\" linked to stream \"%s\"\n",
1012 dev->name, iflink.stream);
1013 return 0;
1014
1015 default:
1016 return -EINVAL;
1017 }
1018 }
1019
1020
1021 /* Initialize the DEV module. */
1022 void
1023 dev_init(void)
1024 {
1025 struct device *dev, *dev2;
1026
1027 /* Add the devices.
1028 * If the call to dev->init fails, the dev is removed
1029 * from the chain disconnecting the device until the
1030 * next reboot.
1031 */
1032 dev2 = NULL;
1033 for (dev = dev_base; dev != NULL; dev=dev->next) {
1034 if (dev->init && dev->init(dev)) {
1035 if (dev2 == NULL) dev_base = dev->next;
1036 else dev2->next = dev->next;
1037 } else {
1038 dev2 = dev;
1039 }
1040 }
1041
1042 /* Set up some IP addresses. */
1043 ip_bcast = in_aton("255.255.255.255");
1044 }
1045
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -