static inline int llf_print_event(struct iw_event *event, struct iw_range *iwrange, int has_iwrange) { char buffer[128]; struct in_addr ip; rt_table_t *rt; /* Now, let's decode the event */ switch (event->cmd) { case IWEVTXDROP: DEBUG(LOG_DEBUG, 0, "Tx packet dropped:%s", iw_pr_ether(buffer, event->u.addr.sa_data)); if (mac_to_ip(&event->u.addr, &ip, this_host.devs[0].ifname) != 0) { DEBUG(LOG_DEBUG, 0, "failed mac_to_ip"); return 0; } //printf("IP=%s\n", ip_to_str(ip)); rt = rt_table_find(ip); if (rt) neighbor_link_break(rt); else DEBUG(LOG_DEBUG, 0, "no route for ip=%s", ip_to_str(ip)); break; default: DEBUG(LOG_DEBUG, 0, "(Unknown Wireless event 0x%04X)", event->cmd); } return 0; }
/* * Execute a private command on the interface */ static int set_private_cmd(int skfd, /* Socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname, /* Dev name */ char * cmdname, /* Command name */ iwprivargs * priv, /* Private ioctl description */ int priv_num) /* Number of descriptions */ { struct iwreq wrq; u_char buffer[4096]; /* Only that big in v25 and later */ int i = 0; /* Start with first command arg */ int k; /* Index in private description table */ int temp; int subcmd = 0; /* sub-ioctl index */ int offset = 0; /* Space for sub-ioctl index */ /* Check if we have a token index. * Do it know so that sub-ioctl takes precendence, and so that we * don't have to bother with it later on... */ if((count > 1) && (sscanf(args[0], "[%i]", &temp) == 1)) { subcmd = temp; args++; count--; } /* Search the correct ioctl */ k = -1; while((++k < priv_num) && strcmp(priv[k].name, cmdname)); /* If not found... */ if(k == priv_num) { fprintf(stderr, "Invalid command : %s\n", cmdname); return(-1); } /* Watch out for sub-ioctls ! */ if(priv[k].cmd < SIOCDEVPRIVATE) { int j = -1; /* Find the matching *real* ioctl */ while((++j < priv_num) && ((priv[j].name[0] != '\0') || (priv[j].set_args != priv[k].set_args) || (priv[j].get_args != priv[k].get_args))); /* If not found... */ if(j == priv_num) { fprintf(stderr, "Invalid private ioctl definition for : %s\n", cmdname); return(-1); } /* Save sub-ioctl number */ subcmd = priv[k].cmd; /* Reserve one int (simplify alignement issues) */ offset = sizeof(__u32); /* Use real ioctl definition from now on */ k = j; printf("<mapping sub-ioctl %s to cmd 0x%X-%d>\n", cmdname, priv[k].cmd, subcmd); } /* If we have to set some data */ if((priv[k].set_args & IW_PRIV_TYPE_MASK) && (priv[k].set_args & IW_PRIV_SIZE_MASK)) { switch(priv[k].set_args & IW_PRIV_TYPE_MASK) { case IW_PRIV_TYPE_BYTE: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { sscanf(args[i], "%i", &temp); buffer[i] = (char) temp; } break; case IW_PRIV_TYPE_INT: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { sscanf(args[i], "%i", &temp); ((__s32 *) buffer)[i] = (__s32) temp; } break; case IW_PRIV_TYPE_CHAR: if(i < count) { /* Size of the string to fetch */ wrq.u.data.length = strlen(args[i]) + 1; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch string */ memcpy(buffer, args[i], wrq.u.data.length); buffer[sizeof(buffer) - 1] = '\0'; i++; } else { wrq.u.data.length = 1; buffer[0] = '\0'; } break; case IW_PRIV_TYPE_FLOAT: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { double freq; if(sscanf(args[i], "%lg", &(freq)) != 1) { printf("Invalid float [%s]...\n", args[i]); return(-1); } if(index(args[i], 'G')) freq *= GIGA; if(index(args[i], 'M')) freq *= MEGA; if(index(args[i], 'k')) freq *= KILO; sscanf(args[i], "%i", &temp); iw_float2freq(freq, ((struct iw_freq *) buffer) + i); } break; case IW_PRIV_TYPE_ADDR: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { if(iw_in_addr(skfd, ifname, args[i], ((struct sockaddr *) buffer) + i) < 0) { printf("Invalid address [%s]...\n", args[i]); return(-1); } } break; default: fprintf(stderr, "Not yet implemented...\n"); return(-1); } if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && (wrq.u.data.length != (priv[k].set_args & IW_PRIV_SIZE_MASK))) { printf("The command %s need exactly %d argument...\n", cmdname, priv[k].set_args & IW_PRIV_SIZE_MASK); return(-1); } } /* if args to set */ else { wrq.u.data.length = 0L; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); /* Those two tests are important. They define how the driver * will have to handle the data */ if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && ((iw_get_priv_size(priv[k].set_args) + offset) <= IFNAMSIZ)) { /* First case : all SET args fit within wrq */ if(offset) wrq.u.mode = subcmd; memcpy(wrq.u.name + offset, buffer, IFNAMSIZ - offset); } else { if((priv[k].set_args == 0) && (priv[k].get_args & IW_PRIV_SIZE_FIXED) && (iw_get_priv_size(priv[k].get_args) <= IFNAMSIZ)) { /* Second case : no SET args, GET args fit within wrq */ if(offset) wrq.u.mode = subcmd; } else { /* Thirst case : args won't fit in wrq, or variable number of args */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.flags = subcmd; } } /* Perform the private ioctl */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept private ioctl...\n"); fprintf(stderr, "%s (%X): %s\n", cmdname, priv[k].cmd, strerror(errno)); return(-1); } /* If we have to get some data */ if((priv[k].get_args & IW_PRIV_TYPE_MASK) && (priv[k].get_args & IW_PRIV_SIZE_MASK)) { int j; int n = 0; /* number of args */ printf("%-8.8s %s:", ifname, cmdname); /* Check where is the returned data */ if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && (iw_get_priv_size(priv[k].get_args) <= IFNAMSIZ)) { memcpy(buffer, wrq.u.name, IFNAMSIZ); n = priv[k].get_args & IW_PRIV_SIZE_MASK; } else n = wrq.u.data.length; switch(priv[k].get_args & IW_PRIV_TYPE_MASK) { case IW_PRIV_TYPE_BYTE: /* Display args */ for(j = 0; j < n; j++) printf("%d ", buffer[j]); printf("\n"); break; case IW_PRIV_TYPE_INT: /* Display args */ for(j = 0; j < n; j++) printf("%d ", ((__s32 *) buffer)[j]); printf("\n"); break; case IW_PRIV_TYPE_CHAR: /* Display args */ buffer[wrq.u.data.length - 1] = '\0'; printf("%s\n", buffer); break; case IW_PRIV_TYPE_FLOAT: { double freq; /* Display args */ for(j = 0; j < n; j++) { freq = iw_freq2float(((struct iw_freq *) buffer) + j); if(freq >= GIGA) printf("%gG ", freq / GIGA); else if(freq >= MEGA) printf("%gM ", freq / MEGA); else printf("%gk ", freq / KILO); } printf("\n"); } break; case IW_PRIV_TYPE_ADDR: { char scratch[128]; struct sockaddr * hwa; /* Display args */ for(j = 0; j < n; j++) { hwa = ((struct sockaddr *) buffer) + j; if(j) printf(" %.*s", (int) strlen(cmdname), " "); printf("%s\n", iw_pr_ether(scratch, hwa->sa_data)); } } break; default: fprintf(stderr, "Not yet implemented...\n"); return(-1); } } /* if args to set */ return(0); }
/* * Print on the screen in a neat fashion all the info we have collected * on a device. */ static void display_info(struct wireless_info * info, char * ifname) { char buffer[128]; /* Temporary buffer */ /* One token is more of less 5 characters, 14 tokens per line */ int tokens = 3; /* For name */ /* Display device name and wireless name (name of the protocol used) */ printf("%-8.8s %s ", ifname, info->name); /* Display ESSID (extended network), if any */ if(info->has_essid) { if(info->essid_on) { /* Does it have an ESSID index ? */ if((info->essid_on & IW_ENCODE_INDEX) > 1) printf("ESSID:\"%s\" [%d] ", info->essid, (info->essid_on & IW_ENCODE_INDEX)); else printf("ESSID:\"%s\" ", info->essid); } else printf("ESSID:off/any "); } /* Display NickName (station name), if any */ if(info->has_nickname) printf("Nickname:\"%s\"", info->nickname); /* Formatting */ if(info->has_essid || info->has_nickname) { printf("\n "); tokens = 0; } /* Display Network ID */ if(info->has_nwid) { /* Note : should display proper number of digit according to info * in range structure */ if(info->nwid.disabled) printf("NWID:off/any "); else printf("NWID:%X ", info->nwid.value); tokens +=2; } /* Display the current mode of operation */ if(info->has_mode) { printf("Mode:%s ", iw_operation_mode[info->mode]); tokens +=3; } /* Display frequency / channel */ if(info->has_freq) { iw_print_freq(buffer, info->freq); printf("%s ", buffer); tokens +=4; } /* Display the address of the current Access Point */ if(info->has_ap_addr) { /* A bit of clever formatting */ if(tokens > 8) { printf("\n "); tokens = 0; } tokens +=6; /* Oups ! No Access Point in Ad-Hoc mode */ if((info->has_mode) && (info->mode == IW_MODE_ADHOC)) printf("Cell:"); else printf("Access Point:"); printf(" %s ", iw_pr_ether(buffer, info->ap_addr.sa_data)); } /* Display the currently used/set bit-rate */ if(info->has_bitrate) { /* A bit of clever formatting */ if(tokens > 11) { printf("\n "); tokens = 0; } tokens +=3; /* Display it */ iw_print_bitrate(buffer, info->bitrate.value); printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer); } #if WIRELESS_EXT > 9 /* Display the Transmit Power */ if(info->has_txpower) { /* A bit of clever formatting */ if(tokens > 11) { printf("\n "); tokens = 0; } tokens +=3; /* Disabled ? */ if(info->txpower.disabled) printf("Tx-Power:off "); else { int dbm; /* Fixed ? */ if(info->txpower.fixed) printf("Tx-Power="); else printf("Tx-Power:"); /* Convert everything to dBm */ if(info->txpower.flags & IW_TXPOW_MWATT) dbm = iw_mwatt2dbm(info->txpower.value); else dbm = info->txpower.value; /* Display */ printf("%d dBm ", dbm); } } #endif /* Display sensitivity */ if(info->has_sens) { /* A bit of clever formatting */ if(tokens > 10) { printf("\n "); tokens = 0; } tokens +=4; /* Fixed ? */ if(info->sens.fixed) printf("Sensitivity="); else printf("Sensitivity:"); if(info->has_range) /* Display in dBm ? */ if(info->sens.value < 0) printf("%d dBm ", info->sens.value); else printf("%d/%d ", info->sens.value, info->range.sensitivity); else printf("%d ", info->sens.value); } printf("\n "); tokens = 0; #if WIRELESS_EXT > 10 /* Display retry limit/lifetime information */ if(info->has_retry) { printf("Retry"); /* Disabled ? */ if(info->retry.disabled) printf(":off"); else { /* Let's check the value and its type */ if(info->retry.flags & IW_RETRY_TYPE) { iw_print_retry_value(buffer, info->retry.value, info->retry.flags); printf("%s", buffer); } /* Let's check if nothing (simply on) */ if(info->retry.flags == IW_RETRY_ON) printf(":on"); } printf(" "); tokens += 5; /* Between 3 and 5, depend on flags */ } #endif /* WIRELESS_EXT > 10 */ /* Display the RTS threshold */ if(info->has_rts) { /* Disabled ? */ if(info->rts.disabled) printf("RTS thr:off "); else { /* Fixed ? */ if(info->rts.fixed) printf("RTS thr="); else printf("RTS thr:"); printf("%d B ", info->rts.value); } tokens += 3; } /* Display the fragmentation threshold */ if(info->has_frag) { /* A bit of clever formatting */ if(tokens > 10) { printf("\n "); tokens = 0; } tokens +=4; /* Disabled ? */ if(info->frag.disabled) printf("Fragment thr:off"); else { /* Fixed ? */ if(info->frag.fixed) printf("Fragment thr="); else printf("Fragment thr:"); printf("%d B ", info->frag.value); } } /* Formating */ if(tokens > 0) printf("\n "); /* Display encryption information */ /* Note : we display only the "current" key, use iwlist to list all keys */ if(info->has_key) { printf("Encryption key:"); if((info->key_flags & IW_ENCODE_DISABLED) || (info->key_size == 0)) printf("off\n "); else { /* Display the key */ iw_print_key(buffer, info->key, info->key_size, info->key_flags); printf("%s", buffer); /* Other info... */ if((info->key_flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", info->key_flags & IW_ENCODE_INDEX); if(info->key_flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted"); if(info->key_flags & IW_ENCODE_OPEN) printf(" Security mode:open"); printf("\n "); } } /* Display Power Management information */ /* Note : we display only one parameter, period or timeout. If a device * (such as HiperLan) has both, the user need to use iwlist... */ if(info->has_power) /* I hope the device has power ;-) */ { printf("Power Management"); /* Disabled ? */ if(info->power.disabled) printf(":off\n "); else { /* Let's check the value and its type */ if(info->power.flags & IW_POWER_TYPE) { iw_print_pm_value(buffer, info->power.value, info->power.flags); printf("%s ", buffer); } /* Let's check the mode */ iw_print_pm_mode(buffer, info->power.flags); printf("%s", buffer); /* Let's check if nothing (simply on) */ if(info->power.flags == IW_POWER_ON) printf(":on"); printf("\n "); } } /* Display statistics */ if(info->has_stats) { info->stats.qual.updated = 0x0; /* Not that reliable, disable */ iw_print_stats(buffer, &info->stats.qual, &info->range, info->has_range); printf("Link %s\n", buffer); #if WIRELESS_EXT > 11 printf(" Rx invalid nwid:%d Rx invalid crypt:%d Rx invalid frag:%d\n Tx excessive retries:%d Invalid misc:%d Missed beacon:%d\n", info->stats.discard.nwid, info->stats.discard.code, info->stats.discard.fragment, info->stats.discard.retries, info->stats.discard.misc, info->stats.miss.beacon); #else /* WIRELESS_EXT > 11 */ printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n", info->stats.discard.nwid, info->stats.discard.code, info->stats.discard.misc); #endif /* WIRELESS_EXT > 11 */ } printf("\n"); }
/* * Print one element from the scanning results */ static inline int print_event_token(struct iw_event * event, /* Extracted token */ struct iw_range * iwrange, /* Range info */ int has_range) { char buffer[128]; /* Temporary buffer */ /* Now, let's decode the event */ switch(event->cmd) { /* ----- set events ----- */ /* Events that result from a "SET XXX" operation by the user */ case SIOCSIWNWID: if(event->u.nwid.disabled) printf("NWID:off/any\n"); else printf("NWID:%X\n", event->u.nwid.value); break; case SIOCSIWFREQ: { float freq; /* Frequency/channel */ freq = iw_freq2float(&(event->u.freq)); iw_print_freq(buffer, freq); printf("%s\n", buffer); } break; case SIOCSIWMODE: printf("Mode:%s\n", iw_operation_mode[event->u.mode]); break; case SIOCSIWESSID: { char essid[IW_ESSID_MAX_SIZE+1]; if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(essid, event->u.essid.pointer, event->u.essid.length); essid[event->u.essid.length] = '\0'; if(event->u.essid.flags) { /* Does it have an ESSID index ? */ if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) printf("ESSID:\"%s\" [%d]\n", essid, (event->u.essid.flags & IW_ENCODE_INDEX)); else printf("ESSID:\"%s\"\n", essid); } else printf("ESSID:off/any\n"); } break; case SIOCSIWENCODE: { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(event->u.data.pointer) memcpy(key, event->u.essid.pointer, event->u.data.length); else event->u.data.flags |= IW_ENCODE_NOKEY; printf("Encryption key:"); if(event->u.data.flags & IW_ENCODE_DISABLED) printf("off\n"); else { /* Display the key */ iw_print_key(buffer, key, event->u.data.length, event->u.data.flags); printf("%s", buffer); /* Other info... */ if((event->u.data.flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX); if(event->u.data.flags & IW_ENCODE_RESTRICTED) printf(" Encryption mode:restricted"); if(event->u.data.flags & IW_ENCODE_OPEN) printf(" Encryption mode:open"); printf("\n"); } } break; /* ----- driver events ----- */ /* Events generated by the driver when something important happens */ case SIOCGIWAP: printf("New Access Point/Cell address:%s\n", iw_pr_ether(buffer, event->u.ap_addr.sa_data)); break; case SIOCGIWSCAN: printf("Scan request completed\n"); break; case IWEVTXDROP: printf("Tx packet dropped:%s\n", iw_pr_ether(buffer, event->u.addr.sa_data)); break; #if WIRELESS_EXT > 14 case IWEVCUSTOM: { char custom[IW_CUSTOM_MAX+1]; if((event->u.data.pointer) && (event->u.data.length)) memcpy(custom, event->u.data.pointer, event->u.data.length); custom[event->u.data.length] = '\0'; printf("Custom driver event:%s\n", custom); } break; case IWEVREGISTERED: printf("Registered node:%s\n", iw_pr_ether(buffer, event->u.addr.sa_data)); break; case IWEVEXPIRED: printf("Expired node:%s\n", iw_pr_ether(buffer, event->u.addr.sa_data)); break; #endif /* WIRELESS_EXT > 14 */ /* ----- junk ----- */ /* other junk not currently in use */ case SIOCGIWRATE: iw_print_bitrate(buffer, event->u.bitrate.value); printf("Bit Rate:%s\n", buffer); break; case IWEVQUAL: { event->u.qual.updated = 0x0; /* Not that reliable, disable */ iw_print_stats(buffer, &event->u.qual, iwrange, has_range); printf("Link %s\n", buffer); break; } default: printf("(Unknown Wireless event 0x%04X)\n", event->cmd); } /* switch(event->cmd) */ return(0); }