--- /dev/null
+/* Note : this particular snipset of code is available under
+ * the LGPL, MPL or BSD license (at your choice).
+ * Jean II
+ */
+
+/* --------------------------- INCLUDE --------------------------- */
+
+#define MAX_KEY_SIZE 16
+#define MAX_KEYS 8
+int key_on = 0;
+int key_open = 1;
+int key_current = 0;
+char key_table[MAX_KEYS][MAX_KEY_SIZE];
+int key_size[MAX_KEYS];
+
+/* --------------------------- HANDLERS --------------------------- */
+
+static int ioctl_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq,
+ char *key)
+{
+ int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+
+ if (erq->length > 0)
+ {
+ /* Check the size of the key */
+ if(erq->length > MAX_KEY_SIZE)
+ return(-EINVAL);
+
+ /* Check the index */
+ if((index < 0) || (index >= MAX_KEYS))
+ index = key_current;
+
+ /* Copy the key in the driver */
+ memcpy(key_table[index], key, erq->length);
+ key_size[index] = erq->length;
+ key_on = 1;
+ }
+ else
+ {
+ /* Do we want to just set the current key ? */
+ if((index >= 0) && (index < MAX_KEYS))
+ {
+ if(key_size[index] > 0)
+ {
+ key_current = index;
+ key_on = 1;
+ }
+ else
+ return(-EINVAL);
+ }
+ }
+
+ /* Read the flags */
+ if(erq->flags & IW_ENCODE_DISABLED)
+ key_on = 0; /* disable encryption */
+ if(erq->flags & IW_ENCODE_RESTRICTED)
+ key_open = 0; /* disable open mode */
+ if(erq->flags & IW_ENCODE_OPEN)
+ key_open = 1; /* enable open mode */
+
+ return(0);
+}
+
+static int ioctl_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq,
+ char *key)
+{
+ int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+
+ /* Set the flags */
+ erq->flags = 0;
+ if(key_on == 0)
+ erq->flags |= IW_ENCODE_DISABLED;
+ if(key_open == 0)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ else
+ erq->flags |= IW_ENCODE_OPEN;
+
+ /* Which key do we want */
+ if((index < 0) || (index >= MAX_KEYS))
+ index = key_current;
+ erq->flags |= index + 1;
+
+ /* Copy the key to the user buffer */
+ erq->length = key_size[index];
+ memcpy(key, key_table[index], key_size[index]);
+
+ return(0);
+}
+
+static int ioctl_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *rrq,
+ char *extra)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+
+ rrq->length = sizeof(struct iw_range);
+
+ memset(range, 0, sizeof(struct iw_range));
+
+#if WIRELESS_EXT > 10
+ /* Version we are compiled with */
+ range->we_version_compiled = WIRELESS_EXT;
+ /* Minimum version we recommend */
+ range->we_version_source = 8;
+#endif /* WIRELESS_EXT > 10 */
+
+#if WIRELESS_EXT > 8
+ range->encoding_size[0] = 8; /* DES = 64 bits key */
+ range->encoding_size[1] = 16;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = 8;
+#endif /* WIRELESS_EXT > 8 */
+ return(0);
+}
+
+/* --------------------------- BINDING --------------------------- */
+
+#if WIRELESS_EXT > 12
+static const iw_handler handler_table[] =
+{
+ ...
+ (iw_handler) ioctl_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) ioctl_get_encode, /* SIOCGIWENCODE */
+};
+#else /* WIRELESS_EXT < 12 */
+static int
+do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct iwreq *wrq = (struct iwreq *) ifr;
+ int err = 0;
+
+ switch (cmd)
+ {
+#if WIRELESS_EXT > 8
+ case SIOCSIWENCODE:
+ {
+ char keybuf[MAX_KEY_SIZE];
+ if(wrq->u.encoding.pointer)
+ {
+ /* We actually have a key to set */
+ if(wrq->u.encoding.length > MAX_KEY_SIZE)
+ {
+ err = -E2BIG;
+ break;
+ }
+ if(copy_from_user(keybuf, wrq->u.encoding.pointer,
+ wrq->u.encoding.length))
+ {
+ err = -EFAULT;
+ break;
+ }
+ }
+ else
+ if(wrq->u.encoding.length != 0)
+ {
+ err = -EINVAL;
+ break;
+ }
+ err = ioctl_set_encode(dev, NULL, &(wrq->u.encoding), keybuf);
+ }
+ break;
+
+ case SIOCGIWENCODE:
+ /* only super-user can see encryption key */
+ if(! capable(CAP_NET_ADMIN))
+ {
+ err = -EPERM;
+ break;
+ }
+ {
+ char keybuf[MAX_KEY_SIZE];
+ err = ioctl_get_encode(dev, NULL, &(wrq->u.encoding), keybuf);
+ if(wrq->u.encoding.pointer)
+ {
+ if (copy_to_user(wrq->u.encoding.pointer, keybuf,
+ wrq->u.encoding.length))
+ err= -EFAULT;
+ }
+ }
+ break;
+#endif /* WIRELESS_EXT > 8 */
+ }
+ return(err);
+}
+#endif /* WIRELESS_EXT < 12 */
+