packets/packet_linux_raw.c

Go to the documentation of this file.
00001 #include "packet_linux_raw.h"
00002 
00003 #ifdef _LINUX_
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 <sys/time.h>
00012 #include <linux/if_ether.h>
00013 #include <linux/if_packet.h>
00014 #include <sys/poll.h>
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include <stdlib.h>
00018 
00019 //#define DEBUG
00020 
00021 extern GlobalVars       Globals;
00022 
00023 /*********************************************
00024 * Get the MTU of interface named "name"
00025 *********************************************/
00026 int GetIfrMTU(char *name) {
00027     int fd;
00028     struct ifreq ifr;
00029     int retval;
00030 
00031     retval = -1;
00032     fd = socket(AF_INET, SOCK_DGRAM, 0);
00033     if ( fd < 0) {
00034         printf("Couldn't create socket for MTU\n");
00035         return -1;
00036     }
00037 
00038     strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
00039     if (ioctl(fd, SIOCGIFMTU, &ifr) == 0)
00040         retval = ifr.ifr_metric;
00041     else
00042         printf("ioctl(SIOCGIFMTU)");    
00043     close(fd);
00044         return retval;
00045 }
00046 
00047 /*********************************************
00048 * Get the id of interface named "name"
00049 * Needed to open the interface
00050 *********************************************/
00051 int get_device_id(int fd, char* name){
00052         struct ifreq    ifr;
00053 
00054         bzero(&ifr, sizeof(struct ifreq));
00055         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));      
00056         if (ioctl(fd, SIOGIFINDEX, &ifr) == -1) return -1;
00057         return ifr.ifr_ifindex; 
00058 }
00059 
00060 /*********************************************
00061 * Open an interface via Linux Raw Sockets
00062 **********************************************/
00063 int OpenInterfaceLinuxRaw(int InterfaceID){
00064         int                             fd;
00065         struct sockaddr_ll      sll;
00066         int                                     ssize;
00067         int                                     errnum;
00068         struct packet_mreq      mr;
00069         InterfaceRec*           Interface;
00070 
00071         DEBUGPATH;
00072 
00073         Interface=&Globals.Interfaces[InterfaceID];
00074 
00075 #ifdef DEBUG
00076         printf("Opening interface %s\n", Interface->Name);
00077 #endif
00078 
00079         fd=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
00080         bzero(&sll,sizeof(struct sockaddr_ll));
00081         sll.sll_family=AF_PACKET;
00082         sll.sll_ifindex=get_device_id(fd, Interface->Name);
00083         sll.sll_protocol=htons(ETH_P_ALL);
00084         ssize=sizeof(struct sockaddr_ll);
00085 
00086         errnum=bind(fd, (struct sockaddr*)&sll, sizeof(sll));
00087         if (errnum==-1){
00088                 printf("Error Binding socket\n");
00089                 return FALSE;
00090         }
00091         
00092         /*set promisc mode*/
00093         memset(&mr, 0, sizeof(mr));
00094         mr.mr_ifindex=get_device_id(fd, Interface->Name);
00095         mr.mr_type=PACKET_MR_PROMISC;
00096         if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr))==-1){
00097                 printf("Failed to set promisc mode\n");
00098                 return FALSE;
00099         }
00100 
00101         Interface->FD=fd;
00102         Interface->MTU=GetIfrMTU(Interface->Name);
00103         if (Interface->MTU==-1) Interface->MTU=1500;
00104 
00105         Interface->IsPollable=TRUE;
00106         
00107         return TRUE;
00108 }
00109 
00110 /**********************************************
00111 * Read a packet off of a Linux Raw Socket
00112 **********************************************/
00113 int ReadPacketLinuxRaw(int InterfaceID){
00114         int                     count;
00115         InterfaceRec*   Interface;
00116         int                             PacketSlot;
00117         PacketRec*              p;
00118 #ifdef DEBUG    
00119         int                             i;
00120 #endif  
00121         
00122         DEBUGPATH;
00123 
00124         Interface=&Globals.Interfaces[InterfaceID];
00125         if ( (PacketSlot=GetEmptyPacket())==-1){
00126                 printf("Unable to allocate packet for reading\n");
00127 #ifdef DEBUG            
00128                 printf("Packets are in the following states:\n");
00129                 for (i=0;i<MAX_PACKETS;i++){
00130                         switch (Globals.Packets[i].Status){
00131                         case PACKET_STATUS_IDLE:
00132                                 printf("%i: idle\n",i);
00133                                 break;
00134                         case PACKET_STATUS_PENDING:
00135                                 printf("%i: pending\n",i);
00136                                 break;                          
00137                         case PACKET_STATUS_SAVED:
00138                                 printf("%i: saved\n",i);
00139                                 break;                          
00140                         case PACKET_STATUS_ALLOCATED:
00141                                 printf("%i: allocated\n",i);
00142                                 break;                          
00143                         case PACKET_STATUS_PROCESSING:
00144                                 printf("%i: processing\n",i);
00145                                 break;                          
00146                         default:
00147                                 printf("%i: unknown(%i)\n",i, Globals.Packets[i].Status);
00148                         }
00149                 }
00150 #endif                  
00151                 return FALSE;           
00152         }       
00153 
00154         
00155         p=&Globals.Packets[PacketSlot];
00156         
00157         p->InterfaceNum=InterfaceID;
00158 
00159         count = read(Interface->FD, (char*)p->RawPacket, TYPICAL_PACKET_SIZE-1);
00160         if (count==-1){
00161 #ifdef DEBUG    
00162                 printf("Failed to read packet. FD %i\n", Interface->FD);
00163 #endif          
00164                 ReturnEmptyPacket(PacketSlot);
00165                 return FALSE;
00166         }
00167         p->PacketLen=count;
00168         
00169         if (ioctl(Interface->FD, SIOCGSTAMP, &p->tv)==-1){
00170 #ifdef DEBUG    
00171                 printf("Failed to get timestamp\n");
00172 #endif
00173                 ReturnEmptyPacket(PacketSlot);
00174                 return FALSE;
00175         }
00176 
00177         if (!AddPacketToPending(PacketSlot)){
00178                 printf("Coulnd't add packet to pending queue\n");
00179                 ReturnEmptyPacket(PacketSlot);
00180                 return FALSE;
00181         }
00182 
00183         return TRUE;
00184 }
00185 
00186 /***************************************************
00187 * Send a packet off to the raw interface
00188 ****************************************************/
00189 int WritePacketLinuxRaw(int InterfaceID, unsigned char* Packet, int PacketLen){
00190         int count;
00191         InterfaceRec* interface;
00192         
00193         DEBUGPATH;
00194 
00195         interface=&Globals.Interfaces[InterfaceID];
00196         
00197         count=write(interface->FD, Packet, PacketLen);
00198         if (count==-1){
00199                 printf("Failed to write packet to interface %s\n",interface->Name);
00200                 return FALSE;
00201         }
00202         
00203         return TRUE;
00204 }
00205 
00206 /**********************************************
00207 * The thread func
00208 **********************************************/
00209 void* LinuxRawLoopFunc(void* v){
00210         int                             InterfaceID;
00211 
00212         DEBUGPATH;
00213 
00214         InterfaceID=(int)v;
00215         while (!Globals.Done){
00216                 ReadPacketLinuxRaw(InterfaceID);
00217         }
00218         
00219         return NULL;
00220 }
00221 
00222 /**********************************************
00223 * Start a thread to continuously read
00224 **********************************************/
00225 int LoopThreadLinuxRaw(int InterfaceID){
00226 
00227         DEBUGPATH;
00228 
00229 #ifndef HAS_THREADS
00230         return FALSE;
00231 #else
00232 
00233 #ifdef DEBUG
00234         printf("Starting Thread for interface %s\n",Globals.Interfaces[InterfaceID].Name);
00235 #endif
00236 
00237         Globals.Interfaces[InterfaceID].ThreadID=pthread_create(
00238                 &Globals.Interfaces[InterfaceID].Thread,
00239                 NULL,
00240                 LinuxRawLoopFunc,
00241                 (void*)InterfaceID
00242         );
00243         
00244         return (!Globals.Interfaces[InterfaceID].ThreadID);
00245 #endif
00246         
00247 }
00248 
00249 #endif /*if linux*/

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