aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-03 10:39:16 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-16 21:34:49 -0400
commit0f5cabba49021d36e9f76bd97d7fa0f4a408063f (patch)
tree3305fab41ac8cc29633c146c03703d3340fd8a0d
parent169a3ec492ddb6b0a8203fccba2ddff077154e26 (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.h2
-rw-r--r--net/wireless/wext.c73
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:
834static int ioctl_standard_call(struct net_device * dev, 834static 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
986static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, 982static 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/* ---------------------------------------------------------------- */
1016typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, 1008typedef 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 */
1023static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, 1016static 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 */
1082static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, 1076static 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,
1100int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, 1094int 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,
1116static int compat_standard_call(struct net_device *dev, 1112static 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
1149static int compat_private_call(struct net_device *dev, struct iwreq *iwr, 1142static 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