1 /* Note : this particular snipset of code is available under
2 * the LGPL, MPL or BSD license (at your choice).
6 // Require Wireless Tools 25 for sub-ioctl and addr support
8 /* --------------------------- INCLUDE --------------------------- */
10 #if WIRELESS_EXT <= 12
11 /* Wireless extensions backward compatibility */
13 /* We need the full definition for private ioctls */
14 struct iw_request_info
16 __u16 cmd; /* Wireless Extension command */
17 __u16 flags; /* More to come ;-) */
19 #endif /* WIRELESS_EXT <= 12 */
21 #ifndef IW_PRIV_TYPE_ADDR
22 #define IW_PRIV_TYPE_ADDR 0x6000
23 #endif /* IW_PRIV_TYPE_ADDR */
25 /* --------------------------- HANDLERS --------------------------- */
27 /* First method : using sub-ioctls.
28 * Note that sizeof(int + struct sockaddr) = 20 > 16, therefore the
29 * data is passed in (char *) extra, and sub-ioctl in data->flags. */
30 static int sample_ioctl_set_mac(struct net_device *dev,
31 struct iw_request_info *info,
32 struct iw_point *data,
33 struct sockaddr *mac_addr)
35 unsigned char * addr = (char *) &mac_addr->sa_data;
39 printk(KERN_DEBUG "%s: mac_add %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
42 printk(KERN_DEBUG "%s: mac_del %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
45 printk(KERN_DEBUG "%s: mac_kick %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
48 printk(KERN_DEBUG "%s: mac_undefined %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
55 /* Second method : bind single handler to multiple ioctls.
56 * Note that sizeof(struct sockaddr) = 16 <= 16, therefore the
57 * data is passed in (struct iwreq) (and also mapped in extra).
59 static int sample_ioctl_set_addr(struct net_device *dev,
60 struct iw_request_info *info,
61 struct sockaddr *mac_addr, char *extra)
63 unsigned char * addr = (char *) &mac_addr->sa_data;
66 case SIOCIWFIRSTPRIV + 28:
67 printk(KERN_DEBUG "%s: addr_add %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
69 case SIOCIWFIRSTPRIV + 30:
70 printk(KERN_DEBUG "%s: addr_del %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
73 printk(KERN_DEBUG "%s: mac_undefined %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
80 // Extra fun for testing
81 static int sample_ioctl_get_mac(struct net_device *dev,
82 struct iw_request_info *info,
83 struct iw_point *data,
84 struct sockaddr *mac_addr)
86 unsigned char fake_addr[6];
90 for(i = 0; i < 16; i++) {
91 /* Create a fake address */
92 for(j = 0; j < 6; j++)
93 fake_addr[j] = (unsigned char) ((j << 4) + i);
94 /* Put in in the table */
95 memcpy(&(mac_addr[i]).sa_data, fake_addr, ETH_ALEN);
96 mac_addr[i].sa_family = ARPHRD_ETHER;
103 static int sample_ioctl_set_float(struct net_device *dev,
104 struct iw_request_info *info,
105 struct iw_freq *freq, char *extra)
107 printk(KERN_DEBUG "%s: set_float %d;%d\n",
108 dev->name, freq->m, freq->e);
113 /* --------------------------- BINDING --------------------------- */
115 static const struct iw_priv_args sample_priv[] = {
116 // *** Method 1 : using sub-ioctls ***
117 /* --- sub-ioctls handler --- */
118 { SIOCIWFIRSTPRIV + 0,
119 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "" },
120 /* --- sub-ioctls definitions --- */
122 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macadd" },
124 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macdel" },
126 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "mackick" },
127 // *** Method 2 : binding one handler to multiple ioctls ***
128 { SIOCIWFIRSTPRIV + 2,
129 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addradd" },
130 { SIOCIWFIRSTPRIV + 4,
131 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addrdel" },
133 { SIOCIWFIRSTPRIV + 1,
134 0, IW_PRIV_TYPE_ADDR | 16, "macget" },
135 { SIOCIWFIRSTPRIV + 6,
136 IW_PRIV_TYPE_FLOAT | IW_PRIV_SIZE_FIXED | 1, 0, "setfloat" },
139 static const iw_handler sample_private_handler[] =
140 { /* SIOCIWFIRSTPRIV + */
141 #if WIRELESS_EXT >= 15
142 /* Various little annoying bugs in the new API before
143 * version 15 make it difficult to use the new API for those ioctls.
144 * For example, it doesn't know about the new data type.
145 * Rather than littering the code with workarounds,
146 * let's use the regular ioctl handler. - Jean II */
147 (iw_handler) sample_ioctl_set_mac, /* 0 */
148 (iw_handler) sample_ioctl_get_mac, /* 1 */
149 (iw_handler) sample_ioctl_set_addr, /* 2 */
150 (iw_handler) NULL, /* 3 */
151 (iw_handler) sample_ioctl_set_addr, /* 4 */
152 (iw_handler) NULL, /* 5 */
153 (iw_handler) sample_ioctl_set_float, /* 6 */
154 #endif /* WIRELESS_EXT >= 15 */
157 #if WIRELESS_EXT < 15
158 /* Various little annoying bugs in the new API before
159 * version 15 make it difficult to use those ioctls.
160 * For example, it doesn't know about the new data type.
161 * Rather than littering the code with workarounds,
162 * let's use this code that just works. - Jean II */
163 case SIOCIWFIRSTPRIV + 0:
164 if (wrq->u.data.length > 1)
166 else if (wrq->u.data.pointer) {
167 struct sockaddr mac_addr;
168 if (copy_from_user(&mac_addr, wrq->u.data.pointer,
169 sizeof(struct sockaddr))) {
173 ret = sample_ioctl_set_mac(dev, NULL, &wrq->u.data,
177 case SIOCIWFIRSTPRIV + 2:
178 case SIOCIWFIRSTPRIV + 4:
179 if (!capable(CAP_NET_ADMIN))
182 struct iw_request_info info;
184 ret = sample_ioctl_set_addr(dev, &info,
189 case SIOCIWFIRSTPRIV + 1:
190 if (wrq->u.essid.pointer) {
191 struct sockaddr mac_addr[16];
192 char nickbuf[IW_ESSID_MAX_SIZE + 1];
193 ret = sample_ioctl_get_mac(dev, NULL, &wrq->u.data,
195 if (copy_to_user(wrq->u.data.pointer, nickbuf,
197 sizeof(struct sockaddr)))
201 case SIOCIWFIRSTPRIV + 6:
202 if (!capable(CAP_NET_ADMIN))
205 ret = sample_ioctl_set_float(dev, NULL,
210 #endif /* WIRELESS_EXT < 15 */