+/*------------------------------------------------------------------*/
+/*
+ * Get essential wireless config from the device driver
+ * We will call all the classical wireless ioctl on the driver through
+ * the socket to know what is supported and to get the settings...
+ * Note : compare to the version in iwconfig, we extract only
+ * what's *really* needed to configure a device...
+ */
+int
+iw_get_basic_config(int skfd,
+ char * ifname,
+ wireless_config * info)
+{
+ struct iwreq wrq;
+
+ memset((char *) info, 0, sizeof(struct wireless_config));
+
+ /* Get wireless name */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
+ /* If no wireless name : no wireless extensions */
+ return(-1);
+ else
+ strcpy(info->name, wrq.u.name);
+
+ /* Get network ID */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0)
+ {
+ info->has_nwid = 1;
+ memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
+ }
+
+ /* Get frequency / channel */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0)
+ {
+ info->has_freq = 1;
+ info->freq = iw_freq2float(&(wrq.u.freq));
+ }
+
+ /* Get encryption information */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ wrq.u.data.pointer = (caddr_t) info->key;
+ wrq.u.data.length = 0;
+ wrq.u.data.flags = 0;
+ if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0)
+ {
+ info->has_key = 1;
+ info->key_size = wrq.u.data.length;
+ info->key_flags = wrq.u.data.flags;
+ }
+
+ /* Get ESSID */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ wrq.u.essid.pointer = (caddr_t) info->essid;
+ wrq.u.essid.length = 0;
+ wrq.u.essid.flags = 0;
+ if(ioctl(skfd, SIOCGIWESSID, &wrq) >= 0)
+ {
+ info->has_essid = 1;
+ info->essid_on = wrq.u.data.flags;
+ }
+
+ /* Get operation mode */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ if(ioctl(skfd, SIOCGIWMODE, &wrq) >= 0)
+ {
+ if((wrq.u.mode < 6) && (wrq.u.mode >= 0))
+ info->has_mode = 1;
+ info->mode = wrq.u.mode;
+ }
+
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Set essential wireless config in the device driver
+ * We will call all the classical wireless ioctl on the driver through
+ * the socket to know what is supported and to set the settings...
+ * We support only the restricted set as above...
+ */
+int
+iw_set_basic_config(int skfd,
+ char * ifname,
+ wireless_config * info)
+{
+ struct iwreq wrq;
+ int ret = 0;
+
+ /* Get wireless name (check if interface is valid) */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ if(ioctl(skfd, SIOCGIWNAME, &wrq) < 0)
+ /* If no wireless name : no wireless extensions */
+ return(-2);
+
+ /* Set Network ID, if available (this is for non-802.11 cards) */
+ if(info->has_nwid)
+ {
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
+ wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */
+
+ if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
+ ret = -1;
+ }
+ }
+
+ /* Set frequency / channel */
+ if(info->has_freq)
+ {
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ iw_float2freq(info->freq, &(wrq.u.freq));
+
+ if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
+ ret = -1;
+ }
+ }
+
+ /* Set encryption information */
+ if(info->has_key)
+ {
+ int flags = info->key_flags;
+
+ /* Check if there is a key index */
+ if((flags & IW_ENCODE_INDEX) > 0)
+ {
+ /* Set the index */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ wrq.u.data.pointer = (caddr_t) NULL;
+ wrq.u.data.flags = flags & (IW_ENCODE_INDEX);
+ wrq.u.data.length = 0;
+
+ if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
+ errno, strerror(errno));
+ ret = -1;
+ }
+ }
+
+ /* Mask out index to minimise probability of reject when setting key */
+ flags = flags & (~IW_ENCODE_INDEX);
+
+ /* Set the key itself (set current key in this case) */
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ wrq.u.data.pointer = (caddr_t) info->key;
+ wrq.u.data.length = info->key_size;
+ wrq.u.data.flags = flags;
+
+ if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
+ errno, strerror(errno));
+ ret = -1;
+ }
+ }
+
+ /* Set ESSID (extended network), if available */
+ if(info->has_essid)
+ {
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ wrq.u.essid.pointer = (caddr_t) info->essid;
+ wrq.u.essid.length = strlen(info->essid) + 1;
+ wrq.u.data.flags = info->essid_on;
+
+ if(ioctl(skfd, SIOCSIWESSID, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
+ ret = -1;
+ }
+ }
+
+ /* Set the current mode of operation */
+ if(info->has_mode)
+ {
+ strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
+ wrq.u.mode = info->mode;
+
+ if(ioctl(skfd, SIOCSIWMODE, &wrq) < 0)
+ {
+ fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
+ ret = -1;
+ }
+ }
+
+ return(ret);
+}
+