📄 sample_priv_addr.c
字号:
/* 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 testingstatic 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -