aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-21 11:19:50 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-21 11:19:50 -0400
commiteb6a12c2428d21a9f3e0f1a50e927d5fd80fc3d0 (patch)
tree5ac6f43899648abeab1d43aad3107f664e7f13d5 /net/wireless/wext.c
parentc4762aba0b1f72659aae9ce37b772ca8bd8f06f4 (diff)
parent14b395e35d1afdd8019d11b92e28041fad591b71 (diff)
Merge branch 'linus' into cpus4096-for-linus
Conflicts: net/sunrpc/svc.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net/wireless/wext.c')
-rw-r--r--net/wireless/wext.c584
1 files changed, 363 insertions, 221 deletions
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index 947188a5b937..df5b3886c36b 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -500,7 +500,7 @@ static int call_commit_handler(struct net_device *dev)
500/* 500/*
501 * Calculate size of private arguments 501 * Calculate size of private arguments
502 */ 502 */
503static inline int get_priv_size(__u16 args) 503static int get_priv_size(__u16 args)
504{ 504{
505 int num = args & IW_PRIV_SIZE_MASK; 505 int num = args & IW_PRIV_SIZE_MASK;
506 int type = (args & IW_PRIV_TYPE_MASK) >> 12; 506 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
@@ -512,10 +512,9 @@ static inline int get_priv_size(__u16 args)
512/* 512/*
513 * Re-calculate the size of private arguments 513 * Re-calculate the size of private arguments
514 */ 514 */
515static inline int adjust_priv_size(__u16 args, 515static int adjust_priv_size(__u16 args, struct iw_point *iwp)
516 union iwreq_data * wrqu)
517{ 516{
518 int num = wrqu->data.length; 517 int num = iwp->length;
519 int max = args & IW_PRIV_SIZE_MASK; 518 int max = args & IW_PRIV_SIZE_MASK;
520 int type = (args & IW_PRIV_TYPE_MASK) >> 12; 519 int type = (args & IW_PRIV_TYPE_MASK) >> 12;
521 520
@@ -695,19 +694,150 @@ void wext_proc_exit(struct net *net)
695 */ 694 */
696 695
697/* ---------------------------------------------------------------- */ 696/* ---------------------------------------------------------------- */
697static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
698 const struct iw_ioctl_description *descr,
699 iw_handler handler, struct net_device *dev,
700 struct iw_request_info *info)
701{
702 int err, extra_size, user_length = 0, essid_compat = 0;
703 char *extra;
704
705 /* Calculate space needed by arguments. Always allocate
706 * for max space.
707 */
708 extra_size = descr->max_tokens * descr->token_size;
709
710 /* Check need for ESSID compatibility for WE < 21 */
711 switch (cmd) {
712 case SIOCSIWESSID:
713 case SIOCGIWESSID:
714 case SIOCSIWNICKN:
715 case SIOCGIWNICKN:
716 if (iwp->length == descr->max_tokens + 1)
717 essid_compat = 1;
718 else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
719 char essid[IW_ESSID_MAX_SIZE + 1];
720
721 err = copy_from_user(essid, iwp->pointer,
722 iwp->length *
723 descr->token_size);
724 if (err)
725 return -EFAULT;
726
727 if (essid[iwp->length - 1] == '\0')
728 essid_compat = 1;
729 }
730 break;
731 default:
732 break;
733 }
734
735 iwp->length -= essid_compat;
736
737 /* Check what user space is giving us */
738 if (IW_IS_SET(cmd)) {
739 /* Check NULL pointer */
740 if (!iwp->pointer && iwp->length != 0)
741 return -EFAULT;
742 /* Check if number of token fits within bounds */
743 if (iwp->length > descr->max_tokens)
744 return -E2BIG;
745 if (iwp->length < descr->min_tokens)
746 return -EINVAL;
747 } else {
748 /* Check NULL pointer */
749 if (!iwp->pointer)
750 return -EFAULT;
751 /* Save user space buffer size for checking */
752 user_length = iwp->length;
753
754 /* Don't check if user_length > max to allow forward
755 * compatibility. The test user_length < min is
756 * implied by the test at the end.
757 */
758
759 /* Support for very large requests */
760 if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
761 (user_length > descr->max_tokens)) {
762 /* Allow userspace to GET more than max so
763 * we can support any size GET requests.
764 * There is still a limit : -ENOMEM.
765 */
766 extra_size = user_length * descr->token_size;
767
768 /* Note : user_length is originally a __u16,
769 * and token_size is controlled by us,
770 * so extra_size won't get negative and
771 * won't overflow...
772 */
773 }
774 }
775
776 /* kzalloc() ensures NULL-termination for essid_compat. */
777 extra = kzalloc(extra_size, GFP_KERNEL);
778 if (!extra)
779 return -ENOMEM;
780
781 /* If it is a SET, get all the extra data in here */
782 if (IW_IS_SET(cmd) && (iwp->length != 0)) {
783 if (copy_from_user(extra, iwp->pointer,
784 iwp->length *
785 descr->token_size)) {
786 err = -EFAULT;
787 goto out;
788 }
789 }
790
791 err = handler(dev, info, (union iwreq_data *) iwp, extra);
792
793 iwp->length += essid_compat;
794
795 /* If we have something to return to the user */
796 if (!err && IW_IS_GET(cmd)) {
797 /* Check if there is enough buffer up there */
798 if (user_length < iwp->length) {
799 err = -E2BIG;
800 goto out;
801 }
802
803 if (copy_to_user(iwp->pointer, extra,
804 iwp->length *
805 descr->token_size)) {
806 err = -EFAULT;
807 goto out;
808 }
809 }
810
811 /* Generate an event to notify listeners of the change */
812 if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) {
813 union iwreq_data *data = (union iwreq_data *) iwp;
814
815 if (descr->flags & IW_DESCR_FLAG_RESTRICT)
816 /* If the event is restricted, don't
817 * export the payload.
818 */
819 wireless_send_event(dev, cmd, data, NULL);
820 else
821 wireless_send_event(dev, cmd, data, extra);
822 }
823
824out:
825 kfree(extra);
826 return err;
827}
828
698/* 829/*
699 * Wrapper to call a standard Wireless Extension handler. 830 * Wrapper to call a standard Wireless Extension handler.
700 * We do various checks and also take care of moving data between 831 * We do various checks and also take care of moving data between
701 * user space and kernel space. 832 * user space and kernel space.
702 */ 833 */
703static int ioctl_standard_call(struct net_device * dev, 834static int ioctl_standard_call(struct net_device * dev,
704 struct ifreq * ifr, 835 struct iwreq *iwr,
705 unsigned int cmd, 836 unsigned int cmd,
837 struct iw_request_info *info,
706 iw_handler handler) 838 iw_handler handler)
707{ 839{
708 struct iwreq * iwr = (struct iwreq *) ifr;
709 const struct iw_ioctl_description * descr; 840 const struct iw_ioctl_description * descr;
710 struct iw_request_info info;
711 int ret = -EINVAL; 841 int ret = -EINVAL;
712 842
713 /* Get the description of the IOCTL */ 843 /* Get the description of the IOCTL */
@@ -715,145 +845,19 @@ static int ioctl_standard_call(struct net_device * dev,
715 return -EOPNOTSUPP; 845 return -EOPNOTSUPP;
716 descr = &(standard_ioctl[cmd - SIOCIWFIRST]); 846 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
717 847
718 /* Prepare the call */
719 info.cmd = cmd;
720 info.flags = 0;
721
722 /* Check if we have a pointer to user space data or not */ 848 /* Check if we have a pointer to user space data or not */
723 if (descr->header_type != IW_HEADER_TYPE_POINT) { 849 if (descr->header_type != IW_HEADER_TYPE_POINT) {
724 850
725 /* No extra arguments. Trivial to handle */ 851 /* No extra arguments. Trivial to handle */
726 ret = handler(dev, &info, &(iwr->u), NULL); 852 ret = handler(dev, info, &(iwr->u), NULL);
727 853
728 /* Generate an event to notify listeners of the change */ 854 /* Generate an event to notify listeners of the change */
729 if ((descr->flags & IW_DESCR_FLAG_EVENT) && 855 if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
730 ((ret == 0) || (ret == -EIWCOMMIT))) 856 ((ret == 0) || (ret == -EIWCOMMIT)))
731 wireless_send_event(dev, cmd, &(iwr->u), NULL); 857 wireless_send_event(dev, cmd, &(iwr->u), NULL);
732 } else { 858 } else {
733 char * extra; 859 ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr,
734 int extra_size; 860 handler, dev, info);
735 int user_length = 0;
736 int err;
737 int essid_compat = 0;
738
739 /* Calculate space needed by arguments. Always allocate
740 * for max space. Easier, and won't last long... */
741 extra_size = descr->max_tokens * descr->token_size;
742
743 /* Check need for ESSID compatibility for WE < 21 */
744 switch (cmd) {
745 case SIOCSIWESSID:
746 case SIOCGIWESSID:
747 case SIOCSIWNICKN:
748 case SIOCGIWNICKN:
749 if (iwr->u.data.length == descr->max_tokens + 1)
750 essid_compat = 1;
751 else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
752 char essid[IW_ESSID_MAX_SIZE + 1];
753
754 err = copy_from_user(essid, iwr->u.data.pointer,
755 iwr->u.data.length *
756 descr->token_size);
757 if (err)
758 return -EFAULT;
759
760 if (essid[iwr->u.data.length - 1] == '\0')
761 essid_compat = 1;
762 }
763 break;
764 default:
765 break;
766 }
767
768 iwr->u.data.length -= essid_compat;
769
770 /* Check what user space is giving us */
771 if (IW_IS_SET(cmd)) {
772 /* Check NULL pointer */
773 if ((iwr->u.data.pointer == NULL) &&
774 (iwr->u.data.length != 0))
775 return -EFAULT;
776 /* Check if number of token fits within bounds */
777 if (iwr->u.data.length > descr->max_tokens)
778 return -E2BIG;
779 if (iwr->u.data.length < descr->min_tokens)
780 return -EINVAL;
781 } else {
782 /* Check NULL pointer */
783 if (iwr->u.data.pointer == NULL)
784 return -EFAULT;
785 /* Save user space buffer size for checking */
786 user_length = iwr->u.data.length;
787
788 /* Don't check if user_length > max to allow forward
789 * compatibility. The test user_length < min is
790 * implied by the test at the end. */
791
792 /* Support for very large requests */
793 if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
794 (user_length > descr->max_tokens)) {
795 /* Allow userspace to GET more than max so
796 * we can support any size GET requests.
797 * There is still a limit : -ENOMEM. */
798 extra_size = user_length * descr->token_size;
799 /* Note : user_length is originally a __u16,
800 * and token_size is controlled by us,
801 * so extra_size won't get negative and
802 * won't overflow... */
803 }
804 }
805
806 /* Create the kernel buffer */
807 /* kzalloc ensures NULL-termination for essid_compat */
808 extra = kzalloc(extra_size, GFP_KERNEL);
809 if (extra == NULL)
810 return -ENOMEM;
811
812 /* If it is a SET, get all the extra data in here */
813 if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
814 err = copy_from_user(extra, iwr->u.data.pointer,
815 iwr->u.data.length *
816 descr->token_size);
817 if (err) {
818 kfree(extra);
819 return -EFAULT;
820 }
821 }
822
823 /* Call the handler */
824 ret = handler(dev, &info, &(iwr->u), extra);
825
826 iwr->u.data.length += essid_compat;
827
828 /* If we have something to return to the user */
829 if (!ret && IW_IS_GET(cmd)) {
830 /* Check if there is enough buffer up there */
831 if (user_length < iwr->u.data.length) {
832 kfree(extra);
833 return -E2BIG;
834 }
835
836 err = copy_to_user(iwr->u.data.pointer, extra,
837 iwr->u.data.length *
838 descr->token_size);
839 if (err)
840 ret = -EFAULT;
841 }
842
843 /* Generate an event to notify listeners of the change */
844 if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
845 ((ret == 0) || (ret == -EIWCOMMIT))) {
846 if (descr->flags & IW_DESCR_FLAG_RESTRICT)
847 /* If the event is restricted, don't
848 * export the payload */
849 wireless_send_event(dev, cmd, &(iwr->u), NULL);
850 else
851 wireless_send_event(dev, cmd, &(iwr->u),
852 extra);
853 }
854
855 /* Cleanup - I told you it wasn't that long ;-) */
856 kfree(extra);
857 } 861 }
858 862
859 /* Call commit handler if needed and defined */ 863 /* Call commit handler if needed and defined */
@@ -881,25 +885,22 @@ static int ioctl_standard_call(struct net_device * dev,
881 * a iw_handler but process it in your ioctl handler (i.e. use the 885 * a iw_handler but process it in your ioctl handler (i.e. use the
882 * old driver API). 886 * old driver API).
883 */ 887 */
884static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, 888static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd,
885 unsigned int cmd, iw_handler handler) 889 const struct iw_priv_args **descrp)
886{ 890{
887 struct iwreq * iwr = (struct iwreq *) ifr; 891 const struct iw_priv_args *descr;
888 const struct iw_priv_args * descr = NULL; 892 int i, extra_size;
889 struct iw_request_info info;
890 int extra_size = 0;
891 int i;
892 int ret = -EINVAL;
893 893
894 /* Get the description of the IOCTL */ 894 descr = NULL;
895 for (i = 0; i < dev->wireless_handlers->num_private_args; i++) 895 for (i = 0; i < dev->wireless_handlers->num_private_args; i++) {
896 if (cmd == dev->wireless_handlers->private_args[i].cmd) { 896 if (cmd == dev->wireless_handlers->private_args[i].cmd) {
897 descr = &(dev->wireless_handlers->private_args[i]); 897 descr = &dev->wireless_handlers->private_args[i];
898 break; 898 break;
899 } 899 }
900 }
900 901
901 /* Compute the size of the set/get arguments */ 902 extra_size = 0;
902 if (descr != NULL) { 903 if (descr) {
903 if (IW_IS_SET(cmd)) { 904 if (IW_IS_SET(cmd)) {
904 int offset = 0; /* For sub-ioctls */ 905 int offset = 0; /* For sub-ioctls */
905 /* Check for sub-ioctl handler */ 906 /* Check for sub-ioctl handler */
@@ -924,72 +925,77 @@ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr,
924 extra_size = 0; 925 extra_size = 0;
925 } 926 }
926 } 927 }
928 *descrp = descr;
929 return extra_size;
930}
927 931
928 /* Prepare the call */ 932static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd,
929 info.cmd = cmd; 933 const struct iw_priv_args *descr,
930 info.flags = 0; 934 iw_handler handler, struct net_device *dev,
935 struct iw_request_info *info, int extra_size)
936{
937 char *extra;
938 int err;
931 939
932 /* Check if we have a pointer to user space data or not. */ 940 /* Check what user space is giving us */
933 if (extra_size == 0) { 941 if (IW_IS_SET(cmd)) {
934 /* No extra arguments. Trivial to handle */ 942 if (!iwp->pointer && iwp->length != 0)
935 ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); 943 return -EFAULT;
936 } else {
937 char * extra;
938 int err;
939 944
940 /* Check what user space is giving us */ 945 if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK))
941 if (IW_IS_SET(cmd)) { 946 return -E2BIG;
942 /* Check NULL pointer */ 947 } else if (!iwp->pointer)
943 if ((iwr->u.data.pointer == NULL) && 948 return -EFAULT;
944 (iwr->u.data.length != 0))
945 return -EFAULT;
946 949
947 /* Does it fits within bounds ? */ 950 extra = kmalloc(extra_size, GFP_KERNEL);
948 if (iwr->u.data.length > (descr->set_args & 951 if (!extra)
949 IW_PRIV_SIZE_MASK)) 952 return -ENOMEM;
950 return -E2BIG;
951 } else if (iwr->u.data.pointer == NULL)
952 return -EFAULT;
953 953
954 /* Always allocate for max space. Easier, and won't last 954 /* If it is a SET, get all the extra data in here */
955 * long... */ 955 if (IW_IS_SET(cmd) && (iwp->length != 0)) {
956 extra = kmalloc(extra_size, GFP_KERNEL); 956 if (copy_from_user(extra, iwp->pointer, extra_size)) {
957 if (extra == NULL) 957 err = -EFAULT;
958 return -ENOMEM; 958 goto out;
959
960 /* If it is a SET, get all the extra data in here */
961 if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
962 err = copy_from_user(extra, iwr->u.data.pointer,
963 extra_size);
964 if (err) {
965 kfree(extra);
966 return -EFAULT;
967 }
968 } 959 }
960 }
969 961
970 /* Call the handler */ 962 /* Call the handler */
971 ret = handler(dev, &info, &(iwr->u), extra); 963 err = handler(dev, info, (union iwreq_data *) iwp, extra);
972 964
973 /* If we have something to return to the user */ 965 /* If we have something to return to the user */
974 if (!ret && IW_IS_GET(cmd)) { 966 if (!err && IW_IS_GET(cmd)) {
967 /* Adjust for the actual length if it's variable,
968 * avoid leaking kernel bits outside.
969 */
970 if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
971 extra_size = adjust_priv_size(descr->get_args, iwp);
975 972
976 /* Adjust for the actual length if it's variable, 973 if (copy_to_user(iwp->pointer, extra, extra_size))
977 * avoid leaking kernel bits outside. */ 974 err = -EFAULT;
978 if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { 975 }
979 extra_size = adjust_priv_size(descr->get_args,
980 &(iwr->u));
981 }
982 976
983 err = copy_to_user(iwr->u.data.pointer, extra, 977out:
984 extra_size); 978 kfree(extra);
985 if (err) 979 return err;
986 ret = -EFAULT; 980}
987 }
988 981
989 /* Cleanup - I told you it wasn't that long ;-) */ 982static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr,
990 kfree(extra); 983 unsigned int cmd, struct iw_request_info *info,
991 } 984 iw_handler handler)
985{
986 int extra_size = 0, ret = -EINVAL;
987 const struct iw_priv_args *descr;
992 988
989 extra_size = get_priv_descr_and_size(dev, cmd, &descr);
990
991 /* Check if we have a pointer to user space data or not. */
992 if (extra_size == 0) {
993 /* No extra arguments. Trivial to handle */
994 ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u));
995 } else {
996 ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr,
997 handler, dev, info, extra_size);
998 }
993 999
994 /* Call commit handler if needed and defined */ 1000 /* Call commit handler if needed and defined */
995 if (ret == -EIWCOMMIT) 1001 if (ret == -EIWCOMMIT)
@@ -999,12 +1005,21 @@ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr,
999} 1005}
1000 1006
1001/* ---------------------------------------------------------------- */ 1007/* ---------------------------------------------------------------- */
1008typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *,
1009 unsigned int, struct iw_request_info *,
1010 iw_handler);
1011
1002/* 1012/*
1003 * Main IOCTl dispatcher. 1013 * Main IOCTl dispatcher.
1004 * Check the type of IOCTL and call the appropriate wrapper... 1014 * Check the type of IOCTL and call the appropriate wrapper...
1005 */ 1015 */
1006static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd) 1016static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
1017 unsigned int cmd,
1018 struct iw_request_info *info,
1019 wext_ioctl_func standard,
1020 wext_ioctl_func private)
1007{ 1021{
1022 struct iwreq *iwr = (struct iwreq *) ifr;
1008 struct net_device *dev; 1023 struct net_device *dev;
1009 iw_handler handler; 1024 iw_handler handler;
1010 1025
@@ -1019,12 +1034,12 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned i
1019 * Note that 'cmd' is already filtered in dev_ioctl() with 1034 * Note that 'cmd' is already filtered in dev_ioctl() with
1020 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ 1035 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
1021 if (cmd == SIOCGIWSTATS) 1036 if (cmd == SIOCGIWSTATS)
1022 return ioctl_standard_call(dev, ifr, cmd, 1037 return standard(dev, iwr, cmd, info,
1023 &iw_handler_get_iwstats); 1038 &iw_handler_get_iwstats);
1024 1039
1025 if (cmd == SIOCGIWPRIV && dev->wireless_handlers) 1040 if (cmd == SIOCGIWPRIV && dev->wireless_handlers)
1026 return ioctl_standard_call(dev, ifr, cmd, 1041 return standard(dev, iwr, cmd, info,
1027 &iw_handler_get_private); 1042 &iw_handler_get_private);
1028 1043
1029 /* Basic check */ 1044 /* Basic check */
1030 if (!netif_device_present(dev)) 1045 if (!netif_device_present(dev))
@@ -1035,9 +1050,9 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned i
1035 if (handler) { 1050 if (handler) {
1036 /* Standard and private are not the same */ 1051 /* Standard and private are not the same */
1037 if (cmd < SIOCIWFIRSTPRIV) 1052 if (cmd < SIOCIWFIRSTPRIV)
1038 return ioctl_standard_call(dev, ifr, cmd, handler); 1053 return standard(dev, iwr, cmd, info, handler);
1039 else 1054 else
1040 return ioctl_private_call(dev, ifr, cmd, handler); 1055 return private(dev, iwr, cmd, info, handler);
1041 } 1056 }
1042 /* Old driver API : call driver ioctl handler */ 1057 /* Old driver API : call driver ioctl handler */
1043 if (dev->do_ioctl) 1058 if (dev->do_ioctl)
@@ -1045,27 +1060,154 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned i
1045 return -EOPNOTSUPP; 1060 return -EOPNOTSUPP;
1046} 1061}
1047 1062
1048/* entry point from dev ioctl */ 1063/* If command is `set a parameter', or `get the encoding parameters',
1049int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, 1064 * check if the user has the right to do it.
1050 void __user *arg) 1065 */
1066static int wext_permission_check(unsigned int cmd)
1051{ 1067{
1052 int ret;
1053
1054 /* If command is `set a parameter', or
1055 * `get the encoding parameters', check if
1056 * the user has the right to do it */
1057 if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE || cmd == SIOCGIWENCODEEXT) 1068 if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE || cmd == SIOCGIWENCODEEXT)
1058 && !capable(CAP_NET_ADMIN)) 1069 && !capable(CAP_NET_ADMIN))
1059 return -EPERM; 1070 return -EPERM;
1060 1071
1072 return 0;
1073}
1074
1075/* entry point from dev ioctl */
1076static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
1077 unsigned int cmd, struct iw_request_info *info,
1078 wext_ioctl_func standard,
1079 wext_ioctl_func private)
1080{
1081 int ret = wext_permission_check(cmd);
1082
1083 if (ret)
1084 return ret;
1085
1061 dev_load(net, ifr->ifr_name); 1086 dev_load(net, ifr->ifr_name);
1062 rtnl_lock(); 1087 rtnl_lock();
1063 ret = wireless_process_ioctl(net, ifr, cmd); 1088 ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
1064 rtnl_unlock(); 1089 rtnl_unlock();
1065 if (IW_IS_GET(cmd) && copy_to_user(arg, ifr, sizeof(struct iwreq))) 1090
1091 return ret;
1092}
1093
1094int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
1095 void __user *arg)
1096{
1097 struct iw_request_info info = { .cmd = cmd, .flags = 0 };
1098 int ret;
1099
1100 ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
1101 ioctl_standard_call,
1102 ioctl_private_call);
1103 if (ret >= 0 &&
1104 IW_IS_GET(cmd) &&
1105 copy_to_user(arg, ifr, sizeof(struct iwreq)))
1106 return -EFAULT;
1107
1108 return ret;
1109}
1110
1111#ifdef CONFIG_COMPAT
1112static int compat_standard_call(struct net_device *dev,
1113 struct iwreq *iwr,
1114 unsigned int cmd,
1115 struct iw_request_info *info,
1116 iw_handler handler)
1117{
1118 const struct iw_ioctl_description *descr;
1119 struct compat_iw_point *iwp_compat;
1120 struct iw_point iwp;
1121 int err;
1122
1123 descr = standard_ioctl + (cmd - SIOCIWFIRST);
1124
1125 if (descr->header_type != IW_HEADER_TYPE_POINT)
1126 return ioctl_standard_call(dev, iwr, cmd, info, handler);
1127
1128 iwp_compat = (struct compat_iw_point *) &iwr->u.data;
1129 iwp.pointer = compat_ptr(iwp_compat->pointer);
1130 iwp.length = iwp_compat->length;
1131 iwp.flags = iwp_compat->flags;
1132
1133 err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info);
1134
1135 iwp_compat->pointer = ptr_to_compat(iwp.pointer);
1136 iwp_compat->length = iwp.length;
1137 iwp_compat->flags = iwp.flags;
1138
1139 return err;
1140}
1141
1142static int compat_private_call(struct net_device *dev, struct iwreq *iwr,
1143 unsigned int cmd, struct iw_request_info *info,
1144 iw_handler handler)
1145{
1146 const struct iw_priv_args *descr;
1147 int ret, extra_size;
1148
1149 extra_size = get_priv_descr_and_size(dev, cmd, &descr);
1150
1151 /* Check if we have a pointer to user space data or not. */
1152 if (extra_size == 0) {
1153 /* No extra arguments. Trivial to handle */
1154 ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u));
1155 } else {
1156 struct compat_iw_point *iwp_compat;
1157 struct iw_point iwp;
1158
1159 iwp_compat = (struct compat_iw_point *) &iwr->u.data;
1160 iwp.pointer = compat_ptr(iwp_compat->pointer);
1161 iwp.length = iwp_compat->length;
1162 iwp.flags = iwp_compat->flags;
1163
1164 ret = ioctl_private_iw_point(&iwp, cmd, descr,
1165 handler, dev, info, extra_size);
1166
1167 iwp_compat->pointer = ptr_to_compat(iwp.pointer);
1168 iwp_compat->length = iwp.length;
1169 iwp_compat->flags = iwp.flags;
1170 }
1171
1172 /* Call commit handler if needed and defined */
1173 if (ret == -EIWCOMMIT)
1174 ret = call_commit_handler(dev);
1175
1176 return ret;
1177}
1178
1179int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
1180 unsigned long arg)
1181{
1182 void __user *argp = (void __user *)arg;
1183 struct iw_request_info info;
1184 struct iwreq iwr;
1185 char *colon;
1186 int ret;
1187
1188 if (copy_from_user(&iwr, argp, sizeof(struct iwreq)))
1189 return -EFAULT;
1190
1191 iwr.ifr_name[IFNAMSIZ-1] = 0;
1192 colon = strchr(iwr.ifr_name, ':');
1193 if (colon)
1194 *colon = 0;
1195
1196 info.cmd = cmd;
1197 info.flags = IW_REQUEST_FLAG_COMPAT;
1198
1199 ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info,
1200 compat_standard_call,
1201 compat_private_call);
1202
1203 if (ret >= 0 &&
1204 IW_IS_GET(cmd) &&
1205 copy_to_user(argp, &iwr, sizeof(struct iwreq)))
1066 return -EFAULT; 1206 return -EFAULT;
1207
1067 return ret; 1208 return ret;
1068} 1209}
1210#endif
1069 1211
1070/************************* EVENT PROCESSING *************************/ 1212/************************* EVENT PROCESSING *************************/
1071/* 1213/*
@@ -1157,7 +1299,7 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
1157 struct sk_buff *skb; 1299 struct sk_buff *skb;
1158 int err; 1300 int err;
1159 1301
1160 if (dev_net(dev) != &init_net) 1302 if (!net_eq(dev_net(dev), &init_net))
1161 return; 1303 return;
1162 1304
1163 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1305 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);