4 * Jean II - HPLB 97->99 - HPL 99->00
6 * Common subroutines to all the wireless tools...
8 * This file is released under the GPL license.
11 #include "iwcommon.h" /* Header */
13 /************************ SOCKET SUBROUTINES *************************/
15 /*------------------------------------------------------------------*/
18 * Depending on the protocol present, open the right socket. The socket
19 * will allow us to talk to the driver.
24 int ipx_sock = -1; /* IPX socket */
25 int ax25_sock = -1; /* AX.25 socket */
26 int inet_sock = -1; /* INET socket */
27 int ddp_sock = -1; /* Appletalk DDP socket */
29 inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
30 ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
31 ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
32 ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
34 * Now pick any (exisiting) useful socket family for generic queries
43 * If this is -1 we have no known network layers and its time to jump.
49 /*********************** WIRELESS SUBROUTINES ************************/
51 /*------------------------------------------------------------------*/
53 * Get the range information out of the driver
56 get_range_info(int skfd,
61 char buffer[sizeof(iwrange) * 2]; /* Large enough */
64 memset(buffer, 0, sizeof(range));
66 strcpy(wrq.ifr_name, ifname);
67 wrq.u.data.pointer = (caddr_t) buffer;
68 wrq.u.data.length = 0;
70 if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0)
73 /* Copy stuff at the right place, ignore extra */
74 memcpy((char *) range, buffer, sizeof(iwrange));
76 /* Lot's of people have driver and tools out of sync as far as Wireless
77 * Extensions are concerned. It's because /usr/include/linux/wireless.h
78 * and /usr/src/linux/include/linux/wireless.h are different.
79 * We try to catch this stuff here... */
81 /* For new versions, we can check the version directly, for old versions
82 * we use magic. 300 bytes is a also magic number, don't touch... */
83 if((WIRELESS_EXT > 10) && (wrq.u.data.length >= 300))
86 /* Version verification - for new versions */
87 if(range->we_version_compiled != WIRELESS_EXT)
89 fprintf(stderr, "Warning : Device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
90 fprintf(stderr, "of Wireless Extension, while we are using version %d.\n", WIRELESS_EXT);
91 fprintf(stderr, "Some things may be broken...\n\n");
93 #endif /* WIRELESS_EXT > 10 */
97 /* Version verification - for old versions */
98 if(wrq.u.data.length != sizeof(iwrange))
100 fprintf(stderr, "Warning : Device %s has been compiled with a different version\n", ifname);
101 fprintf(stderr, "of Wireless Extension than ours (we are using version %d).\n", WIRELESS_EXT);
102 fprintf(stderr, "Some things may be broken...\n\n");
106 /* Note : we are only trying to catch compile difference, not source.
107 * If the driver source has not been updated to the latest, it doesn't
108 * matter because the new fields are set to zero */
113 /*------------------------------------------------------------------*/
115 * Get information about what private ioctls are supported by the driver
118 get_priv_info(int skfd,
125 strcpy(wrq.ifr_name, ifname);
126 wrq.u.data.pointer = (caddr_t) priv;
127 wrq.u.data.length = 0;
128 wrq.u.data.flags = 0;
129 if(ioctl(skfd, SIOCGIWPRIV, &wrq) < 0)
132 /* Return the number of ioctls */
133 return(wrq.u.data.length);
136 /********************** FREQUENCY SUBROUTINES ***********************/
138 /*------------------------------------------------------------------*/
140 * Convert a floating point the our internal representation of
142 * The kernel doesn't want to hear about floating point, so we use
143 * this custom format instead.
146 float2freq(double in,
149 out->e = (short) (floor(log10(in)));
152 out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100;
162 /*------------------------------------------------------------------*/
164 * Convert our internal representation of frequencies to a floating point.
167 freq2float(iwfreq * in)
169 return ((double) in->m) * pow(10,in->e);
172 /************************ POWER SUBROUTINES *************************/
174 /*------------------------------------------------------------------*/
176 * Convert a value in dBm to a value in milliWatt.
181 return((int) (floor(pow(10.0, (((double) in) / 10.0)))));
184 /*------------------------------------------------------------------*/
186 * Convert a value in milliWatt to a value in dBm.
191 return((int) (ceil(10.0 * log10((double) in))));
194 /********************** STATISTICS SUBROUTINES **********************/
196 /*------------------------------------------------------------------*/
198 * Output the link statistics, taking care of formating
201 print_stats(FILE * stream,
207 if(has_range && (qual->level != 0))
209 /* If the statistics are in dBm */
210 if(qual->level > range->max_qual.level)
212 /* Statistics are in dBm (absolute power measurement) */
214 "Quality:%d/%d Signal level:%d dBm Noise level:%d dBm%s\n",
215 qual->qual, range->max_qual.qual,
216 qual->level - 0x100, qual->noise - 0x100,
217 (qual->updated & 0x7) ? " (updated)" : "");
221 /* Statistics are relative values (0 -> max) */
223 "Quality:%d/%d Signal level:%d/%d Noise level:%d/%d%s\n",
224 qual->qual, range->max_qual.qual,
225 qual->level, range->max_qual.level,
226 qual->noise, range->max_qual.noise,
227 (qual->updated & 0x7) ? " (updated)" : "");
232 /* We can't read the range, so we don't know... */
233 fprintf(stream, "Quality:%d Signal level:%d Noise level:%d%s\n",
234 qual->qual, qual->level, qual->noise,
235 (qual->updated & 0x7) ? " (updated)" : "");
239 /*********************** ENCODING SUBROUTINES ***********************/
241 /*------------------------------------------------------------------*/
243 * Output the encoding key, with a nice formating
246 print_key(FILE * stream,
253 /* Is the key present ??? */
254 if(key_flags & IW_ENCODE_NOKEY)
256 /* Nope : print dummy */
258 for(i = 1; i < key_size; i++)
267 /* Yes : print the key */
268 printf("%.2X", key[0]);
269 for(i = 1; i < key_size; i++)
273 printf("%.2X", key[i]);
279 /******************* POWER MANAGEMENT SUBROUTINES *******************/
281 /*------------------------------------------------------------------*/
283 * Output a power management value with all attributes...
286 print_pm_value(FILE * stream,
291 if(flags & IW_POWER_MIN)
292 fprintf(stream, " min");
293 if(flags & IW_POWER_MAX)
294 fprintf(stream, " max");
297 if(flags & IW_POWER_TIMEOUT)
298 fprintf(stream, " timeout:");
300 fprintf(stream, " period:");
302 /* Display value without units */
303 if(flags & IW_POWER_RELATIVE)
304 fprintf(stream, "%g ", ((double) value) / MEGA);
307 /* Display value with units */
308 if(value >= (int) MEGA)
309 fprintf(stream, "%gs ", ((double) value) / MEGA);
311 if(value >= (int) KILO)
312 fprintf(stream, "%gms ", ((double) value) / KILO);
314 fprintf(stream, "%dus ", value);
318 /*------------------------------------------------------------------*/
320 * Output a power management mode
323 print_pm_mode(FILE * stream,
326 /* Print the proper mode... */
327 switch(flags & IW_POWER_MODE)
329 case IW_POWER_UNICAST_R:
330 fprintf(stream, " mode:Unicast only received");
332 case IW_POWER_MULTICAST_R:
333 fprintf(stream, " mode:Multicast only received");
336 fprintf(stream, " mode:All packets received");
338 case IW_POWER_FORCE_S:
339 fprintf(stream, " mode:Force sending");
341 case IW_POWER_REPEATER:
342 fprintf(stream, " mode:Repeat multicasts");
348 /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
350 #if WIRELESS_EXT > 10
351 /*------------------------------------------------------------------*/
353 * Output a retry value with all attributes...
356 print_retry_value(FILE * stream,
361 if(flags & IW_RETRY_MIN)
362 fprintf(stream, " min");
363 if(flags & IW_RETRY_MAX)
364 fprintf(stream, " max");
366 /* Type lifetime of limit */
367 if(flags & IW_RETRY_LIFETIME)
369 fprintf(stream, " lifetime:");
371 /* Display value without units */
372 if(flags & IW_POWER_RELATIVE)
373 fprintf(stream, "%g", ((double) value) / MEGA);
376 /* Display value with units */
377 if(value >= (int) MEGA)
378 fprintf(stream, "%gs", ((double) value) / MEGA);
380 if(value >= (int) KILO)
381 fprintf(stream, "%gms", ((double) value) / KILO);
383 fprintf(stream, "%dus", value);
387 fprintf(stream, " limit:%d", value);
389 #endif /* WIRELESS_EXT > 10 */
391 /*********************** ADDRESS SUBROUTINES ************************/
393 * This section is mostly a cut & past from net-tools-1.2.0
394 * manage address display and input...
397 /*------------------------------------------------------------------*/
399 * Check if interface support the right address types...
402 check_addr_type(int skfd,
407 /* Get the type of interface address */
408 strcpy(ifr.ifr_name, ifname);
409 if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) ||
410 (ifr.ifr_addr.sa_family != AF_INET))
412 /* Deep trouble... */
413 fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname);
418 printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family,
419 *((unsigned long *) ifr.ifr_addr.sa_data));
422 /* Get the type of hardware address */
423 strcpy(ifr.ifr_name, ifname);
424 if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) ||
425 (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER))
427 /* Deep trouble... */
428 fprintf(stderr, "Interface %s doesn't support MAC addresses\n",
434 printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family,
435 pr_ether(ifr.ifr_hwaddr.sa_data));
442 /*------------------------------------------------------------------*/
444 * Display an Ethernet address in readable format.
447 pr_ether(unsigned char *ptr)
449 static char buff[64];
451 sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
452 (ptr[0] & 0xFF), (ptr[1] & 0xFF), (ptr[2] & 0xFF),
453 (ptr[3] & 0xFF), (ptr[4] & 0xFF), (ptr[5] & 0xFF)
458 /*------------------------------------------------------------------*/
460 * Input an Ethernet address and convert to binary.
463 in_ether(char *bufp, struct sockaddr *sap)
469 sap->sa_family = ARPHRD_ETHER;
474 while((*bufp != '\0') && (i < ETH_ALEN)) {
477 if (isdigit(c)) val = c - '0';
478 else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
479 else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
482 fprintf(stderr, "in_ether(%s): invalid ether address!\n", orig);
489 if (isdigit(c)) val |= c - '0';
490 else if (c >= 'a' && c <= 'f') val |= c - 'a' + 10;
491 else if (c >= 'A' && c <= 'F') val |= c - 'A' + 10;
494 fprintf(stderr, "in_ether(%s): invalid ether address!\n", orig);
499 *ptr++ = (unsigned char) (val & 0377);
502 /* We might get a semicolon here - not required. */
506 fprintf(stderr, "in_ether(%s): trailing : ignored!\n",
515 /* That's it. Any trailing junk? */
516 if ((i == ETH_ALEN) && (*bufp != '\0')) {
518 fprintf(stderr, "in_ether(%s): trailing junk!\n", orig);
525 fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data));
531 /*------------------------------------------------------------------*/
533 * Input an Internet address and convert to binary.
536 in_inet(char *bufp, struct sockaddr *sap)
541 struct sockaddr_in *sin = (struct sockaddr_in *) sap;
544 sin->sin_family = AF_INET;
547 /* Default is special, meaning 0.0.0.0. */
548 if (!strcmp(name, "default")) {
549 sin->sin_addr.s_addr = INADDR_ANY;
553 /* Try the NETWORKS database to see if this is a known network. */
554 if ((np = getnetbyname(name)) != (struct netent *)NULL) {
555 sin->sin_addr.s_addr = htonl(np->n_net);
556 strcpy(name, np->n_name);
560 if ((hp = gethostbyname(name)) == (struct hostent *)NULL) {
564 memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
565 strcpy(name, hp->h_name);
569 /*------------------------------------------------------------------*/
571 * Input an address and convert to binary.
577 struct sockaddr *sap)
579 /* Check if it is a hardware or IP address */
580 if(index(bufp, ':') == NULL)
582 struct sockaddr if_address;
583 struct arpreq arp_query;
585 /* Read interface address */
586 if(in_inet(bufp, &if_address) < 0)
588 fprintf(stderr, "Invalid interface address %s\n", bufp);
592 /* Translate IP addresses to MAC addresses */
593 memcpy((char *) &(arp_query.arp_pa),
594 (char *) &if_address,
595 sizeof(struct sockaddr));
596 arp_query.arp_ha.sa_family = 0;
597 arp_query.arp_flags = 0;
598 /* The following restrict the search to the interface only */
599 /* For old kernels which complain, just comment it... */
600 strcpy(arp_query.arp_dev, ifname);
601 if((ioctl(skfd, SIOCGARP, &arp_query) < 0) ||
602 !(arp_query.arp_flags & ATF_COM))
604 fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n",
605 bufp, ifname, errno);
609 /* Store new MAC address */
611 (char *) &(arp_query.arp_ha),
612 sizeof(struct sockaddr));
615 printf("IP Address %s => Hw Address = %s\n",
616 bufp, pr_ether(sap->sa_data));
619 else /* If it's an hardware address */
620 /* Get the hardware address */
621 if(in_ether(bufp, sap) < 0)
623 fprintf(stderr, "Invalid hardware address %s\n", bufp);
628 printf("Hw Address = %s\n", pr_ether(sap->sa_data));
634 /************************* MISC SUBROUTINES **************************/
636 /*------------------------------------------------------------------*/
642 int ret = args & IW_PRIV_SIZE_MASK;
644 if(((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_INT) ||
645 ((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_FLOAT))
648 if((args & IW_PRIV_TYPE_MASK) == IW_PRIV_TYPE_NONE)