packets/packet_osx_bpf.c

Go to the documentation of this file.
00001 #include "packet_osx_bpf.h"
00002 #ifdef _OSX_
00003 
00004 #include <sys/types.h>
00005 #include <sys/socket.h>
00006 #include <netinet/in.h>
00007 #include <unistd.h>
00008 #include <fcntl.h>
00009 #include <sys/ioctl.h>
00010 #include <net/if.h>
00011 #include <time.h>
00012 #include <net/bpf.h>
00013 #include <errno.h>
00014 #include <err.h>
00015 #include <string.h>
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 
00019 #define DEBUG
00020 
00021 #define FATAL           1
00022 #define NONFATAL        0
00023 
00024 extern GlobalVars       Globals;
00025 
00026 /***********************************************
00027 * Open up a bpf
00028 ***********************************************/
00029 static int
00030 bpf_open()
00031 {
00032         int     fd;
00033         int     n = 0;
00034         char    device[sizeof "/dev/bpf0000000000"];
00035 
00036         /* Go through all the minors and find one that isn't in use. */
00037         do {
00038                 (void) snprintf(device, sizeof device, "/dev/bpf%d", n++);
00039                 fd = open(device, O_RDWR);
00040         } while (fd < 0 && errno == EBUSY);
00041 
00042         if (fd < 0) {
00043                 err(FATAL, "%s: %s", device, strerror(errno));
00044                 /* NOTREACHED */
00045         }
00046         return fd;
00047 }
00048 
00049 /*********************************************
00050 * Get the MTU of interface named "name"
00051 *********************************************/
00052 int GetIfrMTU(char *name) {
00053     int fd;
00054     struct ifreq ifr;
00055     int retval;
00056 
00057     retval = -1;
00058     fd = socket(AF_INET, SOCK_DGRAM, 0);
00059     if ( fd < 0) {
00060         printf("Couldn't create socket for MTU\n");
00061         return -1;
00062     }
00063 
00064     strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
00065     if (ioctl(fd, SIOCGIFMTU, &ifr) == 0)
00066         retval = ifr.ifr_metric;
00067     else
00068         printf("ioctl(SIOCGIFMTU)");    
00069     close(fd);
00070         return retval;
00071 }
00072 
00073 
00074 /*********************************************
00075 * Open an interface OSX BPF's
00076 **********************************************/
00077 int OpenInterfaceOSXBPF(int InterfaceID){
00078         int                     fd;
00079         struct                  ifreq ifr;
00080         u_int                   dlt;
00081         int                     immediate;
00082         int                             promisc;
00083         int                             link;
00084         struct timeval  timeout;
00085         InterfaceRec*   Interface;
00086 
00087 #ifdef DEBUGPATH
00088         printf("In OpenInterfaceOSXBPF\n");
00089 #endif
00090 
00091         Interface=&Globals.Interfaces[InterfaceID];
00092 
00093 #ifdef DEBUG
00094         printf("Opening interface %s\n", Interface->Name);
00095 #endif
00096 
00097         fd = bpf_open();
00098 
00099         (void) strncpy(ifr.ifr_name, Interface->Name, sizeof ifr.ifr_name);
00100         if (ioctl(fd, BIOCSETIF, (caddr_t) & ifr) < 0) {
00101                 err(FATAL, "BIOCSETIF: %s", strerror(errno));
00102                 /* NOTREACHED */
00103         }
00104         /* Check that the data link layer is an Ethernet; this code won't work
00105          * with anything else. */
00106         if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) {
00107                 err(FATAL, "BIOCGDLT: %s", strerror(errno));
00108                 /* NOTREACHED */
00109         }
00110         if (dlt != DLT_EN10MB) {
00111                 err(FATAL, "%s is not an ethernet", Interface->Name);
00112                 /* NOTREACHED */
00113         }
00114         /*turn off automatic filling of the mac address*/
00115         link=1;
00116         if (ioctl(fd, BIOCSHDRCMPLT, &link) < 0){
00117                 printf("Couldn't turn off auto mac address\n");
00118                 exit(0);
00119         }
00120         /* Switch the interface into promisc mode*/
00121         promisc=1;
00122         if (ioctl(fd, BIOCPROMISC, &promisc) < 0) {
00123                 printf("Couldn't enter promisc mode\n");
00124                 exit(1);
00125         }
00126         if (dlt != DLT_EN10MB) {
00127                 err(FATAL, "%s is not an ethernet", Interface->Name);
00128                 /* NOTREACHED */
00129         }       
00130         
00131         /* Set immediate mode so packets are processed as they arrive. */
00132         immediate = 1;
00133         if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
00134                 err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
00135                 /* NOTREACHED */
00136         }
00137 
00138         /* Set immediate mode so packets are processed as they arrive. */
00139         timeout.tv_sec=0;
00140         timeout.tv_usec=1;
00141         if (ioctl(fd, BIOCSRTIMEOUT, &timeout) < 0) {
00142                 err(FATAL, "BIOCSRTIMEOUT: %s", strerror(errno));
00143                 /* NOTREACHED */
00144         }
00145 
00146 
00147         /* Set immediate mode so packets are processed as they arrive. */
00148         immediate = 0;
00149         if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
00150                 err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
00151                 /* NOTREACHED */
00152         }
00153 
00154         Interface->FD=fd;
00155         Interface->MTU=GetIfrMTU(Interface->Name);
00156         if (Interface->MTU==-1) Interface->MTU=1500;
00157 
00158         Interface->IsPollable=TRUE;
00159 
00160         return TRUE;
00161 }
00162 
00163 /**********************************************
00164 * Read a packet off of the bpf
00165 * TODO: Get rid of the malloc
00166 **********************************************/
00167 int ReadPacketOSXBPF(int InterfaceID){
00168         int                     bufsize1, cc;
00169         u_char                  *buf1, *bp, *ep;
00170         
00171         InterfaceRec*   interface;
00172         PacketRec*              p;
00173         int             PacketSlot;
00174 
00175 #ifdef DEBUGPATH
00176         printf("In ReadPacketOSXBPF\n");
00177 #endif
00178         
00179         interface=&Globals.Interfaces[InterfaceID];
00180         
00181         /*Get the sizes of the buffers*/
00182         if (ioctl(interface->FD, BIOCGBLEN, (caddr_t) & bufsize1) < 0) {
00183                 err(FATAL, "BIOCGBLEN: %s", strerror(errno));
00184                 /* NOTREACHED */
00185         }
00186 #ifdef DEBUG1   
00187         printf("Buffer size1 is %i\n",bufsize1);
00188 #endif
00189                  
00190         buf1 = (u_char *) malloc((unsigned) bufsize1);
00191         if (buf1 == 0) {
00192                 err(FATAL, "malloc: %s", strerror(errno));
00193                 /* NOTREACHED */
00194         }
00195                 
00196         again:
00197         cc = read(interface->FD, (char *) buf1, bufsize1);
00198 #ifdef DEBUG1                           
00199         printf("Read %i bytes from the bpf\n",cc);
00200 #endif                                  
00201 
00202         if (cc==0){
00203                 free(buf1);
00204                 return TRUE;
00205         }
00206 
00207         /* Don't choke when we get ptraced */
00208         if (cc < 0 && errno == EINTR)
00209                 goto again;
00210         if (cc < 0) {
00211                 if (errno == EINVAL &&
00212                 (lseek(interface->FD, 0, SEEK_CUR) + bufsize1) < 0) {
00213                                 (void) lseek(interface->FD, 0, 0);
00214                                 goto again;
00215                 }
00216                 err(FATAL, "read: %s", strerror(errno));
00217                 
00218                 /* NOTREACHED */
00219         }
00220         
00221         /* Loop through the packet(s) */
00222 #define bhp ((struct bpf_hdr *)bp)
00223         bp = buf1;
00224         ep = bp + cc;
00225         while (bp < ep) {
00226                 register int caplen, hdrlen;
00227 
00228                 caplen = bhp->bh_caplen;
00229                 hdrlen = bhp->bh_hdrlen;
00230                 
00231 #ifdef DEBUG
00232                 printf("This packet is %u bytes\n",bhp->bh_caplen);
00233 #endif  
00234                 /*Get a new packet*/
00235                 PacketSlot=GetEmptyPacket();
00236                 if (PacketSlot==PACKET_NONE) return FALSE;
00237                 p=&Globals.Packets[PacketSlot];
00238                 p->InterfaceNum=InterfaceID;
00239 
00240                 /*fill it in*/
00241                 p->PacketLen=bhp->bh_caplen;                                    
00242                 p->tv.tv_sec=bhp->bh_tstamp.tv_sec;
00243                 p->tv.tv_usec=bhp->bh_tstamp.tv_usec;
00244                 memcpy(p->RawPacket, bp+18, p->PacketLen);
00245                 
00246                 /*send it off*/
00247                 if (!AddPacketToPending(PacketSlot)){
00248                         printf("Coulnd't add packet to pending queue\n");
00249                         ReturnEmptyPacket(PacketSlot);
00250                         free(buf1);
00251                         return FALSE;
00252                 }
00253                 bp += BPF_WORDALIGN(hdrlen + caplen);
00254         }
00255 
00256         free(buf1);     
00257         return TRUE;
00258 }
00259 
00260 /***************************************************
00261 * Send a packet off to the bpf
00262 ****************************************************/
00263 int WritePacketOSXBPF(int InterfaceID, unsigned char* Packet, int PacketLen){
00264         InterfaceRec*   interface;
00265         int                     cc;
00266         
00267 #ifdef DEBUGPATH
00268         printf("In WritePacketOSXBPF\n");
00269 #endif
00270 
00271         interface=&Globals.Interfaces[InterfaceID];
00272 
00273 #ifdef DEBUG
00274         printf("Writing packet OBX to interface %s\n",interface->Name);
00275 #endif
00276         
00277         cc=write(interface->FD, Packet, PacketLen);
00278         if (cc!=PacketLen){
00279 #ifdef DEBUG
00280                 printf("write_packet: Failed to write packet ot interface %s\n",interface->Name);
00281 #endif
00282                 return FALSE;
00283         }
00284 
00285         return TRUE;
00286 }
00287 
00288 /**********************************************
00289 * The thread func
00290 **********************************************/
00291 void* OSXBPFLoopFunc(void* v){
00292         int                             InterfaceID;
00293 
00294 #ifdef DEBUGPATH
00295         printf("In OSXBPFLoopFunc\n");
00296 #endif
00297 
00298         InterfaceID=(int)v;
00299         while (!Globals.Done){
00300                 ReadPacketOSXBPF(InterfaceID);
00301         }
00302         
00303         return NULL;
00304 }
00305 
00306 /**********************************************
00307 * Start a thread to continuously read
00308 **********************************************/
00309 int LoopThreadOSXBPF(int InterfaceID){
00310 #ifdef DEBUGPATH
00311         printf("In loopThreadOSXBPF\n");
00312 #endif
00313 
00314 #ifndef HAS_THREADS
00315         return FALSE;
00316 #else
00317 
00318 #ifdef DEBUG
00319         printf("Starting Thread for interface %s\n",Globals.Interfaces[InterfaceID].Name);
00320 #endif
00321 
00322         Globals.Interfaces[InterfaceID].ThreadID=pthread_create(
00323                 &Globals.Interfaces[InterfaceID].Thread,
00324                 NULL,
00325                 OSXBPFLoopFunc,
00326                 (void*)InterfaceID
00327         );
00328         
00329         return (!Globals.Interfaces[InterfaceID].ThreadID);     
00330 #endif  
00331 }
00332 
00333 #endif /*if OSX*/

Generated on Sat Jul 7 23:33:10 2007 for HLBR by  doxygen 1.5.2