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
00028
00029 static int
00030 bpf_open()
00031 {
00032 int fd;
00033 int n = 0;
00034 char device[sizeof "/dev/bpf0000000000"];
00035
00036
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
00045 }
00046 return fd;
00047 }
00048
00049
00050
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
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
00103 }
00104
00105
00106 if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) {
00107 err(FATAL, "BIOCGDLT: %s", strerror(errno));
00108
00109 }
00110 if (dlt != DLT_EN10MB) {
00111 err(FATAL, "%s is not an ethernet", Interface->Name);
00112
00113 }
00114
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
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
00129 }
00130
00131
00132 immediate = 1;
00133 if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
00134 err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
00135
00136 }
00137
00138
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
00144 }
00145
00146
00147
00148 immediate = 0;
00149 if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
00150 err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno));
00151
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
00165
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
00182 if (ioctl(interface->FD, BIOCGBLEN, (caddr_t) & bufsize1) < 0) {
00183 err(FATAL, "BIOCGBLEN: %s", strerror(errno));
00184
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
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
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
00219 }
00220
00221
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
00235 PacketSlot=GetEmptyPacket();
00236 if (PacketSlot==PACKET_NONE) return FALSE;
00237 p=&Globals.Packets[PacketSlot];
00238 p->InterfaceNum=InterfaceID;
00239
00240
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
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
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
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
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