1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/tiancj-airkiss

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
linux.c 56 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
cjtian Отправлено 15.05.2015 05:57 1d01ab0
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112
/*
* OS dependent APIs for Linux
*
* Copyright (C) 2006, 2007, 2008 Thomas d'Otreppe
* Copyright (C) 2004, 2005 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <netpacket/packet.h>
#include <linux/if_ether.h>
#include <linux/if.h>
#include <linux/wireless.h>
#include <netinet/in.h>
#include <linux/if_tun.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <sys/utsname.h>
#include "radiotap/radiotap-parser.h"
/* radiotap-parser defines types like u8 that
* ieee80211_radiotap.h needs
*
* we use our local copy of ieee80211_radiotap.h
*
* - since we can't support extensions we don't understand
* - since linux does not include it in userspace headers
*/
#include "radiotap/ieee80211_radiotap.h"
#include "osdep.h"
//#include "pcap.h"
#include "crctable_osdep.h"
#include "common.h"
#include "byteorder.h"
#define uchar unsigned char
typedef enum {
DT_NULL = 0,
DT_WLANNG,
DT_HOSTAP,
DT_MADWIFI,
DT_MADWIFING,
DT_BCM43XX,
DT_ORINOCO,
DT_ZD1211RW,
DT_ACX,
DT_MAC80211_RT,
DT_AT76USB,
DT_IPW2200
} DRIVER_TYPE;
static const char * szaDriverTypes[] = {
[DT_NULL] = "Unknown",
[DT_WLANNG] = "Wlan-NG",
[DT_HOSTAP] = "HostAP",
[DT_MADWIFI] = "Madwifi",
[DT_MADWIFING] = "Madwifi-NG",
[DT_BCM43XX] = "BCM43xx",
[DT_ORINOCO] = "Orinoco",
[DT_ZD1211RW] = "ZD1211RW",
[DT_ACX] = "ACX",
[DT_MAC80211_RT] = "Mac80211-Radiotap",
[DT_AT76USB] = "Atmel 76_usb",
[DT_IPW2200] = "ipw2200"
};
/*
* XXX need to have a different read/write/open function for each Linux driver.
*/
struct priv_linux {
int fd_in, arptype_in;
int fd_out, arptype_out;
int fd_main;
int fd_rtc;
DRIVER_TYPE drivertype; /* inited to DT_UNKNOWN on allocation by wi_alloc */
//FILE *f_cap_in;
//struct pcap_file_header pfh_in;
int sysfs_inject;
int channel;
int freq;
int rate;
int tx_power;
char *wlanctlng; /* XXX never set */
char *iwpriv;
char *iwconfig;
char *ifconfig;
char *wl;
char *iw;
char *main_if;
unsigned char pl_mac[6];
int inject_wlanng;
};
#ifndef ETH_P_80211_RAW
#define ETH_P_80211_RAW 25
#endif
#define ARPHRD_IEEE80211 801
#define ARPHRD_IEEE80211_PRISM 802
#define ARPHRD_IEEE80211_FULL 803
#ifndef NULL_MAC
#define NULL_MAC "\x00\x00\x00\x00\x00\x00"
#endif
unsigned long calc_crc_osdep( unsigned char * buf, int len)
{
unsigned long crc = 0xFFFFFFFF;
for( ; len > 0; len--, buf++ )
crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ ( crc >> 8 );
return( ~crc );
}
/* CRC checksum verification routine */
int check_crc_buf_osdep( unsigned char *buf, int len )
{
unsigned long crc;
if (len<0)
return 0;
crc = calc_crc_osdep(buf, len);
buf+=len;
return( ( ( crc ) & 0xFF ) == buf[0] &&
( ( crc >> 8 ) & 0xFF ) == buf[1] &&
( ( crc >> 16 ) & 0xFF ) == buf[2] &&
( ( crc >> 24 ) & 0xFF ) == buf[3] );
}
//Check if the driver is ndiswrapper */
static int is_ndiswrapper(const char * iface, const char * path)
{
int n, pid, unused;
if ((pid=fork())==0)
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execl(path, "iwpriv",iface, "ndis_reset", NULL);
exit( 1 );
}
waitpid( pid, &n, 0 );
return ( ( WIFEXITED(n) && WEXITSTATUS(n) == 0 ));
}
/* Search a file recursively */
static char * searchInside(const char * dir, const char * filename)
{
char * ret;
char * curfile;
struct stat sb;
int len, lentot;
DIR *dp;
struct dirent *ep;
dp = opendir(dir);
if (dp == NULL)
{
return NULL;
}
len = strlen( filename );
lentot = strlen( dir ) + 256 + 2;
curfile = (char *) calloc( 1, lentot );
while ((ep = readdir(dp)) != NULL)
{
memset(curfile, 0, lentot);
sprintf(curfile, "%s/%s", dir, ep->d_name);
//Checking if it's the good file
if ((int)strlen( ep->d_name) == len && !strcmp(ep->d_name, filename))
{
(void)closedir(dp);
return curfile;
}
lstat(curfile, &sb);
//If it's a directory and not a link, try to go inside to search
if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode))
{
//Check if the directory isn't "." or ".."
if (strcmp(".", ep->d_name) && strcmp("..", ep->d_name))
{
//Recursive call
ret = searchInside(curfile, filename);
if (ret != NULL)
{
(void)closedir(dp);
free( curfile );
return ret;
}
}
}
}
(void)closedir(dp);
free( curfile );
return NULL;
}
/* Search a wireless tool and return its path */
static char * wiToolsPath(const char * tool)
{
char * path;
int i, nbelems;
static const char * paths [] = {
"/sbin",
"/usr/sbin",
"/usr/local/sbin",
"/bin",
"/usr/bin",
"/usr/local/bin",
"/tmp"
};
nbelems = sizeof(paths) / sizeof(char *);
for (i = 0; i < nbelems; i++)
{
path = searchInside(paths[i], tool);
if (path != NULL)
return path;
}
return NULL;
}
static int linux_get_channel(struct wif *wi)
{
struct priv_linux *dev = wi_priv(wi);
struct iwreq wrq;
int fd, frequency;
int chan=0;
memset( &wrq, 0, sizeof( struct iwreq ) );
if(dev->main_if)
strncpy( wrq.ifr_name, dev->main_if, IFNAMSIZ );
else
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
fd = dev->fd_in;
if(dev->drivertype == DT_IPW2200)
fd = dev->fd_main;
if( ioctl( fd, SIOCGIWFREQ, &wrq ) < 0 )
return( -1 );
frequency = wrq.u.freq.m;
if (frequency > 100000000)
frequency/=100000;
else if (frequency > 1000000)
frequency/=1000;
if (frequency > 1000)
chan = getChannelFromFrequency(frequency);
else chan = frequency;
return chan;
}
static int linux_get_freq(struct wif *wi)
{
struct priv_linux *dev = wi_priv(wi);
struct iwreq wrq;
int fd, frequency;
memset( &wrq, 0, sizeof( struct iwreq ) );
if(dev->main_if)
strncpy( wrq.ifr_name, dev->main_if, IFNAMSIZ );
else
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
fd = dev->fd_in;
if(dev->drivertype == DT_IPW2200)
fd = dev->fd_main;
if( ioctl( fd, SIOCGIWFREQ, &wrq ) < 0 )
return( -1 );
frequency = wrq.u.freq.m;
if (frequency > 100000000)
frequency/=100000;
else if (frequency > 1000000)
frequency/=1000;
if (frequency < 500) //its not a freq, but the actual channel
frequency = getFrequencyFromChannel(frequency);
return frequency;
}
static int linux_set_rate(struct wif *wi, int rate)
{
struct priv_linux *dev = wi_priv(wi);
struct ifreq ifr;
struct iwreq wrq;
char s[32];
int pid, status, unused;
memset(s, 0, sizeof(s));
switch(dev->drivertype) {
case DT_MADWIFING:
memset( &ifr, 0, sizeof( ifr ) );
strncpy( ifr.ifr_name, wi_get_ifname(wi), sizeof( ifr.ifr_name ) - 1 );
if( ioctl( dev->fd_in, SIOCGIFINDEX, &ifr ) < 0 )
{
printf("Interface %s: \n", wi_get_ifname(wi));
perror( "ioctl(SIOCGIFINDEX) failed" );
return( 1 );
}
/* Bring interface down*/
ifr.ifr_flags = 0;
if( ioctl( dev->fd_in, SIOCSIFFLAGS, &ifr ) < 0 )
{
perror( "ioctl(SIOCSIFFLAGS) failed" );
return( 1 );
}
usleep(100000);
snprintf( s, sizeof( s ) - 1, "%.1fM", (rate/1000000.0) );
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp(dev->iwconfig, "iwconfig", wi_get_ifname(wi),
"rate", s, NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
return 0;
break;
case DT_MAC80211_RT:
dev->rate = (rate/500000);
return 0;
break;
default:
break;
}
/* ELSE */
memset( &wrq, 0, sizeof( struct iwreq ) );
if(dev->main_if)
strncpy( wrq.ifr_name, dev->main_if, IFNAMSIZ );
else
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
wrq.u.bitrate.value = rate;
if( ioctl( dev->fd_in, SIOCSIWRATE, &wrq ) < 0 )
{
return( -1 );
}
return 0;
}
static int linux_get_rate(struct wif *wi)
{
struct priv_linux *dev = wi_priv(wi);
struct iwreq wrq;
memset( &wrq, 0, sizeof( struct iwreq ) );
if( dev->drivertype == DT_MAC80211_RT )
return (dev->rate*500000);
if(dev->main_if)
strncpy( wrq.ifr_name, dev->main_if, IFNAMSIZ );
else
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
if( ioctl( dev->fd_in, SIOCGIWRATE, &wrq ) < 0 )
{
return( -1 );
}
return wrq.u.bitrate.value;
}
static int linux_set_mtu(struct wif *wi, int mtu)
{
struct priv_linux *dev = wi_priv(wi);
struct ifreq ifr;
memset( &ifr, 0, sizeof( struct ifreq ) );
if(dev->main_if)
strncpy( ifr.ifr_name, dev->main_if, sizeof( ifr.ifr_name ) - 1 );
else
strncpy( ifr.ifr_name, wi_get_ifname(wi), sizeof( ifr.ifr_name ) - 1 );
ifr.ifr_mtu = mtu;
if( ioctl( dev->fd_in, SIOCSIFMTU, &ifr ) < 0 )
{
return( -1 );
}
return 0;
}
static int linux_get_mtu(struct wif *wi)
{
struct priv_linux *dev = wi_priv(wi);
struct ifreq ifr;
memset( &ifr, 0, sizeof( struct ifreq ) );
if(dev->main_if)
strncpy( ifr.ifr_name, dev->main_if, sizeof( ifr.ifr_name ) - 1 );
else
strncpy( ifr.ifr_name, wi_get_ifname(wi), sizeof( ifr.ifr_name ) - 1 );
if( ioctl( dev->fd_in, SIOCGIFMTU, &ifr ) < 0 )
{
return( -1 );
}
return ifr.ifr_mtu;
}
static int linux_read(struct wif *wi, unsigned char *buf, int count,
struct rx_info *ri)
{
struct priv_linux *dev = wi_priv(wi);
unsigned char tmpbuf[4096];
int caplen, n, got_signal, got_noise, got_channel, fcs_removed;
caplen = n = got_signal = got_noise = got_channel = fcs_removed = 0;
if((unsigned)count > sizeof(tmpbuf))
return( -1 );
if( ( caplen = read( dev->fd_in, tmpbuf, count ) ) < 0 )
{
if( errno == EAGAIN )
return( 0 );
perror( "read failed" );
return( -1 );
}
switch (dev->drivertype) {
case DT_MADWIFI:
caplen -= 4; /* remove the FCS for madwifi-old! only (not -ng)*/
break;
default:
break;
}
memset( buf, 0, count);
/* XXX */
if (ri)
memset(ri, 0, sizeof(*ri));
if( dev->arptype_in == ARPHRD_IEEE80211_PRISM )
{
/* skip the prism header */
if( tmpbuf[7] == 0x40 )
{
/* prism54 uses a different format */
if(ri)
{
ri->ri_power = tmpbuf[0x33];
ri->ri_noise = *(unsigned int *)( tmpbuf + 0x33 + 12 );
ri->ri_rate = (*(unsigned int *)( tmpbuf + 0x33 + 24 ))*500000;
got_signal = 1;
got_noise = 1;
}
n = 0x40;
}
else
{
if(ri)
{
ri->ri_mactime = *(u_int64_t*)( tmpbuf + 0x5C - 48 );
ri->ri_channel = *(unsigned int *)( tmpbuf + 0x5C - 36 );
ri->ri_power = *(unsigned int *)( tmpbuf + 0x5C );
ri->ri_noise = *(unsigned int *)( tmpbuf + 0x5C + 12 );
ri->ri_rate = (*(unsigned int *)( tmpbuf + 0x5C + 24 ))*500000;
// if( ! memcmp( iface[i], "ath", 3 ) )
if( dev->drivertype == DT_MADWIFI )
ri->ri_power -= *(int *)( tmpbuf + 0x68 );
if( dev->drivertype == DT_MADWIFING )
ri->ri_power -= *(int *)( tmpbuf + 0x68 );
got_channel = 1;
got_signal = 1;
got_noise = 1;
}
n = *(int *)( tmpbuf + 4 );
}
if( n < 8 || n >= caplen )
return( 0 );
}
if( dev->arptype_in == ARPHRD_IEEE80211_FULL )
{
struct ieee80211_radiotap_iterator iterator;
struct ieee80211_radiotap_header *rthdr;
rthdr = (struct ieee80211_radiotap_header *) tmpbuf;
if (ieee80211_radiotap_iterator_init(&iterator, rthdr, caplen) < 0)
return (0);
/* go through the radiotap arguments we have been given
* by the driver
*/
while (ri && (ieee80211_radiotap_iterator_next(&iterator) >= 0)) {
switch (iterator.this_arg_index) {
case IEEE80211_RADIOTAP_TSFT:
ri->ri_mactime = le64_to_cpu(*((uint64_t*)iterator.this_arg));
break;
case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
if(!got_signal) {
if( *iterator.this_arg < 127 )
ri->ri_power = *iterator.this_arg;
else
ri->ri_power = *iterator.this_arg - 255;
got_signal = 1;
}
break;
case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
if(!got_signal) {
if( *iterator.this_arg < 127 )
ri->ri_power = *iterator.this_arg;
else
ri->ri_power = *iterator.this_arg - 255;
got_signal = 1;
}
break;
case IEEE80211_RADIOTAP_DBM_ANTNOISE:
if(!got_noise) {
if( *iterator.this_arg < 127 )
ri->ri_noise = *iterator.this_arg;
else
ri->ri_noise = *iterator.this_arg - 255;
got_noise = 1;
}
break;
case IEEE80211_RADIOTAP_DB_ANTNOISE:
if(!got_noise) {
if( *iterator.this_arg < 127 )
ri->ri_noise = *iterator.this_arg;
else
ri->ri_noise = *iterator.this_arg - 255;
got_noise = 1;
}
break;
case IEEE80211_RADIOTAP_ANTENNA:
ri->ri_antenna = *iterator.this_arg;
break;
case IEEE80211_RADIOTAP_CHANNEL:
ri->ri_channel = *iterator.this_arg;
got_channel = 1;
break;
case IEEE80211_RADIOTAP_RATE:
ri->ri_rate = (*iterator.this_arg) * 500000;
break;
case IEEE80211_RADIOTAP_FLAGS:
/* is the CRC visible at the end?
* remove
*/
if ( *iterator.this_arg &
IEEE80211_RADIOTAP_F_FCS )
{
fcs_removed = 1;
caplen -= 4;
}
if ( *iterator.this_arg &
IEEE80211_RADIOTAP_F_RX_BADFCS )
return( 0 );
break;
}
}
n = le16_to_cpu(rthdr->it_len);
if( n <= 0 || n >= caplen )
return( 0 );
}
caplen -= n;
//detect fcs at the end, even if the flag wasn't set and remove it
if( fcs_removed == 0 && check_crc_buf_osdep( tmpbuf+n, caplen - 4 ) == 1 )
{
caplen -= 4;
}
memcpy( buf, tmpbuf + n, caplen );
if(ri && !got_channel)
ri->ri_channel = wi_get_channel(wi);
return( caplen );
}
static int linux_write(struct wif *wi, unsigned char *buf, int count,
struct tx_info *ti)
{
struct priv_linux *dev = wi_priv(wi);
unsigned char maddr[6];
int ret, usedrtap=0;
unsigned char tmpbuf[4096];
unsigned char rate;
unsigned short int *p_rtlen;
unsigned char u8aRadiotap[] = {
0x00, 0x00, // <-- radiotap version
0x0c, 0x00, // <- radiotap header length
0x04, 0x80, 0x00, 0x00, // <-- bitmap
0x00, // <-- rate
0x00, // <-- padding for natural alignment
0x18, 0x00, // <-- TX flags
};
/* Pointer to the radiotap header length field for later use. */
p_rtlen = (unsigned short int*)(u8aRadiotap+2);
if((unsigned) count > sizeof(tmpbuf)-22) return -1;
/* XXX honor ti */
if (ti) {}
rate = dev->rate;
u8aRadiotap[8] = rate;
switch (dev->drivertype) {
case DT_MAC80211_RT:
memcpy(tmpbuf, u8aRadiotap, sizeof (u8aRadiotap) );
memcpy(tmpbuf + sizeof (u8aRadiotap), buf, count);
count += sizeof (u8aRadiotap);
buf = tmpbuf;
usedrtap = 1;
break;
case DT_WLANNG:
/* Wlan-ng isn't able to inject on kernel > 2.6.11 */
if( dev->inject_wlanng == 0 )
{
perror( "write failed" );
return( -1 );
}
if (count >= 24)
{
/* for some reason, wlan-ng requires a special header */
if( ( ((unsigned char *) buf)[1] & 3 ) != 3 )
{
memcpy( tmpbuf, buf, 24 );
memset( tmpbuf + 24, 0, 22 );
tmpbuf[30] = ( count - 24 ) & 0xFF;
tmpbuf[31] = ( count - 24 ) >> 8;
memcpy( tmpbuf + 46, buf + 24, count - 24 );
count += 22;
}
else
{
memcpy( tmpbuf, buf, 30 );
memset( tmpbuf + 30, 0, 16 );
tmpbuf[30] = ( count - 30 ) & 0xFF;
tmpbuf[31] = ( count - 30 ) >> 8;
memcpy( tmpbuf + 46, buf + 30, count - 30 );
count += 16;
}
buf = tmpbuf;
}
/* fall thru */
case DT_HOSTAP:
if( ( ((uchar *) buf)[1] & 3 ) == 2 )
{
/* Prism2 firmware swaps the dmac and smac in FromDS packets */
memcpy( maddr, buf + 4, 6 );
memcpy( buf + 4, buf + 16, 6 );
memcpy( buf + 16, maddr, 6 );
}
break;
default:
break;
}
ret = write( dev->fd_out, buf, count );
if( ret < 0 )
{
if( errno == EAGAIN || errno == EWOULDBLOCK ||
errno == ENOBUFS || errno == ENOMEM )
{
usleep( 10000 );
return( 0 );
}
perror( "write failed" );
return( -1 );
}
/* radiotap header length is stored little endian on all systems */
if(usedrtap)
ret-=letoh16(*p_rtlen);
if( ret < 0 )
{
if( errno == EAGAIN || errno == EWOULDBLOCK ||
errno == ENOBUFS || errno == ENOMEM )
{
usleep( 10000 );
return( 0 );
}
perror( "write failed" );
return( -1 );
}
return( ret );
}
static int linux_set_channel(struct wif *wi, int channel)
{
struct priv_linux *dev = wi_priv(wi);
char s[64];
int pid, status, unused;
struct iwreq wrq;
memset( s, 0, sizeof( s ) );
switch (dev->drivertype) {
case DT_WLANNG:
snprintf( s, sizeof( s ) - 1, "channel=%d", channel );
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execl( dev->wlanctlng, "wlanctl-ng", wi_get_ifname(wi),
"lnxreq_wlansniff", s, NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
if( WIFEXITED(status) )
{
dev->channel=channel;
return( WEXITSTATUS(status) );
}
else
return( 1 );
break;
case DT_ORINOCO:
snprintf( s, sizeof( s ) - 1, "%d", channel );
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( dev->iwpriv, "iwpriv", wi_get_ifname(wi),
"monitor", "1", s, NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
dev->channel = channel;
return 0;
break; //yeah ;)
case DT_ZD1211RW:
snprintf( s, sizeof( s ) - 1, "%d", channel );
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp(dev->iwconfig, "iwconfig", wi_get_ifname(wi),
"channel", s, NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
dev->channel = channel;
return 0;
break; //yeah ;)
case DT_MAC80211_RT:
snprintf(s, sizeof(s) - 1, "iw %s set channel %d", wi_get_ifname(wi), channel);
printf("exec cmd: %s\n", s);
if(system(s) == 0)
dev->channel = channel;
else
printf("cannot set channel to %d\n", channel);
return 0;
break; //yeah ;)
default:
break;
}
memset( &wrq, 0, sizeof( struct iwreq ) );
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
wrq.u.freq.m = (double) channel;
wrq.u.freq.e = (double) 0;
if( ioctl( dev->fd_in, SIOCSIWFREQ, &wrq ) < 0 )
{
usleep( 10000 ); /* madwifi needs a second chance */
if( ioctl( dev->fd_in, SIOCSIWFREQ, &wrq ) < 0 )
{
perror( "ioctl(SIOCSIWFREQ) failed" );
return( 1 );
}
}
dev->channel = channel;
return( 0 );
}
static int linux_set_freq(struct wif *wi, int freq)
{
struct priv_linux *dev = wi_priv(wi);
char s[64];
int pid, status, unused;
struct iwreq wrq;
memset( s, 0, sizeof( s ) );
switch (dev->drivertype) {
case DT_WLANNG:
case DT_ORINOCO:
case DT_ZD1211RW:
snprintf( s, sizeof( s ) - 1, "%dM", freq );
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp(dev->iwconfig, "iwconfig", wi_get_ifname(wi),
"freq", s, NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
dev->freq = freq;
return 0;
break; //yeah ;)
case DT_MAC80211_RT:
snprintf( s, sizeof( s ) - 1, "iw %s set freq %d", wi_get_ifname(wi), freq );
if(system(s) == 0 )
dev->freq = freq;
return 0;
break; //yeah ;)
default:
break;
}
memset( &wrq, 0, sizeof( struct iwreq ) );
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
wrq.u.freq.m = (double) freq*100000;
wrq.u.freq.e = (double) 1;
if( ioctl( dev->fd_in, SIOCSIWFREQ, &wrq ) < 0 )
{
usleep( 10000 ); /* madwifi needs a second chance */
if( ioctl( dev->fd_in, SIOCSIWFREQ, &wrq ) < 0 )
{
/* perror( "ioctl(SIOCSIWFREQ) failed" ); */
return( 1 );
}
}
dev->freq = freq;
return( 0 );
}
static int opensysfs(struct priv_linux *dev, char *iface, int fd) {
int fd2;
char buf[256];
/* ipw2200 injection */
snprintf(buf, 256, "/sys/class/net/%s/device/inject", iface);
fd2 = open(buf, O_WRONLY);
/* bcm43xx injection */
if (fd2 == -1)
snprintf(buf, 256, "/sys/class/net/%s/device/inject_nofcs", iface);
fd2 = open(buf, O_WRONLY);
if (fd2 == -1)
return -1;
dup2(fd2, fd);
close(fd2);
dev->sysfs_inject=1;
return 0;
}
int linux_get_monitor(struct wif *wi)
{
struct priv_linux *dev = wi_priv(wi);
struct ifreq ifr;
struct iwreq wrq;
/* find the interface index */
if(dev->drivertype == DT_IPW2200)
return( 0 );
memset( &ifr, 0, sizeof( ifr ) );
strncpy( ifr.ifr_name, wi_get_ifname(wi), sizeof( ifr.ifr_name ) - 1 );
// if( ioctl( fd, SIOCGIFINDEX, &ifr ) < 0 )
// {
// printf("Interface %s: \n", iface);
// perror( "ioctl(SIOCGIFINDEX) failed" );
// return( 1 );
// }
/* lookup the hardware type */
if( ioctl( wi_fd(wi), SIOCGIFHWADDR, &ifr ) < 0 )
{
printf("Interface %s: \n", wi_get_ifname(wi));
perror( "ioctl(SIOCGIFHWADDR) failed" );
return( 1 );
}
/* lookup iw mode */
memset( &wrq, 0, sizeof( struct iwreq ) );
strncpy( wrq.ifr_name, wi_get_ifname(wi), IFNAMSIZ );
if( ioctl( wi_fd(wi), SIOCGIWMODE, &wrq ) < 0 )
{
/* most probably not supported (ie for rtap ipw interface) *
* so just assume its correctly set... */
wrq.u.mode = IW_MODE_MONITOR;
}
if( ( ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211 &&
ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM &&
ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL) ||
( wrq.u.mode != IW_MODE_MONITOR && (dev->drivertype != DT_ORINOCO)) )
{
return( 1 );
}
return( 0 );
}
int set_monitor( struct priv_linux *dev, char *iface, int fd )
{
int pid, status, unused;
struct iwreq wrq;
char strbuf[512];
if( strcmp(iface,"prism0") == 0 )
{
dev->wl = wiToolsPath("wl");
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execl( dev->wl, "wl", "monitor", "1", NULL);
exit( 1 );
}
waitpid( pid, &status, 0 );
if( WIFEXITED(status) )
return( WEXITSTATUS(status) );
return( 1 );
}
else if (strncmp(iface, "rtap", 4) == 0 )
{
return 0;
}
else
{
switch(dev->drivertype) {
case DT_WLANNG:
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execl( dev->wlanctlng, "wlanctl-ng", iface,
"lnxreq_wlansniff", "enable=true",
"prismheader=true", "wlanheader=false",
"stripfcs=true", "keepwepflags=true",
"6", NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
if( WIFEXITED(status) )
return( WEXITSTATUS(status) );
return( 1 );
break;
case DT_ORINOCO:
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( dev->iwpriv, "iwpriv", iface,
"monitor", "1", "1", NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
if( WIFEXITED(status) )
return( WEXITSTATUS(status) );
return 1;
break;
case DT_ACX:
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( dev->iwpriv, "iwpriv", iface,
"monitor", "2", "1", NULL );
exit( 1 );
}
waitpid( pid, &status, 0 );
if( WIFEXITED(status) )
return( WEXITSTATUS(status) );
return 1;
break;
case DT_MAC80211_RT:
snprintf(strbuf, sizeof(strbuf) - 1, "ifconfig %s down", iface);
if (system(strbuf) == 0)
printf("down iface %s\n", iface);
snprintf(strbuf, sizeof(strbuf) - 1, "iw %s set type monitor", iface);
if (system(strbuf) == 0)
printf("set iface %s type to monitor\n", iface);
snprintf(strbuf, sizeof(strbuf) - 1, "ifconfig %s up", iface);
if (system(strbuf) == 0)
printf("up iface %s\n", iface);
return 0;
default:
break;
}
memset( &wrq, 0, sizeof( struct iwreq ) );
strncpy( wrq.ifr_name, iface, IFNAMSIZ );
wrq.u.mode = IW_MODE_MONITOR;
if( ioctl( fd, SIOCSIWMODE, &wrq ) < 0 )
{
perror( "ioctl(SIOCSIWMODE) failed" );
return( 1 );
}
if(dev->drivertype == DT_AT76USB)
{
sleep(3);
}
}
/* couple of iwprivs to enable the prism header */
if( ! fork() ) /* hostap */
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( "iwpriv", "iwpriv", iface, "monitor_type", "1", NULL );
exit( 1 );
}
wait( NULL );
if( ! fork() ) /* r8180 */
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( "iwpriv", "iwpriv", iface, "prismhdr", "1", NULL );
exit( 1 );
}
wait( NULL );
if( ! fork() ) /* prism54 */
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( "iwpriv", "iwpriv", iface, "set_prismhdr", "1", NULL );
exit( 1 );
}
wait( NULL );
return( 0 );
}
static int openraw(struct priv_linux *dev, char *iface, int fd, int *arptype,
uchar *mac)
{
struct ifreq ifr;
struct ifreq ifr2;
struct iwreq wrq;
struct iwreq wrq2;
struct packet_mreq mr;
struct sockaddr_ll sll;
struct sockaddr_ll sll2;
/* find the interface index */
memset( &ifr, 0, sizeof( ifr ) );
strncpy( ifr.ifr_name, iface, sizeof( ifr.ifr_name ) - 1 );
if( ioctl( fd, SIOCGIFINDEX, &ifr ) < 0 )
{
printf("Interface %s: \n", iface);
perror( "ioctl(SIOCGIFINDEX) failed" );
return( 1 );
}
memset( &sll, 0, sizeof( sll ) );
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
switch(dev->drivertype) {
case DT_IPW2200:
/* find the interface index */
memset( &ifr2, 0, sizeof( ifr ) );
strncpy( ifr2.ifr_name, dev->main_if, sizeof( ifr2.ifr_name ) - 1 );
if( ioctl( dev->fd_main, SIOCGIFINDEX, &ifr2 ) < 0 )
{
printf("Interface %s: \n", dev->main_if);
perror( "ioctl(SIOCGIFINDEX) failed" );
return( 1 );
}
/* set iw mode to managed on main interface */
memset( &wrq2, 0, sizeof( struct iwreq ) );
strncpy( wrq2.ifr_name, dev->main_if, IFNAMSIZ );
if( ioctl( dev->fd_main, SIOCGIWMODE, &wrq2 ) < 0 )
{
perror("SIOCGIWMODE");
return 1;
}
wrq2.u.mode = IW_MODE_INFRA;
if( ioctl( dev->fd_main, SIOCSIWMODE, &wrq2 ) < 0 )
{
perror("SIOCSIWMODE");
return 1;
}
/* bind the raw socket to the interface */
memset( &sll2, 0, sizeof( sll2 ) );
sll2.sll_family = AF_PACKET;
sll2.sll_ifindex = ifr2.ifr_ifindex;
sll2.sll_protocol = htons( ETH_P_ALL );
if( bind( dev->fd_main, (struct sockaddr *) &sll2,
sizeof( sll2 ) ) < 0 )
{
printf("Interface %s: \n", dev->main_if);
perror( "bind(ETH_P_ALL) failed" );
return( 1 );
}
opensysfs(dev, dev->main_if, dev->fd_in);
break;
case DT_BCM43XX:
opensysfs(dev, iface, dev->fd_in);
break;
case DT_WLANNG:
sll.sll_protocol = htons( ETH_P_80211_RAW );
break;
default:
sll.sll_protocol = htons( ETH_P_ALL );
break;
}
/* lookup the hardware type */
if( ioctl( fd, SIOCGIFHWADDR, &ifr ) < 0 )
{
printf("Interface %s: \n", iface);
perror( "ioctl(SIOCGIFHWADDR) failed" );
return( 1 );
}
/* lookup iw mode */
memset( &wrq, 0, sizeof( struct iwreq ) );
strncpy( wrq.ifr_name, iface, IFNAMSIZ );
if( ioctl( fd, SIOCGIWMODE, &wrq ) < 0 )
{
/* most probably not supported (ie for rtap ipw interface) *
* so just assume its correctly set... */
wrq.u.mode = IW_MODE_MONITOR;
}
if( ( ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211 &&
ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM &&
ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL) ||
( wrq.u.mode != IW_MODE_MONITOR) )
{
if (set_monitor( dev, iface, fd ) && !dev->drivertype == DT_ORINOCO )
{
ifr.ifr_flags &= ~(IFF_UP | IFF_BROADCAST | IFF_RUNNING);
if( ioctl( fd, SIOCSIFFLAGS, &ifr ) < 0 )
{
perror( "ioctl(SIOCSIFFLAGS) failed" );
return( 1 );
}
if (set_monitor( dev, iface, fd ) && !dev->drivertype == DT_ORINOCO )
{
printf("Error setting monitor mode on %s\n",iface);
return( 1 );
}
}
}
/* Is interface st to up, broadcast & running ? */
if((ifr.ifr_flags | IFF_UP | IFF_BROADCAST | IFF_RUNNING) != ifr.ifr_flags)
{
/* Bring interface up*/
ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING;
if( ioctl( fd, SIOCSIFFLAGS, &ifr ) < 0 )
{
perror( "ioctl(SIOCSIFFLAGS) failed" );
return( 1 );
}
}
/* bind the raw socket to the interface */
if( bind( fd, (struct sockaddr *) &sll,
sizeof( sll ) ) < 0 )
{
printf("Interface %s: \n", iface);
perror( "bind(ETH_P_ALL) failed" );
return( 1 );
}
/* lookup the hardware type */
if( ioctl( fd, SIOCGIFHWADDR, &ifr ) < 0 )
{
printf("Interface %s: \n", iface);
perror( "ioctl(SIOCGIFHWADDR) failed" );
return( 1 );
}
memcpy( mac, (unsigned char*)ifr.ifr_hwaddr.sa_data, 6);
*arptype = ifr.ifr_hwaddr.sa_family;
if( ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211 &&
ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM &&
ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL )
{
if( ifr.ifr_hwaddr.sa_family == 1 )
fprintf( stderr, "\nARP linktype is set to 1 (Ethernet) " );
else
fprintf( stderr, "\nUnsupported hardware link type %4d ",
ifr.ifr_hwaddr.sa_family );
fprintf( stderr, "- expected ARPHRD_IEEE80211,\nARPHRD_IEEE80211_"
"FULL or ARPHRD_IEEE80211_PRISM instead. Make\n"
"sure RFMON is enabled: run 'airmon-ng start %s"
" <#>'\nSysfs injection support was not found "
"either.\n\n", iface );
return( 1 );
}
/* enable promiscuous mode */
memset( &mr, 0, sizeof( mr ) );
mr.mr_ifindex = sll.sll_ifindex;
mr.mr_type = PACKET_MR_PROMISC;
if( setsockopt( fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&mr, sizeof( mr ) ) < 0 )
{
perror( "setsockopt(PACKET_MR_PROMISC) failed" );
return( 1 );
}
return( 0 );
}
/*
* Open the interface and set mode monitor
* Return 1 on failure and 0 on success
*/
static int do_linux_open(struct wif *wi, char *iface)
{
int kver, unused;
struct utsname checklinuxversion;
struct priv_linux *dev = wi_priv(wi);
char *iwpriv;
char strbuf[512];
FILE *f;
char athXraw[] = "athXraw";
pid_t pid;
int n;
DIR *net_ifaces;
struct dirent *this_iface;
FILE *acpi;
char r_file[128], buf[128];
struct ifreq ifr;
char * unused_str;
dev->inject_wlanng = 1;
dev->rate = 2; /* default to 1Mbps if nothing is set */
/* open raw socks */
if( ( dev->fd_in = socket( PF_PACKET, SOCK_RAW,
htons( ETH_P_ALL ) ) ) < 0 )
{
perror( "socket(PF_PACKET) failed" );
if( getuid() != 0 )
fprintf( stderr, "This program requires root privileges.\n" );
return( 1 );
}
if( ( dev->fd_main = socket( PF_PACKET, SOCK_RAW,
htons( ETH_P_ALL ) ) ) < 0 )
{
perror( "socket(PF_PACKET) failed" );
if( getuid() != 0 )
fprintf( stderr, "This program requires root privileges.\n" );
return( 1 );
}
/* Check iwpriv existence */
iwpriv = wiToolsPath("iwpriv");
dev->iwpriv = iwpriv;
dev->iwconfig = wiToolsPath("iwconfig");
dev->ifconfig = wiToolsPath("ifconfig");
dev->iw = wiToolsPath("iw");
if (! iwpriv )
{
fprintf(stderr, "Can't find wireless tools, exiting.\n");
goto close_in;
}
/* Exit if ndiswrapper : check iwpriv ndis_reset */
if ( is_ndiswrapper(iface, iwpriv ) )
{
fprintf(stderr, "Ndiswrapper doesn't support monitor mode.\n");
goto close_in;
}
if( ( dev->fd_out = socket( PF_PACKET, SOCK_RAW,
htons( ETH_P_ALL ) ) ) < 0 )
{
perror( "socket(PF_PACKET) failed" );
goto close_in;
}
/* figure out device type */
/* mac80211 radiotap injection
* detected based on interface called mon...
* since mac80211 allows multiple virtual interfaces
*
* note though that the virtual interfaces are ultimately using a
* single physical radio: that means for example they must all
* operate on the same channel
*/
/* mac80211 stack detection */
memset(strbuf, 0, sizeof(strbuf));
snprintf(strbuf, sizeof(strbuf) - 1,
"ls /sys/class/net/%s/phy80211/subsystem >/dev/null 2>/dev/null", iface);
if (system(strbuf) == 0)
dev->drivertype = DT_MAC80211_RT;
/* IPW2200 detection */
memset(strbuf, 0, sizeof(strbuf));
snprintf(strbuf, sizeof(strbuf) - 1,
"ls /sys/class/net/%s/device/inject >/dev/null 2>/dev/null", iface);
if (system(strbuf) == 0)
dev->drivertype = DT_IPW2200;
/* BCM43XX detection */
memset(strbuf, 0, sizeof(strbuf));
snprintf(strbuf, sizeof(strbuf) - 1,
"ls /sys/class/net/%s/device/inject_nofcs >/dev/null 2>/dev/null", iface);
if (system(strbuf) == 0)
dev->drivertype = DT_BCM43XX;
/* check if wlan-ng or hostap or r8180 */
if( strlen(iface) == 5 &&
memcmp(iface, "wlan", 4 ) == 0 )
{
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"wlancfg show %s 2>/dev/null | "
"grep p2CnfWEPFlags >/dev/null",
iface);
if( system( strbuf ) == 0 )
{
if (uname( & checklinuxversion ) >= 0)
{
/* uname succeeded */
if (strncmp(checklinuxversion.release, "2.6.", 4) == 0
&& strncasecmp(checklinuxversion.sysname, "linux", 5) == 0)
{
/* Linux kernel 2.6 */
kver = atoi(checklinuxversion.release + 4);
if (kver > 11)
{
/* That's a kernel > 2.6.11, cannot inject */
dev->inject_wlanng = 0;
}
}
}
dev->drivertype = DT_WLANNG;
dev->wlanctlng = wiToolsPath("wlanctl-ng");
}
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"iwpriv %s 2>/dev/null | "
"grep antsel_rx >/dev/null",
iface);
if( system( strbuf ) == 0 )
dev->drivertype=DT_HOSTAP;
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"iwpriv %s 2>/dev/null | "
"grep GetAcx111Info >/dev/null",
iface);
if( system( strbuf ) == 0 )
dev->drivertype=DT_ACX;
}
/* enable injection on ralink */
if( strcmp( iface, "ra0" ) == 0 ||
strcmp( iface, "ra1" ) == 0 ||
strcmp( iface, "rausb0" ) == 0 ||
strcmp( iface, "rausb1" ) == 0 )
{
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"iwpriv %s rfmontx 1 >/dev/null 2>/dev/null",
iface );
unused = system( strbuf );
}
/* check if newer athXraw interface available */
if( ( strlen( iface ) >= 4 || strlen( iface ) <= 6 )
&& memcmp( iface, "ath", 3 ) == 0 )
{
dev->drivertype = DT_MADWIFI;
memset( strbuf, 0, sizeof( strbuf ) );
snprintf(strbuf, sizeof( strbuf ) -1,
"/proc/sys/net/%s/%%parent", iface);
f = fopen(strbuf, "r");
if (f != NULL)
{
// It is madwifi-ng
dev->drivertype=DT_MADWIFING;
fclose( f );
/* should we force prism2 header? */
sprintf((char *) strbuf, "/proc/sys/net/%s/dev_type", iface);
f = fopen( (char *) strbuf,"w");
if (f != NULL) {
fprintf(f, "802\n");
fclose(f);
}
/* Force prism2 header on madwifi-ng */
}
else
{
// Madwifi-old
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"sysctl -w dev.%s.rawdev=1 >/dev/null 2>/dev/null",
iface );
if( system( strbuf ) == 0 )
{
athXraw[3] = iface[3];
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"ifconfig %s up", athXraw );
unused = system( strbuf );
#if 0 /* some people reported problems when prismheader is enabled */
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"sysctl -w dev.%s.rawdev_type=1 >/dev/null 2>/dev/null",
iface );
unused = system( strbuf );
#endif
iface = athXraw;
}
}
}
/* test if orinoco */
if( memcmp( iface, "eth", 3 ) == 0 )
{
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( "iwpriv", "iwpriv", iface, "get_port3", NULL );
exit( 1 );
}
waitpid( pid, &n, 0 );
if( WIFEXITED(n) && WEXITSTATUS(n) == 0 )
dev->drivertype=DT_ORINOCO;
memset( strbuf, 0, sizeof( strbuf ) );
snprintf( strbuf, sizeof( strbuf ) - 1,
"iwpriv %s 2>/dev/null | "
"grep get_scan_times >/dev/null",
iface);
if( system( strbuf ) == 0 )
dev->drivertype=DT_AT76USB;
}
/* test if zd1211rw */
if( memcmp( iface, "eth", 3 ) == 0 )
{
if( ( pid = fork() ) == 0 )
{
close( 0 ); close( 1 ); close( 2 ); unused = chdir( "/" );
execlp( "iwpriv", "iwpriv", iface, "get_regdomain", NULL );
exit( 1 );
}
waitpid( pid, &n, 0 );
if( WIFEXITED(n) && WEXITSTATUS(n) == 0 )
dev->drivertype=DT_ZD1211RW;
}
if( dev->drivertype == DT_IPW2200 )
{
snprintf(r_file, sizeof(r_file),
"/sys/class/net/%s/device/rtap_iface", iface);
if ((acpi = fopen(r_file, "r")) == NULL)
goto close_out;
memset(buf, 0, 128);
unused_str = fgets(buf, 128, acpi);
buf[127]='\x00';
//rtap iface doesn't exist
if(strncmp(buf, "-1", 2) == 0)
{
//repoen for writing
fclose(acpi);
if ((acpi = fopen(r_file, "w")) == NULL)
goto close_out;
fputs("1", acpi);
//reopen for reading
fclose(acpi);
if ((acpi = fopen(r_file, "r")) == NULL)
goto close_out;
unused_str = fgets(buf, 128, acpi);
}
fclose(acpi);
//use name in buf as new iface and set original iface as main iface
dev->main_if = (char*) malloc(strlen(iface)+1);
memset(dev->main_if, 0, strlen(iface)+1);
strncpy(dev->main_if, iface, strlen(iface));
iface=(char*)malloc(strlen(buf)+1);
memset(iface, 0, strlen(buf)+1);
strncpy(iface, buf, strlen(buf));
}
/* test if rtap interface and try to find real interface */
if( memcmp( iface, "rtap", 4) == 0 && dev->main_if == NULL)
{
memset( &ifr, 0, sizeof( ifr ) );
strncpy( ifr.ifr_name, iface, sizeof( ifr.ifr_name ) - 1 );
n = 0;
if( ioctl( dev->fd_out, SIOCGIFINDEX, &ifr ) < 0 )
{
//create rtap interface
n = 1;
}
net_ifaces = opendir("/sys/class/net");
if ( net_ifaces != NULL )
{
while (net_ifaces != NULL && ((this_iface = readdir(net_ifaces)) != NULL))
{
if (this_iface->d_name[0] == '.')
continue;
snprintf(r_file, sizeof(r_file),
"/sys/class/net/%s/device/rtap_iface", this_iface->d_name);
if ((acpi = fopen(r_file, "r")) == NULL)
continue;
if (acpi != NULL)
{
dev->drivertype = DT_IPW2200;
memset(buf, 0, 128);
unused_str = fgets(buf, 128, acpi);
if(n==0) //interface exists
{
if (strncmp(buf, iface, 5) == 0)
{
fclose(acpi);
if (net_ifaces != NULL)
{
closedir(net_ifaces);
net_ifaces = NULL;
}
dev->main_if = (char*) malloc(strlen(this_iface->d_name)+1);
strcpy(dev->main_if, this_iface->d_name);
break;
}
}
else //need to create interface
{
if (strncmp(buf, "-1", 2) == 0)
{
//repoen for writing
fclose(acpi);
if ((acpi = fopen(r_file, "w")) == NULL)
continue;
fputs("1", acpi);
//reopen for reading
fclose(acpi);
if ((acpi = fopen(r_file, "r")) == NULL)
continue;
unused_str = fgets(buf, 128, acpi);
if (strncmp(buf, iface, 5) == 0)
{
if (net_ifaces != NULL)
{
closedir(net_ifaces);
net_ifaces = NULL;
}
dev->main_if = (char*) malloc(strlen(this_iface->d_name)+1);
strcpy(dev->main_if, this_iface->d_name);
fclose(acpi);
break;
}
}
}
fclose(acpi);
}
}
if (net_ifaces != NULL)
closedir(net_ifaces);
}
}
if(0)
fprintf(stderr, "Interface %s -> driver: %s\n", iface,
szaDriverTypes[dev->drivertype]);
if (openraw(dev, iface, dev->fd_out, &dev->arptype_out, dev->pl_mac) != 0) {
goto close_out;
}
/* don't use the same file descriptor for in and out on bcm43xx,
as you read from the interface, but write into a file in /sys/...
*/
if(!(dev->drivertype == DT_BCM43XX) && !(dev->drivertype == DT_IPW2200))
dev->fd_in = dev->fd_out;
else
{
/* if bcm43xx or ipw2200, swap both fds */
n=dev->fd_out;
dev->fd_out=dev->fd_in;
dev->fd_in=n;
}
dev->arptype_in = dev->arptype_out;
return 0;
close_out:
close(dev->fd_out);
close_in:
close(dev->fd_in);
return 1;
}
static void do_free(struct wif *wi)
{
struct priv_linux *pl = wi_priv(wi);
if(pl->wlanctlng)
free(pl->wlanctlng);
if(pl->iwpriv)
free(pl->iwpriv);
if(pl->iwconfig)
free(pl->iwconfig);
if(pl->ifconfig)
free(pl->ifconfig);
if(pl->wl)
free(pl->wl);
if(pl->main_if)
free(pl->main_if);
free(pl);
free(wi);
}
static void linux_close(struct wif *wi)
{
struct priv_linux *pl = wi_priv(wi);
if (pl->fd_in)
close(pl->fd_in);
if (pl->fd_out)
close(pl->fd_out);
do_free(wi);
}
static int linux_fd(struct wif *wi)
{
struct priv_linux *pl = wi_priv(wi);
return pl->fd_in;
}
static int linux_get_mac(struct wif *wi, unsigned char *mac)
{
struct priv_linux *pl = wi_priv(wi);
struct ifreq ifr;
int fd;
fd = wi_fd(wi);
/* find the interface index */
/* ipw2200 got a file opened as fd */
if(pl->drivertype == DT_IPW2200)
{
memcpy(mac, pl->pl_mac, 6);
return 0;
}
memset( &ifr, 0, sizeof( ifr ) );
strncpy( ifr.ifr_name, wi_get_ifname(wi), sizeof( ifr.ifr_name ) - 1 );
if( ioctl( fd, SIOCGIFINDEX, &ifr ) < 0 )
{
printf("Interface %s: \n", wi_get_ifname(wi));
perror( "ioctl(SIOCGIFINDEX) failed" );
return( 1 );
}
if( ioctl( fd, SIOCGIFHWADDR, &ifr ) < 0 )
{
printf("Interface %s: \n", wi_get_ifname(wi));
perror( "ioctl(SIOCGIFHWADDR) failed" );
return( 1 );
}
memcpy( pl->pl_mac, (unsigned char*)ifr.ifr_hwaddr.sa_data, 6);
/* XXX */
memcpy(mac, pl->pl_mac, 6);
return 0;
}
static int linux_set_mac(struct wif *wi, unsigned char *mac)
{
struct priv_linux *pl = wi_priv(wi);
struct ifreq ifr;
int fd, ret;
fd = wi_fd(wi);
/* find the interface index */
memset( &ifr, 0, sizeof( ifr ) );
strncpy( ifr.ifr_name, wi_get_ifname(wi), sizeof( ifr.ifr_name ) - 1 );
if( ioctl( fd, SIOCGIFHWADDR, &ifr ) < 0 )
{
printf("Interface %s: \n", wi_get_ifname(wi));
perror( "ioctl(SIOCGIFHWADDR) failed" );
return( 1 );
}
// if down
ifr.ifr_flags &= ~(IFF_UP | IFF_BROADCAST | IFF_RUNNING);
if( ioctl( fd, SIOCSIFFLAGS, &ifr ) < 0 )
{
perror( "ioctl(SIOCSIFFLAGS) failed" );
return( 1 );
}
// ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
// ifr.ifr_hwaddr.sa_len = 6;
memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
memcpy(pl->pl_mac, mac, 6);
//set mac
ret = ioctl(fd, SIOCSIFHWADDR, ifr);
//if up
ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING;
if( ioctl( fd, SIOCSIFFLAGS, &ifr ) < 0 )
{
perror( "ioctl(SIOCSIFFLAGS) failed" );
return( 1 );
}
return ret;
}
static struct wif *linux_open(char *iface)
{
struct wif *wi;
struct priv_linux *pl;
wi = wi_alloc(sizeof(*pl));
if (!wi)
return NULL;
wi->wi_read = linux_read;
wi->wi_write = linux_write;
wi->wi_set_channel = linux_set_channel;
wi->wi_get_channel = linux_get_channel;
wi->wi_set_freq = linux_set_freq;
wi->wi_get_freq = linux_get_freq;
wi->wi_close = linux_close;
wi->wi_fd = linux_fd;
wi->wi_get_mac = linux_get_mac;
wi->wi_set_mac = linux_set_mac;
wi->wi_get_monitor = linux_get_monitor;
wi->wi_get_rate = linux_get_rate;
wi->wi_set_rate = linux_set_rate;
wi->wi_get_mtu = linux_get_mtu;
wi->wi_set_mtu = linux_set_mtu;
if (do_linux_open(wi, iface)) {
do_free(wi);
return NULL;
}
return wi;
}
struct wif *wi_open_osdep(char *iface)
{
return linux_open(iface);
}
int get_battery_state(void)
{
char buf[128];
int batteryTime = 0;
FILE *apm;
int flag;
char units[32];
int ret;
static int linux_apm = 1;
static int linux_acpi = 1;
if (linux_apm == 1)
{
if ((apm = fopen("/proc/apm", "r")) != NULL ) {
if ( fgets(buf, 128,apm) != NULL ) {
int charging, ac;
fclose(apm);
ret = sscanf(buf, "%*s %*d.%*d %*x %x %x %x %*d%% %d %s\n", &ac,
&charging, &flag, &batteryTime, units);
if(!ret) return 0;
if ((flag & 0x80) == 0 && charging != 0xFF && ac != 1 && batteryTime != -1) {
if (!strncmp(units, "min", 32))
batteryTime *= 60;
}
else return 0;
linux_acpi = 0;
return batteryTime;
}
}
linux_apm = 0;
}
if (linux_acpi && !linux_apm)
{
DIR *batteries, *ac_adapters;
struct dirent *this_battery, *this_adapter;
FILE *acpi, *info;
char battery_state[128];
char battery_info[128];
int rate = 1, remain = 0, current = 0;
static int total_remain = 0, total_cap = 0;
int batno = 0;
static int info_timer = 0;
int batt_full_capacity[3];
linux_apm=0;
linux_acpi=1;
ac_adapters = opendir("/proc/acpi/ac_adapter");
if ( ac_adapters == NULL )
return 0;
while (ac_adapters != NULL && ((this_adapter = readdir(ac_adapters)) != NULL)) {
if (this_adapter->d_name[0] == '.')
continue;
/* safe overloaded use of battery_state path var */
snprintf(battery_state, sizeof(battery_state),
"/proc/acpi/ac_adapter/%s/state", this_adapter->d_name);
if ((acpi = fopen(battery_state, "r")) == NULL)
continue;
if (acpi != NULL) {
while(fgets(buf, 128, acpi)) {
if (strstr(buf, "on-line") != NULL) {
fclose(acpi);
if (ac_adapters != NULL)
closedir(ac_adapters);
return 0;
}
}
fclose(acpi);
}
}
if (ac_adapters != NULL)
closedir(ac_adapters);
batteries = opendir("/proc/acpi/battery");
if (batteries == NULL) {
closedir(batteries);
return 0;
}
while (batteries != NULL && ((this_battery = readdir(batteries)) != NULL)) {
if (this_battery->d_name[0] == '.')
continue;
snprintf(battery_info, sizeof(battery_info), "/proc/acpi/battery/%s/info", this_battery->d_name);
info = fopen(battery_info, "r");
batt_full_capacity[batno] = 0;
if ( info != NULL ) {
while (fgets(buf, sizeof(buf), info) != NULL)
if (sscanf(buf, "last full capacity: %d mWh", &batt_full_capacity[batno]) == 1)
continue;
fclose(info);
}
snprintf(battery_state, sizeof(battery_state),
"/proc/acpi/battery/%s/state", this_battery->d_name);
if ((acpi = fopen(battery_state, "r")) == NULL)
continue;
while (fgets(buf, 128, acpi)) {
if (strncmp(buf, "present:", 8 ) == 0) {
/* No information for this battery */
if (strstr(buf, "no" ))
continue;
}
else if (strncmp(buf, "charging state:", 15) == 0) {
/* the space makes it different than discharging */
if (strstr(buf, " charging" )) {
fclose( acpi );
return 0;
}
}
else if (strncmp(buf, "present rate:", 13) == 0)
rate = atoi(buf + 25);
else if (strncmp(buf, "remaining capacity:", 19) == 0) {
remain = atoi(buf + 25);
total_remain += remain;
}
else if (strncmp(buf, "present voltage:", 17) == 0)
current = atoi(buf + 25);
}
total_cap += batt_full_capacity[batno];
fclose(acpi);
batteryTime += (int) (( ((float)remain) /rate ) * 3600);
batno++;
}
info_timer++;
if (batteries != NULL)
closedir(batteries);
}
return batteryTime;
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/tiancj-airkiss.git
git@api.gitlife.ru:oschina-mirror/tiancj-airkiss.git
oschina-mirror
tiancj-airkiss
tiancj-airkiss
master