OSDN Git Service

Add Android.mk
[android-x86/external-wireless-tools.git] / wireless_tools / sample_priv_addr.c
1 /* Note : this particular snipset of code is available under
2  * the LGPL, MPL or BSD license (at your choice).
3  * Jean II
4  */
5
6 // Require Wireless Tools 25 for sub-ioctl and addr support
7
8 /* --------------------------- INCLUDE --------------------------- */
9
10 #if WIRELESS_EXT <= 12
11 /* Wireless extensions backward compatibility */
12
13 /* We need the full definition for private ioctls */
14 struct iw_request_info
15 {
16         __u16           cmd;            /* Wireless Extension command */
17         __u16           flags;          /* More to come ;-) */
18 };
19 #endif /* WIRELESS_EXT <= 12 */
20
21 #ifndef IW_PRIV_TYPE_ADDR
22 #define IW_PRIV_TYPE_ADDR       0x6000
23 #endif  /* IW_PRIV_TYPE_ADDR */
24
25 /* --------------------------- HANDLERS --------------------------- */
26
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)
34 {
35         unsigned char * addr = (char *) &mac_addr->sa_data;
36
37         switch(data->flags) {
38         case 0:
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]);
40                 break;
41         case 1:
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]);
43                 break;
44         case 2:
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]);
46                 break;
47         default:
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]);
49                 break;
50         }
51
52         return 0;
53 }
54
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).
58  */
59 static int sample_ioctl_set_addr(struct net_device *dev,
60                                  struct iw_request_info *info,
61                                  struct sockaddr *mac_addr, char *extra)
62 {
63         unsigned char * addr = (char *) &mac_addr->sa_data;
64
65         switch(info->cmd) {
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]);
68                 break;
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]);
71                 break;
72         default:
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]);
74                 break;
75         }
76
77         return 0;
78 }
79
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)
85 {
86         unsigned char   fake_addr[6];
87         int             i;
88         int             j;
89
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;
97         }
98         data->length = 16;
99
100         return 0;
101 }
102
103 static int sample_ioctl_set_float(struct net_device *dev,
104                                   struct iw_request_info *info,
105                                   struct iw_freq *freq, char *extra)
106 {
107         printk(KERN_DEBUG "%s: set_float %d;%d\n",
108                dev->name, freq->m, freq->e);
109
110         return 0;
111 }
112
113 /* --------------------------- BINDING --------------------------- */
114
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 --- */
121         { 0,
122           IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macadd" },
123         { 1,
124           IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macdel" },
125         { 2,
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" },
132         // *** Extra fun ***
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" },
137 };
138
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 */
155 };
156
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)
165                         ret = -E2BIG;
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))) {
170                                 ret = -EFAULT;
171                                 break;
172                         }
173                         ret = sample_ioctl_set_mac(dev, NULL, &wrq->u.data,
174                                                    &mac_addr);
175                 }
176                 break;
177         case SIOCIWFIRSTPRIV + 2:
178         case SIOCIWFIRSTPRIV + 4:
179                 if (!capable(CAP_NET_ADMIN))
180                         ret = -EPERM;
181                 else {
182                         struct iw_request_info info;
183                         info.cmd = cmd;
184                         ret = sample_ioctl_set_addr(dev, &info,
185                                                     &wrq->u.ap_addr,
186                                                     NULL);
187                 }
188                 break;
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,
194                                                    mac_addr);
195                         if (copy_to_user(wrq->u.data.pointer, nickbuf,
196                                          wrq->u.data.length *
197                                          sizeof(struct sockaddr)))
198                                 ret = -EFAULT;
199                 }
200                 break;
201         case SIOCIWFIRSTPRIV + 6:
202                 if (!capable(CAP_NET_ADMIN))
203                         ret = -EPERM;
204                 else {
205                         ret = sample_ioctl_set_float(dev, NULL,
206                                                      &wrq->u.freq,
207                                                      NULL);
208                 }
209                 break;
210 #endif  /* WIRELESS_EXT < 15 */