123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /* Note : this particular snipset of code is available under
- * the LGPL, MPL or BSD license (at your choice).
- * Jean II
- */
- // Require Wireless Tools 25 for sub-ioctl and addr support
- /* --------------------------- INCLUDE --------------------------- */
- #if WIRELESS_EXT <= 12
- /* Wireless extensions backward compatibility */
- /* We need the full definition for private ioctls */
- struct iw_request_info
- {
- __u16 cmd; /* Wireless Extension command */
- __u16 flags; /* More to come ;-) */
- };
- #endif /* WIRELESS_EXT <= 12 */
- #ifndef IW_PRIV_TYPE_ADDR
- #define IW_PRIV_TYPE_ADDR 0x6000
- #endif /* IW_PRIV_TYPE_ADDR */
- /* --------------------------- HANDLERS --------------------------- */
- /* First method : using sub-ioctls.
- * Note that sizeof(int + struct sockaddr) = 20 > 16, therefore the
- * data is passed in (char *) extra, and sub-ioctl in data->flags. */
- static int sample_ioctl_set_mac(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data,
- struct sockaddr *mac_addr)
- {
- unsigned char * addr = (char *) &mac_addr->sa_data;
- switch(data->flags) {
- case 0:
- 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]);
- break;
- case 1:
- 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]);
- break;
- case 2:
- 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]);
- break;
- default:
- 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]);
- break;
- }
- return 0;
- }
- /* Second method : bind single handler to multiple ioctls.
- * Note that sizeof(struct sockaddr) = 16 <= 16, therefore the
- * data is passed in (struct iwreq) (and also mapped in extra).
- */
- static int sample_ioctl_set_addr(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *mac_addr, char *extra)
- {
- unsigned char * addr = (char *) &mac_addr->sa_data;
- switch(info->cmd) {
- case SIOCIWFIRSTPRIV + 28:
- 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]);
- break;
- case SIOCIWFIRSTPRIV + 30:
- 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]);
- break;
- default:
- 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]);
- break;
- }
- return 0;
- }
- // Extra fun for testing
- static int sample_ioctl_get_mac(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data,
- struct sockaddr *mac_addr)
- {
- unsigned char fake_addr[6];
- int i;
- int j;
- for(i = 0; i < 16; i++) {
- /* Create a fake address */
- for(j = 0; j < 6; j++)
- fake_addr[j] = (unsigned char) ((j << 4) + i);
- /* Put in in the table */
- memcpy(&(mac_addr[i]).sa_data, fake_addr, ETH_ALEN);
- mac_addr[i].sa_family = ARPHRD_ETHER;
- }
- data->length = 16;
- return 0;
- }
- static int sample_ioctl_set_float(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
- {
- printk(KERN_DEBUG "%s: set_float %d;%d\n",
- dev->name, freq->m, freq->e);
- return 0;
- }
- /* --------------------------- BINDING --------------------------- */
- static const struct iw_priv_args sample_priv[] = {
- // *** Method 1 : using sub-ioctls ***
- /* --- sub-ioctls handler --- */
- { SIOCIWFIRSTPRIV + 0,
- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "" },
- /* --- sub-ioctls definitions --- */
- { 0,
- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macadd" },
- { 1,
- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macdel" },
- { 2,
- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "mackick" },
- // *** Method 2 : binding one handler to multiple ioctls ***
- { SIOCIWFIRSTPRIV + 2,
- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addradd" },
- { SIOCIWFIRSTPRIV + 4,
- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addrdel" },
- // *** Extra fun ***
- { SIOCIWFIRSTPRIV + 1,
- 0, IW_PRIV_TYPE_ADDR | 16, "macget" },
- { SIOCIWFIRSTPRIV + 6,
- IW_PRIV_TYPE_FLOAT | IW_PRIV_SIZE_FIXED | 1, 0, "setfloat" },
- };
- static const iw_handler sample_private_handler[] =
- { /* SIOCIWFIRSTPRIV + */
- #if WIRELESS_EXT >= 15
- /* Various little annoying bugs in the new API before
- * version 15 make it difficult to use the new API for those ioctls.
- * For example, it doesn't know about the new data type.
- * Rather than littering the code with workarounds,
- * let's use the regular ioctl handler. - Jean II */
- (iw_handler) sample_ioctl_set_mac, /* 0 */
- (iw_handler) sample_ioctl_get_mac, /* 1 */
- (iw_handler) sample_ioctl_set_addr, /* 2 */
- (iw_handler) NULL, /* 3 */
- (iw_handler) sample_ioctl_set_addr, /* 4 */
- (iw_handler) NULL, /* 5 */
- (iw_handler) sample_ioctl_set_float, /* 6 */
- #endif /* WIRELESS_EXT >= 15 */
- };
- #if WIRELESS_EXT < 15
- /* Various little annoying bugs in the new API before
- * version 15 make it difficult to use those ioctls.
- * For example, it doesn't know about the new data type.
- * Rather than littering the code with workarounds,
- * let's use this code that just works. - Jean II */
- case SIOCIWFIRSTPRIV + 0:
- if (wrq->u.data.length > 1)
- ret = -E2BIG;
- else if (wrq->u.data.pointer) {
- struct sockaddr mac_addr;
- if (copy_from_user(&mac_addr, wrq->u.data.pointer,
- sizeof(struct sockaddr))) {
- ret = -EFAULT;
- break;
- }
- ret = sample_ioctl_set_mac(dev, NULL, &wrq->u.data,
- &mac_addr);
- }
- break;
- case SIOCIWFIRSTPRIV + 2:
- case SIOCIWFIRSTPRIV + 4:
- if (!capable(CAP_NET_ADMIN))
- ret = -EPERM;
- else {
- struct iw_request_info info;
- info.cmd = cmd;
- ret = sample_ioctl_set_addr(dev, &info,
- &wrq->u.ap_addr,
- NULL);
- }
- break;
- case SIOCIWFIRSTPRIV + 1:
- if (wrq->u.essid.pointer) {
- struct sockaddr mac_addr[16];
- char nickbuf[IW_ESSID_MAX_SIZE + 1];
- ret = sample_ioctl_get_mac(dev, NULL, &wrq->u.data,
- mac_addr);
- if (copy_to_user(wrq->u.data.pointer, nickbuf,
- wrq->u.data.length *
- sizeof(struct sockaddr)))
- ret = -EFAULT;
- }
- break;
- case SIOCIWFIRSTPRIV + 6:
- if (!capable(CAP_NET_ADMIN))
- ret = -EPERM;
- else {
- ret = sample_ioctl_set_float(dev, NULL,
- &wrq->u.freq,
- NULL);
- }
- break;
- #endif /* WIRELESS_EXT < 15 */
|