wlan-ng.c

Go to the documentation of this file.
00001 /* Linux Prism II Stumbler - Utility Scan for 802_11 networks under Linux
00002  * 
00003  * File : wlan-ng.c
00004  * Project : WifiScanner (c) 2002 Hervé Schauer Consultants
00005  * Usage : This utility is written for use with IEEE 802.11 adapters based
00006  * on Intersil's PRISM II chipset (PCMCIA).
00007  * 
00008  * Base code was from prismstumbler Jan Fernquist <Jan.B.Fernquist@telia.com>
00009  * and wlanctl from www.linux-wlan.com
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  * 
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  * 
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00024  *
00025  * $Id: wlan-ng.c 178 2007-08-11 16:57:24Z poggij $
00026  */
00027 
00028 #include <include.h>
00029 #include <src/interface.h>
00030 #include <src/crt_io.h>
00031 #include <src/wlan-ng.h>
00032 #include <src/driver.h>
00033 #include <src/functions.h>
00034 
00035 static char *ID = "$Id: wlan-ng.c 178 2007-08-11 16:57:24Z poggij $";
00036 
00037 //#define I_WANT_TO_DEBUG
00038 
00039 extern WINDOW *Sum_WND, *RealTime_WND;
00040 extern ScanResult_t Res;
00041 
00042 static CaptureArg ca;
00043 static char errbuf[PCAP_ERRBUF_SIZE];
00044 
00045 #ifdef LWNG_15
00046 extern p80211_caphdr_t wlan_header;
00047 
00048 //UINT8 wlan_payload[WLAN_A4FR_MAXLEN];
00049 //static UINT8 wlan_payload[MAX_BUFFER_SIZE];
00050 #endif                          /* ifdef LWNG_15 */
00051 
00052 #ifndef WITH_SYSTEMCALL
00053 /* Why I put this data in static ? 
00054    because if it's not, ioctl can't access it !  */
00055 static p80211msg_lnxreq_wlansniff_t lnxreq_wlansniff;
00056 static p80211msg_lnxreq_ifstate_t lnxreq_ifstate;
00057 #endif
00058 
00059 #ifndef WITH_SYSTEMCALL
00060 // Function to dump in hexa the message send or sent to the driver
00061 //  Only for DEBUG
00062 void dump_msg(void *msg)
00063 {
00064   p80211msgd_t *msgp = msg;
00065   int i;
00066   int bodylen;
00067 
00068   debug(3, "  msgcode=0x%08lx  msglen=%lu  devname=%s\n",
00069         msgp->msgcode, msgp->msglen, msgp->devname);
00070   debug(3, "body: ");
00071   bodylen =
00072       msgp->msglen - (sizeof(msgp->msgcode) + sizeof(msgp->msglen) +
00073                       sizeof(msgp->devname));
00074   for (i = 0; i < bodylen; i += 4) {
00075     debug(3, "%02x%02x%02x%02x ", msgp->args[i],
00076           msgp->args[i + 1], msgp->args[i + 2], msgp->args[i + 3]);
00077   }
00078   debug(3, "\n");
00079 }
00080 
00081 /*----------------------------------------------------------------
00082 * do_ioctl
00083 *
00084 * Send command to driver with ioctl
00085 *
00086 * Arguments:
00087 *       char *devname : device name
00088 *       UINT8 * msg   : the message to send to driver
00089 *
00090 * Returns: 
00091 *       0       - success 
00092 *       ~0      - failure
00093 ----------------------------------------------------------------*/
00094 int do_ioctl(char *devname, UINT8 * msg, size_t size)
00095 {
00096   register int result = -1;
00097   register int fd;
00098   p80211ioctl_req_t req;
00099   UINT8 *msg_local = NULL;
00100 
00101   // In my config with wlan-ng 0.2.1_pre23 it's needed, because ioctl can't access
00102   //   to msg directly ... perharps some GRSEC pretections :-)
00103   msg_local = malloc(size);
00104   if (msg_local == NULL) {
00105     warning("ioctl error : malloc of %d can't be done", size);
00106     return (result);
00107   }
00108   memcpy(msg_local, msg, size);
00109 
00110   /* set the magic */
00111   req.magic = P80211_IOCTL_MAGIC;
00112 
00113   /* get a socket */
00114   fd = socket(AF_INET, SOCK_STREAM, 0);
00115   if (fd == -1) {
00116     warning("ioctl error : socket can't open\n");
00117     return (result);
00118   }
00119   // prepare request
00120   req.len = MSG_BUFF_LEN;
00121   req.data = msg_local;
00122   strncpy(req.name, devname, DEVNAME_LEN - 1);
00123   req.result = 0;
00124 
00125 #ifdef I_WANT_TO_DEBUG
00126   dump_msg(msg);
00127 #endif
00128 
00129   // Send request
00130   //debugTS(0, "Debut ioctl\n");
00131   result = ioctl(fd, P80211_IFREQ, &req);
00132   //debugTS(0, "Fin   ioctl\n");
00133 
00134   // check the result and send a warning if problem
00135   //   The caller choice what to do if error
00136   if (result == -1) {
00137     warning("ioctl error : \"%s\"(%d) - req=0x%X \n", strerror(errno),
00138             errno, &req);
00139 #ifdef I_WANT_TO_DEBUG
00140     dump_msg(msg);
00141 #endif
00142   }
00143   close(fd);
00144   free(msg_local);
00145   return result;
00146 }
00147 
00148 #endif                          // ifndef WITH_SYSTEMCALL
00149 
00150 /*----------------------------------------------------------------
00151 * selectChannelWLAN
00152 *
00153 * Select channel on a wlan-ng card
00154 *
00155 * Arguments:
00156 *       char *devname : device name
00157 *       int channel   : channel (not checked !) 
00158 *
00159 * Returns: 
00160 *       0       - success 
00161 *       ~0      - failure
00162 ----------------------------------------------------------------*/
00163 int selectChannelWLAN(char *devname, int channel)
00164 {
00165   INT result = 0;
00166 
00167 #ifdef WITH_SYSTEMCALL
00168   char CmdSystem[128];
00169 #endif
00170 
00171   debug(3, "%s#%d : devname=%s , channel=%02d\n", __FUNCTION__, __LINE__,
00172         devname, channel);
00173 
00174   PrintScaleChannel(channel);
00175 
00176   debug(3, "%s#%d : Define SChannel = %02d\n", __FUNCTION__, __LINE__,
00177         channel);
00178   Res.SChannel = channel;
00179 
00180 /*  No more stop monitor mode before change channel
00181 #ifdef LWNG_20
00182 
00183 #ifndef WITH_SYSTEMCALL
00184   // Stop Sniff function if wlan-ng driver version is greater or egual to 0.2.0
00185   memset (&lnxreq_wlansniff, 0, sizeof (p80211msg_lnxreq_wlansniff_t));
00186   lnxreq_wlansniff.msgcode = DIDmsg_lnxreq_wlansniff;
00187   lnxreq_wlansniff.msglen = sizeof (p80211msg_lnxreq_wlansniff_t);
00188   strncpy ((char *) lnxreq_wlansniff.devname, devname, DEVNAME_LEN - 1);
00189 
00190   lnxreq_wlansniff.enable.did = DIDmsg_lnxreq_wlansniff_enable;
00191   lnxreq_wlansniff.enable.data = P80211ENUM_truth_false;
00192   lnxreq_wlansniff.enable.len = 4;
00193 
00194   lnxreq_wlansniff.channel.did = DIDmsg_lnxreq_wlansniff_channel;
00195   lnxreq_wlansniff.channel.status = P80211ENUM_msgitem_status_no_value;
00196   lnxreq_wlansniff.channel.len = 4;
00197 
00198   lnxreq_wlansniff.prismheader.did = DIDmsg_lnxreq_wlansniff_prismheader;
00199   lnxreq_wlansniff.prismheader.status = P80211ENUM_msgitem_status_no_value;
00200   lnxreq_wlansniff.prismheader.len = 4;
00201 
00202   lnxreq_wlansniff.wlanheader.did = DIDmsg_lnxreq_wlansniff_wlanheader;
00203   lnxreq_wlansniff.wlanheader.status = P80211ENUM_msgitem_status_no_value;
00204   lnxreq_wlansniff.wlanheader.len = 4;
00205 
00206   lnxreq_wlansniff.keepwepflags.did = DIDmsg_lnxreq_wlansniff_keepwepflags;
00207   lnxreq_wlansniff.keepwepflags.status = P80211ENUM_msgitem_status_no_value;
00208   lnxreq_wlansniff.keepwepflags.len = 4;
00209 
00210   lnxreq_wlansniff.stripfcs.did = DIDmsg_lnxreq_wlansniff_stripfcs;
00211   lnxreq_wlansniff.stripfcs.status = P80211ENUM_msgitem_status_no_value;
00212   lnxreq_wlansniff.stripfcs.len = 4;
00213 
00214   lnxreq_wlansniff.packet_trunc.did = DIDmsg_lnxreq_wlansniff_packet_trunc;
00215   lnxreq_wlansniff.packet_trunc.status = P80211ENUM_msgitem_status_no_value;
00216   lnxreq_wlansniff.packet_trunc.len = 4;
00217 
00218   lnxreq_wlansniff.resultcode.did = DIDmsg_lnxreq_wlansniff_resultcode;
00219   lnxreq_wlansniff.resultcode.status = P80211ENUM_msgitem_status_no_value;
00220   lnxreq_wlansniff.resultcode.len = 4;
00221 
00222   result = do_ioctl (devname, (UINT8 *) & lnxreq_wlansniff, sizeof(p80211msg_lnxreq_wlansniff_t));
00223 #else
00224   sprintf (CmdSystem,
00225      "wlanctl-ng %s lnxreq_wlansniff enable=false > /dev/null",
00226      devname);
00227   result = system (CmdSystem);
00228 #endif  // WITH_SYSTEMCALL
00229 
00230   debug (3, "#%d : lnxreq_wlansniff enable=false\n", __LINE__);
00231 
00232   if (result) {
00233     warning ("Warning : Exit from monitor mode failed\n");
00234   }
00235 #endif  // LWNG_20
00236 */
00237 
00238   // Second part
00239   // put in monitor mode with the good channel
00240 
00241 #ifndef WITH_SYSTEMCALL
00242   memset(&lnxreq_wlansniff, 0, sizeof(p80211msg_lnxreq_wlansniff_t));
00243   lnxreq_wlansniff.msgcode = DIDmsg_lnxreq_wlansniff;
00244   lnxreq_wlansniff.msglen = sizeof(p80211msg_lnxreq_wlansniff_t);
00245 
00246   strncpy((char *) lnxreq_wlansniff.devname, devname, DEVNAME_LEN - 1);
00247 
00248   lnxreq_wlansniff.enable.did = DIDmsg_lnxreq_wlansniff_enable;
00249   lnxreq_wlansniff.enable.data = P80211ENUM_truth_true;
00250   lnxreq_wlansniff.enable.len = 4;
00251 
00252   lnxreq_wlansniff.channel.did = DIDmsg_lnxreq_wlansniff_channel;
00253   lnxreq_wlansniff.channel.data = channel;
00254   lnxreq_wlansniff.channel.len = 4;
00255 
00256   lnxreq_wlansniff.prismheader.did = DIDmsg_lnxreq_wlansniff_prismheader;
00257   lnxreq_wlansniff.prismheader.data = P80211ENUM_truth_true;
00258   lnxreq_wlansniff.prismheader.len = 4;
00259 
00260   lnxreq_wlansniff.keepwepflags.did = DIDmsg_lnxreq_wlansniff_keepwepflags;
00261   lnxreq_wlansniff.keepwepflags.data = P80211ENUM_truth_false;
00262   lnxreq_wlansniff.keepwepflags.len = 4;
00263 
00264   lnxreq_wlansniff.resultcode.did = DIDmsg_lnxreq_wlansniff_resultcode;
00265   lnxreq_wlansniff.resultcode.status = P80211ENUM_msgitem_status_no_value;
00266   lnxreq_wlansniff.resultcode.len = 4;
00267 
00268   result =
00269       do_ioctl(devname, (UINT8 *) & lnxreq_wlansniff,
00270                sizeof(p80211msg_lnxreq_wlansniff_t));
00271 #else
00272   sprintf(CmdSystem,
00273           "wlanctl-ng %s lnxreq_wlansniff enable=true channel=%d "
00274           "keepwepflags=false prismheader=true > /dev/null", devname,
00275           channel);
00276   result = system(CmdSystem);
00277 
00278 #endif
00279 
00280   debug(3,
00281         "%s#%d : lnxreq_wlansniff enable=true channel=%02d "
00282         "keepwepflags=false prismheader=true\n", __FUNCTION__, __LINE__,
00283         channel);
00284 
00285   // Check result
00286   if (result) {
00287     fatal
00288         (ERROR_CANT_SET_CHANNEL, "Fatal error : change to Channel %d failed (%s:%d)\n",
00289          channel, __FUNCTION__, __LINE__);
00290   }
00291 
00292   return result;
00293 }
00294 
00295 /***
00296  * Function needed to stop correctly the monitor mode
00297  ***/
00298 int shutCardWLAN(char *devname)
00299 {
00300   INT result = 0;
00301 #ifdef WITH_SYSTEMCALL
00302   char CmdSystem[128];
00303 #endif
00304 
00305   /* Down interface */
00306   IfconfigSetFlags(devname, 0);
00307 
00308 #ifndef WITH_SYSTEMCALL
00309   /* Stop Sniff function */
00310   memset(&lnxreq_wlansniff, 0, sizeof(p80211msg_lnxreq_wlansniff_t));
00311 
00312   lnxreq_wlansniff.msgcode = DIDmsg_lnxreq_wlansniff;
00313   lnxreq_wlansniff.msglen = sizeof(p80211msg_lnxreq_wlansniff_t);
00314 
00315   strncpy((char *) lnxreq_wlansniff.devname, devname, DEVNAME_LEN - 1);
00316 
00317   lnxreq_wlansniff.enable.did = DIDmsg_lnxreq_wlansniff_enable;
00318   lnxreq_wlansniff.enable.data = P80211ENUM_truth_false;
00319   lnxreq_wlansniff.enable.len = 4;
00320 
00321   lnxreq_wlansniff.channel.did = DIDmsg_lnxreq_wlansniff_channel;
00322   lnxreq_wlansniff.channel.status = P80211ENUM_msgitem_status_no_value;
00323   lnxreq_wlansniff.channel.len = 4;
00324 
00325   lnxreq_wlansniff.resultcode.did = DIDmsg_lnxreq_wlansniff_resultcode;
00326   lnxreq_wlansniff.resultcode.status = P80211ENUM_msgitem_status_no_value;
00327   lnxreq_wlansniff.resultcode.len = 4;
00328 
00329   result =
00330       do_ioctl(lnxreq_wlansniff.devname, (UINT8 *) & lnxreq_wlansniff,
00331                sizeof(p80211msg_lnxreq_wlansniff_t));
00332 #else
00333   sprintf(CmdSystem,
00334           "wlanctl-ng %s lnxreq_wlansniff enable=false > /dev/null",
00335           dev, channel);
00336   result = system(CmdSystem);
00337 #endif
00338 
00339   debug(3, "%s#%d : lnxreq_wlansniff enable=false\n", __FUNCTION__,
00340         __LINE__);
00341 
00342   return result;
00343 
00344 }
00345 
00346 int openCardWLAN(char *devname)
00347 {
00348   INT result = 0;
00349 #ifdef WITH_SYSTEMCALL
00350   char CmdSystem[32];
00351 #endif
00352 
00353 #ifndef WITH_SYSTEMCALL
00354   /* put interface state UP  */
00355   memset(&lnxreq_ifstate, 0, sizeof(p80211msg_lnxreq_ifstate_t));
00356   lnxreq_ifstate.msgcode = DIDmsg_lnxreq_ifstate;
00357   lnxreq_ifstate.msglen = sizeof(p80211msg_lnxreq_ifstate_t);
00358 
00359   strncpy((char *) lnxreq_ifstate.devname, devname, DEVNAME_LEN - 1);
00360 
00361   lnxreq_ifstate.ifstate.did = DIDmsg_lnxreq_ifstate_ifstate;
00362   lnxreq_ifstate.ifstate.len = 4;
00363   lnxreq_ifstate.ifstate.data = P80211ENUM_ifstate_enable;
00364 
00365   lnxreq_ifstate.resultcode.did = DIDmsg_lnxreq_ifstate_resultcode;
00366   lnxreq_ifstate.resultcode.len = 4;
00367   lnxreq_ifstate.resultcode.status = P80211ENUM_msgitem_status_no_value;
00368 
00369   result =
00370       do_ioctl(devname, (UINT8 *) & lnxreq_ifstate,
00371                sizeof(p80211msg_lnxreq_ifstate_t));
00372 #else
00373   sprintf(CmdSystem,
00374           "wlanctl-ng %s lnxreq_ifstate ifstate=enable > /dev/null",
00375           dev, channel);
00376   result = system(CmdSystem);
00377 #endif
00378 
00379   debug(3, "%s#%d : lnxreq_ifstate ifstate=enable\n", __FUNCTION__,
00380         __LINE__);
00381   // Check result
00382   if (result) {
00383     fatal(ERROR_IF_CANT_INIT, "Warning : Change state of interface to enable failed\n");
00384   }
00385 #ifndef WITH_SYSTEMCALL
00386 
00387   /* Stop Sniff function */
00388   memset(&lnxreq_wlansniff, 0, sizeof(p80211msg_lnxreq_wlansniff_t));
00389   lnxreq_wlansniff.msgcode = DIDmsg_lnxreq_wlansniff;
00390   lnxreq_wlansniff.msglen = sizeof(p80211msg_lnxreq_wlansniff_t);
00391 
00392   strncpy((char *) lnxreq_wlansniff.devname, devname, DEVNAME_LEN - 1);
00393 
00394   lnxreq_wlansniff.enable.did = DIDmsg_lnxreq_wlansniff_enable;
00395   lnxreq_wlansniff.enable.data = P80211ENUM_truth_false;
00396   lnxreq_wlansniff.enable.len = 4;
00397 
00398   lnxreq_wlansniff.channel.did = DIDmsg_lnxreq_wlansniff_channel;
00399   lnxreq_wlansniff.channel.status = P80211ENUM_msgitem_status_no_value;
00400   lnxreq_wlansniff.channel.len = 4;
00401 
00402   lnxreq_wlansniff.resultcode.did = DIDmsg_lnxreq_wlansniff_resultcode;
00403   lnxreq_wlansniff.resultcode.status = P80211ENUM_msgitem_status_no_value;
00404   lnxreq_wlansniff.resultcode.len = 4;
00405 
00406   result =
00407       do_ioctl(devname, (UINT8 *) & lnxreq_wlansniff,
00408                sizeof(p80211msg_lnxreq_wlansniff_t));
00409 #else
00410   sprintf(CmdSystem,
00411           "wlanctl-ng %s lnxreq_wlansniff enable=false channel= > /dev/null");
00412   result = system(CmdSystem);
00413 #endif
00414   debug(3, "%s#%d : lnxreq_wlansniff enable=false channel= \n",
00415         __FUNCTION__, __LINE__);
00416   if ((result)
00417       && (lnxreq_wlansniff.msgcode != P80211ENUM_resultcode_success)
00418       && (lnxreq_wlansniff.msgcode != P80211ENUM_resultcode_refused)) {
00419     warning("Warning : Exit from monitor mode failed\n");
00420   }
00421   // Put no IP, so better hide from hell ;)
00422   // put interface up with addresse 0
00423   result += IfconfigSetFlags(devname, IFF_UP);
00424 
00425   return result;
00426 }
00427 
00428 
00429 // Get packet from card and fill correctly radio structure
00430 int getPacketWLAN(p80211_caphdr_t * wlan_header, UINT8 * buf, int maxlen)
00431 {
00432   struct pcap_pkthdr pktHdr;
00433   u_char *RadioPacket;
00434   fd_set rs;
00435   // p80211msg_lnxind_wlansniffrm_t *Sniff_Frame;
00436 
00437   FD_ZERO(&rs);
00438   FD_SET(0, &rs);
00439 
00440   RadioPacket = (u_char *) pcap_next(ca.pcap, &pktHdr);
00441 
00442   //DEBUG 
00443   if (RadioPacket != NULL) {
00444     debug(3, "RadioPacket= %x  - pktHdr.len = %x\n", RadioPacket,
00445           pktHdr.len);
00446 
00447     // If no problem and packet is enought big (with data)
00448     if (pktHdr.len >= sizeof(p80211msg_lnxind_wlansniffrm_t)) {
00449       if (pktHdr.len > MAX_BUFFER_SIZE) {
00450         debug(1, "ERROR : Packet is TOOO BIG size=%d\n", pktHdr.len);
00451         // Sometimes Wlan-NG return an enormous empty packet ...
00452         //DumpHexPaquets(RealTime_WND, buf, 0x1B0);
00453         return 0;
00454       } else {
00455         FillRadioData(&wlan_header, ca.DataLink, RadioPacket, pktHdr.len);
00456         memcpy_buff(buf, RadioPacket + ca.offset,
00457                     MIN_OF((pktHdr.len - ca.offset), maxlen));
00458         return MAX_OF(0,
00459                       (pktHdr.len -
00460                        sizeof(p80211msg_lnxind_wlansniffrm_t)));
00461       }
00462     }
00463   }
00464   return (0);                   /* Noting to read */
00465 }
00466 
00467 
00468 // The packet catcher !
00469 int openPacketWLAN(char *devname)
00470 {
00471   ca.pcap = pcap_open_live(devname, 3000, 1, 1, errbuf);
00472   if (ca.pcap) {
00473     pcap_setnonblock(ca.pcap, 1, errbuf);
00474     ca.DataLink = pcap_datalink(ca.pcap);
00475     ca.offset = CalculateOffset(ca.DataLink);
00476     return NO_ERROR;
00477   }
00478   return ERROR_CANT_OPEN_PCAP;
00479 }
00480 
00481 // Close pcap
00482 void closePacketWLAN(void)
00483 {
00484   pcap_close(ca.pcap);
00485 }

Generated on Fri Jul 25 17:10:37 2008 for WifiScanner by  doxygen 1.5.5