📄 iwlib.c
字号:
eth->ether_addr_octet[i] = (unsigned char) (val & 0377); if(++i == ETH_ALEN) { /* That's it. Any trailing junk? */ if (*bufp != '\0') {#ifdef DEBUG fprintf(stderr, "iw_ether_aton(%s): trailing junk!\n", orig); errno = EINVAL; return(0);#endif }#ifdef DEBUG fprintf(stderr, "iw_ether_aton(%s): %s\n", orig, ether_ntoa(eth));#endif return(1); } if (*bufp != ':') break; }#ifdef DEBUG fprintf(stderr, "iw_ether_aton(%s): invalid ether address!\n", orig);#endif errno = EINVAL; return(0);}/*------------------------------------------------------------------*//* * Input an Internet address and convert to binary. */intiw_in_inet(char *name, struct sockaddr *sap){ struct hostent *hp; struct netent *np; struct sockaddr_in *sain = (struct sockaddr_in *) sap; /* Grmpf. -FvK */ sain->sin_family = AF_INET; sain->sin_port = 0; /* Default is special, meaning 0.0.0.0. */ if (!strcmp(name, "default")) { sain->sin_addr.s_addr = INADDR_ANY; return(1); } /* Try the NETWORKS database to see if this is a known network. */ if ((np = getnetbyname(name)) != (struct netent *)NULL) { sain->sin_addr.s_addr = htonl(np->n_net); strcpy(name, np->n_name); return(1); } /* Always use the resolver (DNS name + IP addresses) */ if ((hp = gethostbyname(name)) == (struct hostent *)NULL) { errno = h_errno; return(-1); } memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length); strcpy(name, hp->h_name); return(0);}/*------------------------------------------------------------------*//* * Input an address and convert to binary. */intiw_in_addr(int skfd, char * ifname, char * bufp, struct sockaddr *sap){ /* Check if it is a hardware or IP address */ if(index(bufp, ':') == NULL) { struct sockaddr if_address; struct arpreq arp_query; /* Check if we have valid interface address type */ if(iw_check_if_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support IP addresses\n", ifname); return(-1); } /* Read interface address */ if(iw_in_inet(bufp, &if_address) < 0) { fprintf(stderr, "Invalid interface address %s\n", bufp); return(-1); } /* Translate IP addresses to MAC addresses */ memcpy((char *) &(arp_query.arp_pa), (char *) &if_address, sizeof(struct sockaddr)); arp_query.arp_ha.sa_family = 0; arp_query.arp_flags = 0; /* The following restrict the search to the interface only */ /* For old kernels which complain, just comment it... */ strncpy(arp_query.arp_dev, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGARP, &arp_query) < 0) || !(arp_query.arp_flags & ATF_COM)) { fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n", bufp, ifname, errno); return(-1); } /* Store new MAC address */ memcpy((char *) sap, (char *) &(arp_query.arp_ha), sizeof(struct sockaddr));#ifdef DEBUG printf("IP Address %s => Hw Address = %s\n", bufp, iw_ether_ntoa((struct ether_addr *) sap->sa_data));#endif } else /* If it's an hardware address */ { /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname); return(-1); } /* Get the hardware address */ if(iw_in_ether(bufp, sap) < 0) { fprintf(stderr, "Invalid hardware address %s\n", bufp); return(-1); } }#ifdef DEBUG printf("Hw Address = %s\n", iw_ether_ntoa((struct ether_addr *) sap->sa_data));#endif return(0);}/************************* MISC SUBROUTINES **************************//* Size (in bytes) of various events */static const int priv_type_size[] = { 0, /* IW_PRIV_TYPE_NONE */ 1, /* IW_PRIV_TYPE_BYTE */ 1, /* IW_PRIV_TYPE_CHAR */ 0, /* Not defined */ sizeof(__u32), /* IW_PRIV_TYPE_INT */ sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 0, /* Not defined */};/*------------------------------------------------------------------*//* * Max size in bytes of an private argument. */intiw_get_priv_size(int args){ int num = args & IW_PRIV_SIZE_MASK; int type = (args & IW_PRIV_TYPE_MASK) >> 12; return(num * priv_type_size[type]);}/************************ EVENT SUBROUTINES ************************//* * The Wireless Extension API 14 and greater define Wireless Events, * that are used for various events and scanning. * Those functions help the decoding of events, so are needed only in * this case. *//* Type of headers we know about (basically union iwreq_data) */#define IW_HEADER_TYPE_NULL 0 /* Not available */#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */#define IW_HEADER_TYPE_UINT 4 /* __u32 */#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality *//* Headers for the various requests */static const char standard_ioctl_hdr[] = { IW_HEADER_TYPE_NULL, /* SIOCSIWCOMMIT */ IW_HEADER_TYPE_CHAR, /* SIOCGIWNAME */ IW_HEADER_TYPE_PARAM, /* SIOCSIWNWID */ IW_HEADER_TYPE_PARAM, /* SIOCGIWNWID */ IW_HEADER_TYPE_FREQ, /* SIOCSIWFREQ */ IW_HEADER_TYPE_FREQ, /* SIOCGIWFREQ */ IW_HEADER_TYPE_UINT, /* SIOCSIWMODE */ IW_HEADER_TYPE_UINT, /* SIOCGIWMODE */ IW_HEADER_TYPE_PARAM, /* SIOCSIWSENS */ IW_HEADER_TYPE_PARAM, /* SIOCGIWSENS */ IW_HEADER_TYPE_NULL, /* SIOCSIWRANGE */ IW_HEADER_TYPE_POINT, /* SIOCGIWRANGE */ IW_HEADER_TYPE_NULL, /* SIOCSIWPRIV */ IW_HEADER_TYPE_POINT, /* SIOCGIWPRIV */ IW_HEADER_TYPE_NULL, /* SIOCSIWSTATS */ IW_HEADER_TYPE_POINT, /* SIOCGIWSTATS */ IW_HEADER_TYPE_POINT, /* SIOCSIWSPY */ IW_HEADER_TYPE_POINT, /* SIOCGIWSPY */ IW_HEADER_TYPE_POINT, /* SIOCSIWTHRSPY */ IW_HEADER_TYPE_POINT, /* SIOCGIWTHRSPY */ IW_HEADER_TYPE_ADDR, /* SIOCSIWAP */ IW_HEADER_TYPE_ADDR, /* SIOCGIWAP */ IW_HEADER_TYPE_NULL, /* -- hole -- */ IW_HEADER_TYPE_POINT, /* SIOCGIWAPLIST */ IW_HEADER_TYPE_PARAM, /* SIOCSIWSCAN */ IW_HEADER_TYPE_POINT, /* SIOCGIWSCAN */ IW_HEADER_TYPE_POINT, /* SIOCSIWESSID */ IW_HEADER_TYPE_POINT, /* SIOCGIWESSID */ IW_HEADER_TYPE_POINT, /* SIOCSIWNICKN */ IW_HEADER_TYPE_POINT, /* SIOCGIWNICKN */ IW_HEADER_TYPE_NULL, /* -- hole -- */ IW_HEADER_TYPE_NULL, /* -- hole -- */ IW_HEADER_TYPE_PARAM, /* SIOCSIWRATE */ IW_HEADER_TYPE_PARAM, /* SIOCGIWRATE */ IW_HEADER_TYPE_PARAM, /* SIOCSIWRTS */ IW_HEADER_TYPE_PARAM, /* SIOCGIWRTS */ IW_HEADER_TYPE_PARAM, /* SIOCSIWFRAG */ IW_HEADER_TYPE_PARAM, /* SIOCGIWFRAG */ IW_HEADER_TYPE_PARAM, /* SIOCSIWTXPOW */ IW_HEADER_TYPE_PARAM, /* SIOCGIWTXPOW */ IW_HEADER_TYPE_PARAM, /* SIOCSIWRETRY */ IW_HEADER_TYPE_PARAM, /* SIOCGIWRETRY */ IW_HEADER_TYPE_POINT, /* SIOCSIWENCODE */ IW_HEADER_TYPE_POINT, /* SIOCGIWENCODE */ IW_HEADER_TYPE_PARAM, /* SIOCSIWPOWER */ IW_HEADER_TYPE_PARAM, /* SIOCGIWPOWER */};static const unsigned int standard_ioctl_num = sizeof(standard_ioctl_hdr);/* * Meta-data about all the additional standard Wireless Extension events * we know about. */static const char standard_event_hdr[] = { IW_HEADER_TYPE_ADDR, /* IWEVTXDROP */ IW_HEADER_TYPE_QUAL, /* IWEVQUAL */ IW_HEADER_TYPE_POINT, /* IWEVCUSTOM */ IW_HEADER_TYPE_ADDR, /* IWEVREGISTERED */ IW_HEADER_TYPE_ADDR, /* IWEVEXPIRED */};static const unsigned int standard_event_num = sizeof(standard_event_hdr);/* Size (in bytes) of various events */static const int event_type_size[] = { IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */ 0, IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */ 0, IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */ IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */ IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */ 0, IW_EV_POINT_LEN, /* Without variable payload */ IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */ IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */};/* Forward compatibility with WE-19 */#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL)/*------------------------------------------------------------------*//* * Initialise the struct stream_descr so that we can extract * individual events from the event stream. */voidiw_init_event_stream(struct stream_descr * stream, /* Stream of events */ char * data, int len){ /* Cleanup */ memset((char *) stream, '\0', sizeof(struct stream_descr)); /* Set things up */ stream->current = data; stream->end = data + len;}/*------------------------------------------------------------------*//* * Extract the next event from the event stream. */intiw_extract_event_stream(struct stream_descr * stream, /* Stream of events */ struct iw_event * iwe, /* Extracted event */ int we_version){ int event_type = 0; unsigned int event_len = 1; /* Invalid */ char * pointer; /* Don't "optimise" the following variable, it will crash */ unsigned cmd_index; /* *MUST* be unsigned */ /* Unused for now. Will be later on... */ we_version = we_version; /* Check for end of stream */ if((stream->current + IW_EV_LCP_LEN) > stream->end) return(0);#if 0 printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n", stream->current, stream->value, stream->end);#endif /* Extract the event header (to get the event id). * Note : the event may be unaligned, therefore copy... */ memcpy((char *) iwe, stream->current, IW_EV_LCP_LEN);#if 0 printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n", iwe->cmd, iwe->len);#endif /* Check invalid events */ if(iwe->len <= IW_EV_LCP_LEN) return(-1); /* Get the type and length of that event */ if(iwe->cmd <= SIOCIWLAST) { cmd_index = iwe->cmd - SIOCIWFIRST; if(cmd_index < standard_ioctl_num) event_type = standard_ioctl_hdr[cmd_index]; } else { cmd_index = iwe->cmd - IWEVFIRST; if(cmd_index < standard_event_num) event_type = standard_event_hdr[cmd_index]; } /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */ event_len = event_type_size[event_type]; /* Fixup for later version of WE */ if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT)) event_len -= IW_EV_POINT_OFF; /* Check if we know about this event */ if(event_len <= IW_EV_LCP_LEN) { /* Skip to next event */ stream->current += iwe->len; return(2); } event_len -= IW_EV_LCP_LEN; /* Set pointer on data */ if(stream->value != NULL) pointer = stream->value; /* Next value in event */ else pointer = stream->current + IW_EV_LCP_LEN; /* First value in event */#if 0 printf("DBG - event_type = %d, event_len = %d, pointer = %p\n", event_type, event_len, pointer);#endif /* Copy the rest of the event (at least, fixed part) */ if((pointer + event_len) > stream->end) { /* Go to next event */ stream->current += iwe->len; return(-2); } /* Fixup for later version of WE */ if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT)) memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len); else memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); /* Skip event in the stream */ pointer += event_len; /* Special processing for iw_point events */ if(event_type == IW_HEADER_TYPE_POINT) { /* Check the length of the payload */ if((iwe->len - (event_len + IW_EV_LCP_LEN)) > 0) /* Set pointer on variable part (warning : non aligned) */ iwe->u.data.pointer = pointer; else /* No data */ iwe->u.data.pointer = NULL; /* Go to next event */ stream->current += iwe->len; } else { /* Is there more value in the event ? */ if((pointer + event_len) <= (stream->current + iwe->len)) /* Go to next value */ stream->value = pointer; else { /* Go to next event */ stream->value = NULL; stream->current += iwe->len; } } return(1);}/*********************** SCANNING SUBROUTINES ***********************//* * The Wireless Extension API 14 and greater define Wireless Scanning. * The normal API is complex, this is an easy API that return * a subset of the scanning results. This should be enough for most * applications that want to use Scanning. * If you want to have use the full/normal API, check iwlist.c... * * Precaution when using scanning : * The scanning operation disable normal network traffic, and therefore * you should not abuse of scan. * The scan need to check the presence of network on other frequencies. * While you are checking those other frequencies, you can *NOT* be on * your normal frequency to listen to normal traffic in the cell. * You need typically in the order of one second to actively probe all * 802.11b channels (do the maths). Some cards may do that in background, * to reply to scan commands faster, but they still have to do it. * Leaving the cell for such an extended period of time is pretty bad. * Any kind of streaming/low latency traffic will be impacted, and the * user will perceive it (easily checked with telnet). People trying to * send traffic to you will retry packets and waste bandwidth. Some * applications may be sensitive to those packet losses in weird ways, * and tracing those weird behavior back to scanning may take time. * If you are in ad-hoc mode, if two nodes scan approx at the same * time, they won't see each other, which may create associations issues. * For those reasons, the scanning activity should be limited to * what's really needed, and continuous scanning is a bad idea. * Jean II *//*------------------------------------------------------------------*//* * Process/store one element from the scanning results in wireless_scan */static inline struct wireless_scan *iw_process_scanning_token(struct iw_event * event, struct wireless_scan * wscan){ struct wireless_scan * oldwscan; /* Now, let's decode the event */ switch(event->cmd) { case SIOCGIWAP: /* New cell description. Allocate new cell descriptor, zero it. */ oldwscan = wscan; wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan)); if(wscan == NULL) return(wscan); /* Link at the end of the list */ if(oldwscan != NULL) oldwscan->next = wscan; /* Reset it */ bzero(wscan, sizeof(struct wireless_scan)); /* Save cell identifier */ wscan->has_ap_addr = 1; memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr)); break; case SIOCGIWNWID: wscan->b.has_nwid = 1; memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam)); break; case SIOCG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -