diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-03 10:39:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-16 21:34:49 -0400 |
commit | 0f5cabba49021d36e9f76bd97d7fa0f4a408063f (patch) | |
tree | 3305fab41ac8cc29633c146c03703d3340fd8a0d | |
parent | 169a3ec492ddb6b0a8203fccba2ddff077154e26 (diff) |
wext: Create IW_REQUEST_FLAG_COMPAT and set it as needed.
Now low-level WEXT ioctl handlers can do compat handling
when necessary.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/iw_handler.h | 2 | ||||
-rw-r--r-- | net/wireless/wext.c | 73 |
2 files changed, 34 insertions, 41 deletions
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index 369d50e08b99..c99a8eec84e7 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h | |||
@@ -256,7 +256,7 @@ | |||
256 | #define EIWCOMMIT EINPROGRESS | 256 | #define EIWCOMMIT EINPROGRESS |
257 | 257 | ||
258 | /* Flags available in struct iw_request_info */ | 258 | /* Flags available in struct iw_request_info */ |
259 | #define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */ | 259 | #define IW_REQUEST_FLAG_COMPAT 0x0001 /* Compat ioctl call */ |
260 | 260 | ||
261 | /* Type of headers we know about (basically union iwreq_data) */ | 261 | /* Type of headers we know about (basically union iwreq_data) */ |
262 | #define IW_HEADER_TYPE_NULL 0 /* Not available */ | 262 | #define IW_HEADER_TYPE_NULL 0 /* Not available */ |
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 1a4636a9fcde..273a84359998 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
@@ -834,10 +834,10 @@ out: | |||
834 | static int ioctl_standard_call(struct net_device * dev, | 834 | static int ioctl_standard_call(struct net_device * dev, |
835 | struct iwreq *iwr, | 835 | struct iwreq *iwr, |
836 | unsigned int cmd, | 836 | unsigned int cmd, |
837 | struct iw_request_info *info, | ||
837 | iw_handler handler) | 838 | iw_handler handler) |
838 | { | 839 | { |
839 | const struct iw_ioctl_description * descr; | 840 | const struct iw_ioctl_description * descr; |
840 | struct iw_request_info info; | ||
841 | int ret = -EINVAL; | 841 | int ret = -EINVAL; |
842 | 842 | ||
843 | /* Get the description of the IOCTL */ | 843 | /* Get the description of the IOCTL */ |
@@ -845,15 +845,11 @@ static int ioctl_standard_call(struct net_device * dev, | |||
845 | return -EOPNOTSUPP; | 845 | return -EOPNOTSUPP; |
846 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); | 846 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); |
847 | 847 | ||
848 | /* Prepare the call */ | ||
849 | info.cmd = cmd; | ||
850 | info.flags = 0; | ||
851 | |||
852 | /* 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 */ |
853 | if (descr->header_type != IW_HEADER_TYPE_POINT) { | 849 | if (descr->header_type != IW_HEADER_TYPE_POINT) { |
854 | 850 | ||
855 | /* No extra arguments. Trivial to handle */ | 851 | /* No extra arguments. Trivial to handle */ |
856 | ret = handler(dev, &info, &(iwr->u), NULL); | 852 | ret = handler(dev, info, &(iwr->u), NULL); |
857 | 853 | ||
858 | /* Generate an event to notify listeners of the change */ | 854 | /* Generate an event to notify listeners of the change */ |
859 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && | 855 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && |
@@ -861,7 +857,7 @@ static int ioctl_standard_call(struct net_device * dev, | |||
861 | wireless_send_event(dev, cmd, &(iwr->u), NULL); | 857 | wireless_send_event(dev, cmd, &(iwr->u), NULL); |
862 | } else { | 858 | } else { |
863 | ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, | 859 | ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, |
864 | handler, dev, &info); | 860 | handler, dev, info); |
865 | } | 861 | } |
866 | 862 | ||
867 | /* Call commit handler if needed and defined */ | 863 | /* Call commit handler if needed and defined */ |
@@ -984,25 +980,21 @@ out: | |||
984 | } | 980 | } |
985 | 981 | ||
986 | static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, | 982 | static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, |
987 | unsigned int cmd, iw_handler handler) | 983 | unsigned int cmd, struct iw_request_info *info, |
984 | iw_handler handler) | ||
988 | { | 985 | { |
989 | int extra_size = 0, ret = -EINVAL; | 986 | int extra_size = 0, ret = -EINVAL; |
990 | const struct iw_priv_args *descr; | 987 | const struct iw_priv_args *descr; |
991 | struct iw_request_info info; | ||
992 | 988 | ||
993 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | 989 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); |
994 | 990 | ||
995 | /* Prepare the call */ | ||
996 | info.cmd = cmd; | ||
997 | info.flags = 0; | ||
998 | |||
999 | /* Check if we have a pointer to user space data or not. */ | 991 | /* Check if we have a pointer to user space data or not. */ |
1000 | if (extra_size == 0) { | 992 | if (extra_size == 0) { |
1001 | /* No extra arguments. Trivial to handle */ | 993 | /* No extra arguments. Trivial to handle */ |
1002 | ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); | 994 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); |
1003 | } else { | 995 | } else { |
1004 | ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, | 996 | ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, |
1005 | handler, dev, &info, extra_size); | 997 | handler, dev, info, extra_size); |
1006 | } | 998 | } |
1007 | 999 | ||
1008 | /* Call commit handler if needed and defined */ | 1000 | /* Call commit handler if needed and defined */ |
@@ -1014,7 +1006,8 @@ static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, | |||
1014 | 1006 | ||
1015 | /* ---------------------------------------------------------------- */ | 1007 | /* ---------------------------------------------------------------- */ |
1016 | typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | 1008 | typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, |
1017 | unsigned int, iw_handler); | 1009 | unsigned int, struct iw_request_info *, |
1010 | iw_handler); | ||
1018 | 1011 | ||
1019 | /* | 1012 | /* |
1020 | * Main IOCTl dispatcher. | 1013 | * Main IOCTl dispatcher. |
@@ -1022,6 +1015,7 @@ typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | |||
1022 | */ | 1015 | */ |
1023 | static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, | 1016 | static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, |
1024 | unsigned int cmd, | 1017 | unsigned int cmd, |
1018 | struct iw_request_info *info, | ||
1025 | wext_ioctl_func standard, | 1019 | wext_ioctl_func standard, |
1026 | wext_ioctl_func private) | 1020 | wext_ioctl_func private) |
1027 | { | 1021 | { |
@@ -1040,11 +1034,11 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, | |||
1040 | * Note that 'cmd' is already filtered in dev_ioctl() with | 1034 | * Note that 'cmd' is already filtered in dev_ioctl() with |
1041 | * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ | 1035 | * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ |
1042 | if (cmd == SIOCGIWSTATS) | 1036 | if (cmd == SIOCGIWSTATS) |
1043 | return standard(dev, iwr, cmd, | 1037 | return standard(dev, iwr, cmd, info, |
1044 | &iw_handler_get_iwstats); | 1038 | &iw_handler_get_iwstats); |
1045 | 1039 | ||
1046 | if (cmd == SIOCGIWPRIV && dev->wireless_handlers) | 1040 | if (cmd == SIOCGIWPRIV && dev->wireless_handlers) |
1047 | return standard(dev, iwr, cmd, | 1041 | return standard(dev, iwr, cmd, info, |
1048 | &iw_handler_get_private); | 1042 | &iw_handler_get_private); |
1049 | 1043 | ||
1050 | /* Basic check */ | 1044 | /* Basic check */ |
@@ -1056,9 +1050,9 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, | |||
1056 | if (handler) { | 1050 | if (handler) { |
1057 | /* Standard and private are not the same */ | 1051 | /* Standard and private are not the same */ |
1058 | if (cmd < SIOCIWFIRSTPRIV) | 1052 | if (cmd < SIOCIWFIRSTPRIV) |
1059 | return standard(dev, iwr, cmd, handler); | 1053 | return standard(dev, iwr, cmd, info, handler); |
1060 | else | 1054 | else |
1061 | return private(dev, iwr, cmd, handler); | 1055 | return private(dev, iwr, cmd, info, handler); |
1062 | } | 1056 | } |
1063 | /* Old driver API : call driver ioctl handler */ | 1057 | /* Old driver API : call driver ioctl handler */ |
1064 | if (dev->do_ioctl) | 1058 | if (dev->do_ioctl) |
@@ -1080,7 +1074,7 @@ static int wext_permission_check(unsigned int cmd) | |||
1080 | 1074 | ||
1081 | /* entry point from dev ioctl */ | 1075 | /* entry point from dev ioctl */ |
1082 | static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, | 1076 | static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, |
1083 | unsigned int cmd, | 1077 | unsigned int cmd, struct iw_request_info *info, |
1084 | wext_ioctl_func standard, | 1078 | wext_ioctl_func standard, |
1085 | wext_ioctl_func private) | 1079 | wext_ioctl_func private) |
1086 | { | 1080 | { |
@@ -1091,7 +1085,7 @@ static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, | |||
1091 | 1085 | ||
1092 | dev_load(net, ifr->ifr_name); | 1086 | dev_load(net, ifr->ifr_name); |
1093 | rtnl_lock(); | 1087 | rtnl_lock(); |
1094 | ret = wireless_process_ioctl(net, ifr, cmd, standard, private); | 1088 | ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); |
1095 | rtnl_unlock(); | 1089 | rtnl_unlock(); |
1096 | 1090 | ||
1097 | return ret; | 1091 | return ret; |
@@ -1100,10 +1094,12 @@ static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, | |||
1100 | int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 1094 | int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, |
1101 | void __user *arg) | 1095 | void __user *arg) |
1102 | { | 1096 | { |
1103 | int ret = wext_ioctl_dispatch(net, ifr, cmd, | 1097 | struct iw_request_info info = { .cmd = cmd, .flags = 0 }; |
1104 | ioctl_standard_call, | 1098 | int ret; |
1105 | ioctl_private_call); | ||
1106 | 1099 | ||
1100 | ret = wext_ioctl_dispatch(net, ifr, cmd, &info, | ||
1101 | ioctl_standard_call, | ||
1102 | ioctl_private_call); | ||
1107 | if (ret >= 0 && | 1103 | if (ret >= 0 && |
1108 | IW_IS_GET(cmd) && | 1104 | IW_IS_GET(cmd) && |
1109 | copy_to_user(arg, ifr, sizeof(struct iwreq))) | 1105 | copy_to_user(arg, ifr, sizeof(struct iwreq))) |
@@ -1116,28 +1112,25 @@ int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | |||
1116 | static int compat_standard_call(struct net_device *dev, | 1112 | static int compat_standard_call(struct net_device *dev, |
1117 | struct iwreq *iwr, | 1113 | struct iwreq *iwr, |
1118 | unsigned int cmd, | 1114 | unsigned int cmd, |
1115 | struct iw_request_info *info, | ||
1119 | iw_handler handler) | 1116 | iw_handler handler) |
1120 | { | 1117 | { |
1121 | const struct iw_ioctl_description *descr; | 1118 | const struct iw_ioctl_description *descr; |
1122 | struct compat_iw_point *iwp_compat; | 1119 | struct compat_iw_point *iwp_compat; |
1123 | struct iw_request_info info; | ||
1124 | struct iw_point iwp; | 1120 | struct iw_point iwp; |
1125 | int err; | 1121 | int err; |
1126 | 1122 | ||
1127 | descr = standard_ioctl + (cmd - SIOCIWFIRST); | 1123 | descr = standard_ioctl + (cmd - SIOCIWFIRST); |
1128 | 1124 | ||
1129 | if (descr->header_type != IW_HEADER_TYPE_POINT) | 1125 | if (descr->header_type != IW_HEADER_TYPE_POINT) |
1130 | return ioctl_standard_call(dev, iwr, cmd, handler); | 1126 | return ioctl_standard_call(dev, iwr, cmd, info, handler); |
1131 | 1127 | ||
1132 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | 1128 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; |
1133 | iwp.pointer = compat_ptr(iwp_compat->pointer); | 1129 | iwp.pointer = compat_ptr(iwp_compat->pointer); |
1134 | iwp.length = iwp_compat->length; | 1130 | iwp.length = iwp_compat->length; |
1135 | iwp.flags = iwp_compat->flags; | 1131 | iwp.flags = iwp_compat->flags; |
1136 | 1132 | ||
1137 | info.cmd = cmd; | 1133 | err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info); |
1138 | info.flags = 0; | ||
1139 | |||
1140 | err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, &info); | ||
1141 | 1134 | ||
1142 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | 1135 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); |
1143 | iwp_compat->length = iwp.length; | 1136 | iwp_compat->length = iwp.length; |
@@ -1147,22 +1140,18 @@ static int compat_standard_call(struct net_device *dev, | |||
1147 | } | 1140 | } |
1148 | 1141 | ||
1149 | static int compat_private_call(struct net_device *dev, struct iwreq *iwr, | 1142 | static int compat_private_call(struct net_device *dev, struct iwreq *iwr, |
1150 | unsigned int cmd, iw_handler handler) | 1143 | unsigned int cmd, struct iw_request_info *info, |
1144 | iw_handler handler) | ||
1151 | { | 1145 | { |
1152 | const struct iw_priv_args *descr; | 1146 | const struct iw_priv_args *descr; |
1153 | struct iw_request_info info; | ||
1154 | int ret, extra_size; | 1147 | int ret, extra_size; |
1155 | 1148 | ||
1156 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | 1149 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); |
1157 | 1150 | ||
1158 | /* Prepare the call */ | ||
1159 | info.cmd = cmd; | ||
1160 | info.flags = 0; | ||
1161 | |||
1162 | /* Check if we have a pointer to user space data or not. */ | 1151 | /* Check if we have a pointer to user space data or not. */ |
1163 | if (extra_size == 0) { | 1152 | if (extra_size == 0) { |
1164 | /* No extra arguments. Trivial to handle */ | 1153 | /* No extra arguments. Trivial to handle */ |
1165 | ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); | 1154 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); |
1166 | } else { | 1155 | } else { |
1167 | struct compat_iw_point *iwp_compat; | 1156 | struct compat_iw_point *iwp_compat; |
1168 | struct iw_point iwp; | 1157 | struct iw_point iwp; |
@@ -1173,7 +1162,7 @@ static int compat_private_call(struct net_device *dev, struct iwreq *iwr, | |||
1173 | iwp.flags = iwp_compat->flags; | 1162 | iwp.flags = iwp_compat->flags; |
1174 | 1163 | ||
1175 | ret = ioctl_private_iw_point(&iwp, cmd, descr, | 1164 | ret = ioctl_private_iw_point(&iwp, cmd, descr, |
1176 | handler, dev, &info, extra_size); | 1165 | handler, dev, info, extra_size); |
1177 | 1166 | ||
1178 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | 1167 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); |
1179 | iwp_compat->length = iwp.length; | 1168 | iwp_compat->length = iwp.length; |
@@ -1191,6 +1180,7 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | |||
1191 | unsigned long arg) | 1180 | unsigned long arg) |
1192 | { | 1181 | { |
1193 | void __user *argp = (void __user *)arg; | 1182 | void __user *argp = (void __user *)arg; |
1183 | struct iw_request_info info; | ||
1194 | struct iwreq iwr; | 1184 | struct iwreq iwr; |
1195 | char *colon; | 1185 | char *colon; |
1196 | int ret; | 1186 | int ret; |
@@ -1203,7 +1193,10 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | |||
1203 | if (colon) | 1193 | if (colon) |
1204 | *colon = 0; | 1194 | *colon = 0; |
1205 | 1195 | ||
1206 | ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, | 1196 | info.cmd = cmd; |
1197 | info.flags = IW_REQUEST_FLAG_COMPAT; | ||
1198 | |||
1199 | ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info, | ||
1207 | compat_standard_call, | 1200 | compat_standard_call, |
1208 | compat_private_call); | 1201 | compat_private_call); |
1209 | 1202 | ||