sample_priv_addr.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. // Require Wireless Tools 25 for sub-ioctl and addr support
  6. /* --------------------------- INCLUDE --------------------------- */
  7. #if WIRELESS_EXT <= 12
  8. /* Wireless extensions backward compatibility */
  9. /* We need the full definition for private ioctls */
  10. struct iw_request_info
  11. {
  12. __u16 cmd; /* Wireless Extension command */
  13. __u16 flags; /* More to come ;-) */
  14. };
  15. #endif /* WIRELESS_EXT <= 12 */
  16. #ifndef IW_PRIV_TYPE_ADDR
  17. #define IW_PRIV_TYPE_ADDR 0x6000
  18. #endif /* IW_PRIV_TYPE_ADDR */
  19. /* --------------------------- HANDLERS --------------------------- */
  20. /* First method : using sub-ioctls.
  21. * Note that sizeof(int + struct sockaddr) = 20 > 16, therefore the
  22. * data is passed in (char *) extra, and sub-ioctl in data->flags. */
  23. static int sample_ioctl_set_mac(struct net_device *dev,
  24. struct iw_request_info *info,
  25. struct iw_point *data,
  26. struct sockaddr *mac_addr)
  27. {
  28. unsigned char * addr = (char *) &mac_addr->sa_data;
  29. switch(data->flags) {
  30. case 0:
  31. 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]);
  32. break;
  33. case 1:
  34. 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]);
  35. break;
  36. case 2:
  37. 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]);
  38. break;
  39. default:
  40. 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]);
  41. break;
  42. }
  43. return 0;
  44. }
  45. /* Second method : bind single handler to multiple ioctls.
  46. * Note that sizeof(struct sockaddr) = 16 <= 16, therefore the
  47. * data is passed in (struct iwreq) (and also mapped in extra).
  48. */
  49. static int sample_ioctl_set_addr(struct net_device *dev,
  50. struct iw_request_info *info,
  51. struct sockaddr *mac_addr, char *extra)
  52. {
  53. unsigned char * addr = (char *) &mac_addr->sa_data;
  54. switch(info->cmd) {
  55. case SIOCIWFIRSTPRIV + 28:
  56. 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]);
  57. break;
  58. case SIOCIWFIRSTPRIV + 30:
  59. 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]);
  60. break;
  61. default:
  62. 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]);
  63. break;
  64. }
  65. return 0;
  66. }
  67. // Extra fun for testing
  68. static int sample_ioctl_get_mac(struct net_device *dev,
  69. struct iw_request_info *info,
  70. struct iw_point *data,
  71. struct sockaddr *mac_addr)
  72. {
  73. unsigned char fake_addr[6];
  74. int i;
  75. int j;
  76. for(i = 0; i < 16; i++) {
  77. /* Create a fake address */
  78. for(j = 0; j < 6; j++)
  79. fake_addr[j] = (unsigned char) ((j << 4) + i);
  80. /* Put in in the table */
  81. memcpy(&(mac_addr[i]).sa_data, fake_addr, ETH_ALEN);
  82. mac_addr[i].sa_family = ARPHRD_ETHER;
  83. }
  84. data->length = 16;
  85. return 0;
  86. }
  87. static int sample_ioctl_set_float(struct net_device *dev,
  88. struct iw_request_info *info,
  89. struct iw_freq *freq, char *extra)
  90. {
  91. printk(KERN_DEBUG "%s: set_float %d;%d\n",
  92. dev->name, freq->m, freq->e);
  93. return 0;
  94. }
  95. /* --------------------------- BINDING --------------------------- */
  96. static const struct iw_priv_args sample_priv[] = {
  97. // *** Method 1 : using sub-ioctls ***
  98. /* --- sub-ioctls handler --- */
  99. { SIOCIWFIRSTPRIV + 0,
  100. IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "" },
  101. /* --- sub-ioctls definitions --- */
  102. { 0,
  103. IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macadd" },
  104. { 1,
  105. IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macdel" },
  106. { 2,
  107. IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "mackick" },
  108. // *** Method 2 : binding one handler to multiple ioctls ***
  109. { SIOCIWFIRSTPRIV + 2,
  110. IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addradd" },
  111. { SIOCIWFIRSTPRIV + 4,
  112. IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addrdel" },
  113. // *** Extra fun ***
  114. { SIOCIWFIRSTPRIV + 1,
  115. 0, IW_PRIV_TYPE_ADDR | 16, "macget" },
  116. { SIOCIWFIRSTPRIV + 6,
  117. IW_PRIV_TYPE_FLOAT | IW_PRIV_SIZE_FIXED | 1, 0, "setfloat" },
  118. };
  119. static const iw_handler sample_private_handler[] =
  120. { /* SIOCIWFIRSTPRIV + */
  121. #if WIRELESS_EXT >= 15
  122. /* Various little annoying bugs in the new API before
  123. * version 15 make it difficult to use the new API for those ioctls.
  124. * For example, it doesn't know about the new data type.
  125. * Rather than littering the code with workarounds,
  126. * let's use the regular ioctl handler. - Jean II */
  127. (iw_handler) sample_ioctl_set_mac, /* 0 */
  128. (iw_handler) sample_ioctl_get_mac, /* 1 */
  129. (iw_handler) sample_ioctl_set_addr, /* 2 */
  130. (iw_handler) NULL, /* 3 */
  131. (iw_handler) sample_ioctl_set_addr, /* 4 */
  132. (iw_handler) NULL, /* 5 */
  133. (iw_handler) sample_ioctl_set_float, /* 6 */
  134. #endif /* WIRELESS_EXT >= 15 */
  135. };
  136. #if WIRELESS_EXT < 15
  137. /* Various little annoying bugs in the new API before
  138. * version 15 make it difficult to use those ioctls.
  139. * For example, it doesn't know about the new data type.
  140. * Rather than littering the code with workarounds,
  141. * let's use this code that just works. - Jean II */
  142. case SIOCIWFIRSTPRIV + 0:
  143. if (wrq->u.data.length > 1)
  144. ret = -E2BIG;
  145. else if (wrq->u.data.pointer) {
  146. struct sockaddr mac_addr;
  147. if (copy_from_user(&mac_addr, wrq->u.data.pointer,
  148. sizeof(struct sockaddr))) {
  149. ret = -EFAULT;
  150. break;
  151. }
  152. ret = sample_ioctl_set_mac(dev, NULL, &wrq->u.data,
  153. &mac_addr);
  154. }
  155. break;
  156. case SIOCIWFIRSTPRIV + 2:
  157. case SIOCIWFIRSTPRIV + 4:
  158. if (!capable(CAP_NET_ADMIN))
  159. ret = -EPERM;
  160. else {
  161. struct iw_request_info info;
  162. info.cmd = cmd;
  163. ret = sample_ioctl_set_addr(dev, &info,
  164. &wrq->u.ap_addr,
  165. NULL);
  166. }
  167. break;
  168. case SIOCIWFIRSTPRIV + 1:
  169. if (wrq->u.essid.pointer) {
  170. struct sockaddr mac_addr[16];
  171. char nickbuf[IW_ESSID_MAX_SIZE + 1];
  172. ret = sample_ioctl_get_mac(dev, NULL, &wrq->u.data,
  173. mac_addr);
  174. if (copy_to_user(wrq->u.data.pointer, nickbuf,
  175. wrq->u.data.length *
  176. sizeof(struct sockaddr)))
  177. ret = -EFAULT;
  178. }
  179. break;
  180. case SIOCIWFIRSTPRIV + 6:
  181. if (!capable(CAP_NET_ADMIN))
  182. ret = -EPERM;
  183. else {
  184. ret = sample_ioctl_set_float(dev, NULL,
  185. &wrq->u.freq,
  186. NULL);
  187. }
  188. break;
  189. #endif /* WIRELESS_EXT < 15 */