/**************************************************************** * This file is just the front-end application for * configuring the driver. Nothing too special. * * *****************************************************************/ #include #include #include #include #include #include #ifdef CONFIG_NET_RADIO /* If wireless extension exist in the kernel */ /* #include don't include for now ... */ #endif /* CONFIG_NET_RADIO */ #include "lld.h" #include "rl2cfg.h" char *types[]={"Station", "Alt", "Master"}; #ifndef WIRELESS_EXT main(int argc, char *argv[]) { int s,i; unsigned_32 secid; int j; struct rl2_ioctl *ioc; struct ifreq ifr; s=socket(AF_INET, SOCK_DGRAM, 0); ioc = (struct rl2_ioctl *) &ifr.ifr_data; myopts.domain = 0xff; myopts.type = 0xff; myopts.channel = 0xff; myopts.subchannel = 0xff; myopts.roamconfig = 0xff; myopts.macoptimize = 0xff; if(argc == 1 || !strcmp(argv[1], "--help")) { fprintf(stderr, "Usage: rl2cfg interface\n"); fprintf(stderr, "\trl2cfg [dev {ifname}] info|roam\n"); fprintf(stderr, "\trl2cfg [dev {ifname}] secid {password}\n"); fprintf(stderr, "\trl2cfg [dev {ifname}] [sta|alt|msta] [domain {d}] [channel {c}] [sub {s}]\n"); fprintf(stderr, "\t\t[name (name)] [roamconfig (slow|norm|fast)] [MAC (vlite|lite|norm)]\n"); return 0; } if(s==-1) { perror("socket:"); exit(1); } if(!strcmp(argv[1],"dev")) { strcpy(ifr.ifr_name,argv[2]); i=3; } else { strcpy(ifr.ifr_name, "eth0"); i=1; } for(;icmd = RL2INFO; break; } if(!strcmp(argv[i],"roam")) { ioc->cmd = RL2ROAM; break; } if(!strcmp(argv[i],"secid")) { ioc->cmd = RL2MASTEROPTS; myopts.type = 4; /*SET ID*/ i++; secid=0x030201; for(j=0; j< strlen(argv[i]); j++) { secid = (secid * argv[i][j]) % 0xfffffD; } secid = secid | 0x030000; myopts.id[0] = (secid & 0xff0000) >> 16; myopts.id[1] = (secid & 0x00ff00) >> 8; myopts.id[2] = (secid & 0x0000ff); break; } if(!strcmp(argv[i],"list")) { ioc->cmd = RL2LISTAPS; break; } if(!strcmp(argv[i],"msta")) { ioc->cmd = RL2MASTEROPTS; myopts.type = 2; } if(!strcmp(argv[i],"alt")) { ioc->cmd = RL2MASTEROPTS; myopts.type = 1; } if(!strcmp(argv[i],"sta")) { ioc->cmd = RL2MASTEROPTS; myopts.type=0; } if(!strcmp(argv[i],"domain")) { ioc->cmd = RL2MASTEROPTS; i++; myopts.domain=atoi(argv[i]); } if(!strcmp(argv[i],"channel")) { ioc->cmd = RL2MASTEROPTS; i++; myopts.channel=atoi(argv[i]); } if(!strcmp(argv[i],"sub")) { ioc->cmd = RL2MASTEROPTS; i++; myopts.subchannel=atoi(argv[i]); } if(!strcmp(argv[i],"roamconfig")) { ioc->cmd = RL2MASTEROPTS; i++; if(!strcmp(argv[i], "slow")) myopts.roamconfig=0; if(!strcmp(argv[i], "norm")) myopts.roamconfig=1; if(!strcmp(argv[i], "fast")) myopts.roamconfig=2; } if(!strcmp(argv[i],"MAC")) { ioc->cmd = RL2MASTEROPTS; i++; if(!strcmp(argv[i], "vlite")) myopts.macoptimize=0; if(!strcmp(argv[i], "lite")) myopts.macoptimize=1; if(!strcmp(argv[i], "norm")) myopts.macoptimize=2; } if(!strcmp(argv[i],"name")) { ioc->cmd = RL2MASTEROPTS; i++; strcpy(myopts.name,argv[i]); } } ioc->data = (unsigned char *) &myopts; if(ioctl(s,SIOCDEVPRIVATE,&ifr) == -1) { perror("ioctl:"); exit(1); } } #else /* * Hack my way... Jean II * Compile with -lm */ #include /*#include */ #include /*#include */ #include #include #include #include #include #include #include #include #include #include /* Some usefull constants */ #define KILO 1e3 #define MEGA 1e6 #define GIGA 1e9 typedef struct iw_statistics iwstats; typedef struct iw_range iwrange; typedef struct iw_freq iwfreq; /* Structure for storing all wireless information for each device */ struct wireless_info { char dev[IFNAMSIZ]; /* Interface name (device) */ char name[12]; /* Wireless name */ int has_nwid; int nwid_on; u_long nwid; /* Network ID */ int has_freq; float freq; /* Frequency/channel */ int has_sens; u_long sens; /* sensitivity */ int has_enc; int enc_method; /* encoding method or off */ long long enc_key; /* key used */ /* Stats */ iwstats stats; int has_stats; iwrange range; int has_range; }; int skfd = -1; /* generic raw socket desc. */ int ipx_sock = -1; /* IPX socket */ int ax25_sock = -1; /* AX.25 socket */ int inet_sock = -1; /* INET socket */ int ddp_sock = -1; /* Appletalk DDP socket */ static void iw_usage(void) { fprintf(stderr, "Usage: rl2cfg interface\n"); fprintf(stderr, " [domain NN]\n"); fprintf(stderr, " [freq N.NN[k, M or G]]\n"); fprintf(stderr, " [sens N]\n"); fprintf(stderr, " [enc NNNN-NNNN]\n"); exit(1); } static void print_info(struct wireless_info * info) { /* Display device name */ printf("%-8.8s ", info->dev); /* Display wireless name */ printf("%s ", info->name); /* Display Network ID */ printf("NWID:%lX ", info->nwid); /* Display frequency / channel */ printf("Channel:%g ", info->freq); printf("\n"); if(info->has_stats) { if(info->has_range) printf(" Link quality:%d/%d Signal level:%d/%d Noise level:%d/%d\n", info->stats.qual.qual, info->range.max_qual.qual, info->stats.qual.level, info->range.max_qual.level, info->stats.qual.noise, info->range.max_qual.noise); else printf(" Link quality:%d Signal level:%d Noise level:%d\n", info->stats.qual.qual, info->stats.qual.level, info->stats.qual.noise); printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n", info->stats.discard.nwid, info->stats.discard.code, info->stats.discard.misc); } printf("\n"); } static int if_getstats(char *ifname, iwstats * stats) { FILE *f=fopen("/proc/net/wireless","r"); char buf[256]; char *bp; if(f==NULL) return -1; while(fgets(buf,255,f)) { bp=buf; while(*bp&&isspace(*bp)) bp++; if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { bp=strchr(bp,':'); bp++; bp = strtok(bp, " ."); sscanf(bp, "%X", &stats->status); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->qual.qual); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->qual.level); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->qual.noise); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " ."); sscanf(bp, "%d", &stats->discard.misc); fclose(f); return 0; } } fclose(f); return 0; } /* Get wireless informations & config from the device driver */ static int get_info(char * ifname, struct wireless_info * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_info)); /* Get device name */ strcpy(info->dev, ifname); /* Get wireless name */ strcpy(wrq.ifr_name, ifname); 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 */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWNWID, &wrq) >= 0) { info->has_nwid = 1; info->nwid_on = wrq.u.nwid.on; info->nwid = wrq.u.nwid.nwid; } /* Get frequency / channel */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; } /* Get sensitivity */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWSENS, &wrq) >= 0) { info->has_sens = 1; info->sens = wrq.u.sensitivity; } /* Get encryption information */ strcpy(wrq.ifr_name, ifname); if(ioctl(skfd, SIOCGIWENCODE, &wrq) >= 0) { info->has_enc = 1; info->enc_method = wrq.u.encoding.method; info->enc_key = wrq.u.encoding.code; } /* Get stats */ if(if_getstats(ifname, &(info->stats)) == 0) { info->has_stats = 1; } /* Get ranges */ strcpy(wrq.ifr_name, ifname); wrq.u.data.pointer = (caddr_t) &(info->range); wrq.u.data.length = 0; wrq.u.data.flags = 0; if(ioctl(skfd, SIOCGIWRANGE, &wrq) >= 0) { info->has_range = 1; } return(0); } static int set_info(char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { struct iwreq wrq; int i; /* Set dev name */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); /* List of frequencies and channel numbers */ if((!strncmp(args[0], "list_freq", 9)) || (!strcmp(args[0], "list_channel"))) { float freq; struct iw_range range; int k; if(count > 1) iw_usage(); wrq.u.data.pointer = (caddr_t) ⦥ wrq.u.data.length = 0; wrq.u.data.flags = 0; if(ioctl(skfd, SIOCGIWRANGE, &wrq) < 0) { fprintf(stderr, "SIOCGIWRANGE: %s\n", strerror(errno)); return(-1); } printf("%d channels", range.num_channels); if (range.num_frequency != 0) printf(" ; available frequencies :"); for(k = 0; k < range.num_frequency; k++) { if(freq > GIGA) printf(" %gGHz ", freq / GIGA); else if(freq > MEGA) printf(" %gMHz ", freq / MEGA); else printf(" %gkHz ", freq / KILO); } printf("\n"); return 0; /* no more arg */ } /* The other args on the line specify options to be set... */ for(i = 0; i < count; i++) { /* Set network ID */ if((!strcmp(args[i], "nwid")) || (!strcmp(args[i], "domain"))) { i++; if(i >= count) iw_usage(); if(!strcasecmp(args[i], "off")) wrq.u.nwid.on = 0; else if(!strcasecmp(args[i], "on")) { /* Get old nwid */ if(ioctl(skfd, SIOCGIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCGIWNWID: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); wrq.u.nwid.on = 1; } else if(sscanf(args[i], "%lX", &(wrq.u.nwid.nwid)) != 1) iw_usage(); else wrq.u.nwid.on = 1; if(ioctl(skfd, SIOCSIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); return(-1); } continue; } /* Set frequency / channel */ if((!strncmp(args[i], "freq", 4)) || (!strcmp(args[i], "channel"))) { float freq; if(++i >= count) iw_usage(); if(sscanf(args[i], "%g", &(freq)) != 1) iw_usage(); if(index(args[i], 'G')) freq *= GIGA; if(index(args[i], 'M')) freq *= MEGA; if(index(args[i], 'k')) freq *= KILO; if(ioctl(skfd, SIOCSIWFREQ, &wrq) < 0) { fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); return(-1); } continue; } /* Set sensitivity */ if(!strncmp(args[i], "sens", 4)) { if(++i >= count) iw_usage(); if(sscanf(args[i], "%ld", &(wrq.u.sensitivity)) != 1) iw_usage(); if(ioctl(skfd, SIOCSIWSENS, &wrq) < 0) { fprintf(stderr, "SIOCSIWSENS: %s\n", strerror(errno)); return(-1); } continue; } /* Set encryption stuff */ if(!strncmp(args[i], "enc", 3 )) { unsigned long long key = 0; if(++i >= count) iw_usage(); if(!strcasecmp(args[i], "off")) wrq.u.encoding.method = 0; else { if(!strcasecmp(args[i], "on")) { /* Get old encryption information */ if(ioctl(skfd, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCGIWENCODE: %s\n", strerror(errno)); return(-1); } strcpy(wrq.ifr_name, ifname); } else { char * buff; char * p; u_long temp; p = buff = malloc(strlen(args[i] + 1)); strcpy(buff, args[i]); p = strtok(buff, "-:;.,*#"); while(p != (char *) NULL) { key = key << 16; if(sscanf(p, "%lX", &temp) != 1) iw_usage(); key += temp; p = strtok((char *) NULL, "-:;.,*#"); } free(buff); wrq.u.encoding.code = key; } /* TODO : check for "(method)" in args list */ wrq.u.encoding.method = 1; } if(ioctl(skfd, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); return(-1); } continue; } /* Here we have an unrecognised arg... */ fprintf(stderr, "Invalid argument : %s\n", args[i]); iw_usage(); return(-1); } /* for(index ... */ return(0); } static void print_devices(char *ifname) { char buff[1024]; struct wireless_info info; struct ifconf ifc; struct ifreq *ifr; int i; if(ifname == (char *)NULL) { ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); return; } ifr = ifc.ifc_req; for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { if(get_info(ifr->ifr_name, &info) < 0) { /* Could skip this message ? */ fprintf(stderr, "%-8.8s no wireless extensions.\n\n", ifr->ifr_name); continue; } print_info(&info); } } else { if(get_info(ifname, &info) < 0) { fprintf(stderr, "%s: no wireless extensions.\n", ifname); iw_usage(); } else print_info(&info); } } static int sockets_open() { inet_sock=socket(AF_INET, SOCK_DGRAM, 0); ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0); ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0); ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0); /* * Now pick any (exisiting) useful socket family for generic queries */ if(inet_sock!=-1) return inet_sock; if(ipx_sock!=-1) return ipx_sock; if(ax25_sock!=-1) return ax25_sock; /* * If this is -1 we have no known network layers and its time to jump. */ return ddp_sock; } int main(int argc, char ** argv) { int goterr = 0; /* Create a channel to the NET kernel. */ if((skfd = sockets_open()) < 0) { perror("socket"); exit(-1); } /* No argument : show the list of all device + info */ if(argc == 1) { print_devices((char *)NULL); close(skfd); exit(0); } /* The device name must be the first argument */ if(argc == 2) { print_devices(argv[1]); close(skfd); exit(0); } /* The other args on the line specify options to be set... */ goterr = set_info(argv + 2, argc - 2, argv[1]); /* Close the socket. */ close(skfd); return(goterr); } #endif /* WIRELESS_EXT */