packets/packet_obsd_bpf.c

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

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