ll_com.c
Go to the documentation of this file.
00001 /*------------------------------------------------------------------------
00002  *---------------------           RT-WMP              --------------------
00003  *------------------------------------------------------------------------
00004  *                                                         V7.0B  11/05/10
00005  *
00006  *
00007  *  File: ./src/platforms/linux_us/hwi/raw/ll_com.c
00008  *  Authors: Danilo Tardioli
00009  *  ----------------------------------------------------------------------
00010  *  Copyright (C) 2000-2010, Universidad de Zaragoza, SPAIN
00011  *
00012  *  Contact Addresses: Danilo Tardioli                   dantard@unizar.es
00013  *
00014  *  RT-WMP is free software; you can  redistribute it and/or  modify it
00015  *  under the terms of the GNU General Public License  as published by the
00016  *  Free Software Foundation;  either  version 2, or (at  your option) any
00017  *  later version.
00018  *
00019  *  RT-WMP  is distributed  in the  hope  that  it will be   useful, but
00020  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
00021  *  MERCHANTABILITY  or  FITNESS FOR A  PARTICULAR PURPOSE.    See the GNU
00022  *  General Public License for more details.
00023  *
00024  *  You should have received  a  copy of  the  GNU General Public  License
00025  *  distributed with RT-WMP;  see file COPYING.   If not,  write to the
00026  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
00027  *  02111-1307, USA.
00028  *
00029  *  As a  special exception, if you  link this  unit  with other  files to
00030  *  produce an   executable,   this unit  does  not  by  itself cause  the
00031  *  resulting executable to be covered by the  GNU General Public License.
00032  *  This exception does  not however invalidate  any other reasons why the
00033  *  executable file might be covered by the GNU Public License.
00034  *
00035  *----------------------------------------------------------------------*/
00036 
00037 #include "config/compiler.h"
00038 #include <sys/types.h>
00039 #include <sys/time.h>
00040 #include <arpa/inet.h>
00041 #include <unistd.h>
00042 #include <assert.h>
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <string.h>
00046 #include <errno.h>
00047 #include <string.h>
00048 #include <sys/time.h>
00049 #include <ctype.h>
00050 #include <sys/ioctl.h>
00051 #include <sys/socket.h>
00052 #include <netinet/in.h>
00053 #include <linux/if.h>
00054 #include <netpacket/packet.h>
00055 #include <net/ethernet.h>     /* the L2 protocols */
00056 #include <asm/types.h>
00057 #include <time.h>
00058 #include <pcap.h>
00059 #include <netinet/if_ether.h>
00060 #include <netinet/if_ether.h>
00061 
00062 #include "core/include/ml_com.h"
00063 #include "core/include/definitions.h"
00064 #include "core/interface/wmp_interface.h"
00065 #include "core/include/wmp_misc.h"
00066 #include "core/include/frames.h"
00067 #include "core/include/ll_com.h"
00068 
00069 #include "radiotap/radiotap.h"
00070 #include "radiotap/radiotap_iter.h"
00071 
00072 static int s, rx, freq, txpower, pfd[2], dl, use_mon = 1;
00073 static struct ethhdr *eh;
00074 static struct sockaddr_ll socket_address;
00075 static char DEV[20], ESSID[32], param[20], val[20], buffer[2500], *eth_head,
00076                 *eth_data;
00077 static unsigned char src_mac[6], bcast_mac[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
00078                 0xFF };
00079 static struct pcap_pkthdr header;
00080 static pcap_t *handle;
00081 static int use_lo = 0;
00082 
00083 static int readllcfg() {
00084         char filename[256], line[256];
00085         sprintf(DEV, "lo");
00086         sprintf(ESSID, "rt-wmp");
00087         freq = 2412;
00088         txpower = 15;
00089 
00090         snprintf(filename, 256, "%s/.rt-wmp/rt-wmp-us-raw.ll", getenv("HOME"));
00091         FILE * f = fopen(filename, "r");
00092         if (f > 0) {
00093                 WMP_MSG(stderr, "Reading Low Level Configuration file (%s)... \n", filename);
00094                 while (fgets(line, 256, f) != NULL) {
00095 
00096                         if (line[0] < 65 || line[0] > 90) {
00097                                 continue;
00098                         }
00099                         sscanf(line, "%s %s", param, val);
00100 
00101                         int exists = 0;
00102                         if (strcmp(param, "DEVICE") == 0) {
00103                                 strcpy(DEV, val);
00104                                 exists = 1;
00105                         } else if (strcmp(param, "FREQ") == 0) {
00106                                 freq = atoi(val);
00107                                 exists = 1;
00108                         } else if (strcmp(param, "ESSID") == 0) {
00109                                 freq = atoi(val);
00110                                 exists = 1;
00111                         } else if (strcmp(param, "TXPOWER") == 0) {
00112                                 txpower = atoi(val);
00113                                 exists = 1;
00114                         } else if (strcmp(param, "USE_MONITOR") == 0) {
00115                                 use_mon = atoi(val);
00116                                 exists = 1;
00117                         }
00118 
00119                         if (exists) {
00120                                 WMP_MSG(stderr, "READ OPTION: %s = %s\n", param, val);
00121                         } else {
00122                                 WMP_MSG(stderr, "*** UKNOWN OPTION: %s = %s\n", param, val);
00123                         }
00124                 }
00125                 WMP_MSG(stderr, "Done.\n");
00126         } else {
00127                 WMP_MSG(stderr, "File %s not found, using default values\n", filename);
00128         }
00129         return 0;
00130 }
00131 
00132 static void parse_radiotap(struct ieee80211_radiotap_header * buf, int * rate,
00133                 char * rssi, char * noise) {
00134         int pkt_rate_100kHz = 0, antenna = 0, pwr = 0;
00135         char rssi_dbm = 0, noise_dbm = 0;
00136         struct ieee80211_radiotap_iterator iterator;
00137         int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buf->it_len, 0);
00138 
00139         while (!ret) {
00140 
00141                 ret = ieee80211_radiotap_iterator_next(&iterator);
00142 
00143                 if (ret)
00144                         continue;
00145 
00146                 /* see if this argument is something we can use */
00147 
00148                 switch (iterator.this_arg_index) {
00149                 /*
00150                  * You must take care when dereferencing iterator.this_arg
00151                  * for multibyte types... the pointer is not aligned.  Use
00152                  * get_unaligned((type *)iterator.this_arg) to dereference
00153                  * iterator.this_arg for type "type" safely on all arches.
00154                  */
00155                 case IEEE80211_RADIOTAP_RATE:
00156                         /* radiotap "rate" u8 is in
00157                          * 500kbps units, eg, 0x02=1Mbps
00158                          */
00159                         pkt_rate_100kHz = (*iterator.this_arg) * 5;
00160                         break;
00161                 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
00162                         rssi_dbm = (*iterator.this_arg);
00163                         break;
00164                 case IEEE80211_RADIOTAP_ANTENNA:
00165                         /* radiotap uses 0 for 1st ant */
00166                         antenna = (*iterator.this_arg);
00167                         break;
00168 
00169                 case IEEE80211_RADIOTAP_DBM_TX_POWER:
00170                         pwr = *iterator.this_arg;
00171                         break;
00172                 case IEEE80211_RADIOTAP_DB_ANTNOISE:
00173                         noise_dbm = *iterator.this_arg;
00174                         break;
00175                 default:
00176                         break;
00177                 }
00178         } /* while more rt headers */
00179         *noise = noise_dbm;
00180         *rssi = rssi_dbm;
00181         *rate = pkt_rate_100kHz;
00182 }
00183 
00184 static int pcap_init(char * dev, int promisc) {
00185         char errbuf[PCAP_ERRBUF_SIZE];
00186         fprintf(stderr, "Opening device %s...", dev);
00187         handle = pcap_open_live(dev, BUFSIZ, promisc, 1000, errbuf);
00188         fprintf(stderr, "Success.", dev);
00189 
00190         if (handle == NULL) {
00191                 fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
00192                 return 0;
00193         }
00194         dl = pcap_datalink(handle);
00195 }
00196 
00197 static rxInfo pcap_sniff_packet(char * data, int delay_ms) {
00198         rxInfo rxi;
00199         int offset = 0, i, rate;
00200         char rssi, noise;
00201         struct timeval tv;
00202         const u_char *packet;
00203 
00204         tv.tv_sec = 0;
00205         tv.tv_usec = 1000 * delay_ms;
00206 
00207         fd_set set1;
00208         FD_ZERO(&set1);
00209         FD_SET(pcap_fileno(handle), &set1);
00210         select(FD_SETSIZE, &set1, NULL, NULL, &tv);
00211 
00212         if (FD_ISSET(pcap_fileno(handle), &set1)) {
00213                 packet = pcap_next(handle, &header);
00214         } else {
00215                 rxi.error = 1;
00216                 return rxi;
00217         }
00218 
00219         if (packet == NULL) {
00220                 rxi.error = 1;
00221                 return rxi;
00222         }
00223 
00224         if (use_lo){
00225                 usleep(10000); //to allow other threads to enter in the simulation
00226         }
00227 
00228         switch (dl) {
00229         case 1:
00230                 offset = sizeof(struct ethhdr);
00231                 break;
00232 
00233         case 127: {
00234                 struct ieee80211_radiotap_header * rth =
00235                                 (struct ieee80211_radiotap_header*) packet;
00236                 offset = rth->it_len + 24 + 8; //radiotap+80211
00237                 parse_radiotap(rth, &rate, &rssi, &noise);
00238         }
00239                 break;
00240         default:
00241                 offset = 0;
00242         };
00243 
00244         if (header.len > offset) {
00245                 short protocol_type = ntohs(*(short*) (packet + offset - 2));
00246                 char * f_data = (char*) &packet[offset];
00247                 int f_len = header.len - offset;
00248                 f_len > 1500 ? 1500 : f_len;
00249                 rxi.rssi = 96 + rssi;
00250                 rxi.rssi = rxi.rssi > 100 ? 100 : rxi.rssi;
00251                 rxi.rssi = rxi.rssi > 0 ? rxi.rssi : 1;
00252                 rxi.rate = rate;
00253                 rxi.noise = noise;
00254                 rxi.proto = protocol_type;
00255                 rxi.error = 0;
00256                 rxi.size = f_len;
00257                 rxi.has_lq = 1;
00258                 memcpy(data, f_data, f_len);
00259                 return rxi;
00260         } else {
00261                 rxi.proto = 0;
00262                 rxi.size = 0;
00263                 rxi.error = 0;
00264                 rxi.has_lq = 0;
00265                 return rxi;
00266         }
00267 }
00268 
00269 static int eth_raw_init(char * DEVICE) {
00270 
00271         /* Vars */
00272         int i;
00273         struct ifreq ifr;
00274         int ifindex = 0; /*Ethernet Interface index*/
00275 
00276         /* Open socket */
00277         s = socket(PF_PACKET, SOCK_RAW, htons(WMP_TYPE_FIELD));
00278         if (s == -1) {
00279                 perror("socket():");
00280                 exit(1);
00281         }
00282         printf("Successfully opened socket: %i\n", s);
00283 
00284         /*Get ethernet interface index*/
00285         strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ);
00286         if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
00287                 perror("SIOCGIFINDEX");
00288                 exit(1);
00289         }
00290         ifindex = ifr.ifr_ifindex;
00291         printf("Successfully got interface index: %i\n", ifindex);
00292 
00293         /*retrieve corresponding MAC*/
00294         if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
00295                 perror("SIOCGIFINDEX");
00296                 exit(1);
00297         }
00298         for (i = 0; i < 6; i++) {
00299                 src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
00300         }
00301         WMP_MSG(stderr,"Host MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", src_mac[0],
00302                         src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]);
00303 
00304         /*prepare sockaddr_ll*/
00305         socket_address.sll_family = PF_PACKET;
00306         socket_address.sll_protocol = htons(ETH_P_ALL);
00307         socket_address.sll_ifindex = ifindex;
00308         socket_address.sll_pkttype = PACKET_BROADCAST;
00309         socket_address.sll_halen = ETH_ALEN;
00310         if (strcmp(DEV, "lo") == 0) {
00311                 WMP_MSG(stderr,"*** WARNING: Using 'lo' interface\n");
00312                 for (i = 0; i < 6; i++) {
00313                         socket_address.sll_addr[0] = src_mac[i];
00314                 }
00315         } else {
00316                 for (i = 0; i < 6; i++) {
00317                         socket_address.sll_addr[0] = bcast_mac[i];
00318                 }
00319         }
00320         socket_address.sll_addr[6] = 0x00;
00321         socket_address.sll_addr[7] = 0x00;
00322         return 0;
00323 }
00324 
00325 void closeLowLevelCom() {
00326         pcap_close(handle);
00327 }
00328 
00329 int initLowLevelCom() {
00330         char cmd[256];
00331         readllcfg();
00332         eth_raw_init(DEV);
00333         eth_head = buffer; /* eth_head points to beginning of buffer (ethernet header fields) */
00334         eth_data = buffer + ETH_HLEN; /* eth_data points to data field of the ethernet frame */
00335         eh = (struct ethhdr *) eth_head;
00336         use_lo = strcmp(DEV, "lo") == 0;
00337         if (!use_lo && use_mon) {
00338                 fprintf(stderr, "Checking sudo...");
00339                 int res = system("sudo ls >/dev/null 2>1");
00340                 if (res != 0){
00341                         fprintf(stderr, "\nUnable to execute 'sudo' exiting...");
00342                         exit(0);        
00343                 }
00344                 fprintf(stderr,"OK\n");
00345                 usleep(100000);
00346 
00347                 fprintf(stderr, "Checking iw...");
00348                 res = system("sudo iw >/dev/null 2>1");
00349                 if (res != 0){
00350                         fprintf(stderr, "\nUnable to execute 'iw' exiting...");
00351                         exit(0);        
00352                 }
00353                 fprintf(stderr,"OK\n");
00354                 usleep(100000);
00355         
00356                 fprintf(stderr, "Checking iwconfig...");
00357                 res = system("sudo iwconfig >/dev/null 2>1");
00358                 if (res != 0){
00359                         fprintf(stderr, "\nUnable to execute 'iwconfig' exiting...");
00360                         exit(0);        
00361                 }
00362                 fprintf(stderr,"OK\n");
00363                 usleep(100000);
00364 
00365                 fprintf(stderr, "Checking interface mon0...");
00366                 res = system("sudo iw dev mon0 info >/dev/null 2>1");
00367                 if (res == 0){
00368                         fprintf(stderr, "OK\n");
00369                 }else{
00370                         fprintf(stderr, "does not exist, creating...");
00371 
00372                         sprintf(cmd, "sudo ifconfig %s down >/dev/null 2>1", DEV);
00373                         res = system(cmd);
00374 
00375                         sprintf(cmd,"sudo iw dev %s interface add mon0 type monitor 2>/dev/null", DEV);
00376                         res = system(cmd);
00377                         if (res != 0){
00378                                 fprintf(stderr, "\nUnable to create mon0 interface exiting...");
00379                                 exit(0);        
00380                         }else{
00381                                 fprintf(stderr,"OK\n");                 
00382                         }
00383                 }               
00384                 usleep(500000);
00385 
00386                 res = system("sudo ifconfig mon0 down >/dev/null 2>1");
00387                 if (res != 0){
00388                         fprintf(stderr, "Unable to put mon0 down, troubles ahead...\n");
00389                 }
00390                 usleep(100000);
00391 
00392                 fprintf(stderr, "Setting frequency for mon0...");
00393                 sprintf(cmd,"sudo iwconfig mon0 freq %dM  >/dev/null 2>1", freq);
00394                 res = system(cmd);
00395                 if (res != 0){
00396                         fprintf(stderr, "failed (normal with some driver)\n");
00397                 }else{
00398                         fprintf(stderr,"OK\n");                 
00399                 }
00400                 usleep(100000);
00401 
00402                 fprintf(stderr, "Setting mode ad-hoc for %s...", DEV);
00403                 sprintf(cmd,"sudo iwconfig %s mode ad-hoc essid %s  >/dev/null 2>1", DEV, ESSID);
00404                 res = system(cmd);
00405                 if (res != 0){
00406                         fprintf(stderr, "failed, exiting...\n");
00407                         exit(0);
00408                 }else{
00409                         fprintf(stderr,"OK\n");                 
00410                 }
00411                 usleep(100000);
00412 
00413                 fprintf(stderr, "Setting frequency and tx power for %s...", DEV);
00414                 sprintf(cmd,"sudo iwconfig %s freq %dM txpower %d >/dev/null 2>1",DEV, freq, txpower);
00415                 res = system(cmd);
00416                 if (res != 0){
00417                         fprintf(stderr, "failed\n");
00418                 }else{
00419                         fprintf(stderr,"OK\n");                 
00420                 }
00421                 usleep(100000);
00422 
00423                 sprintf(cmd, "sudo ifconfig %s up 2>/dev/null", DEV);
00424                 res = system(cmd);
00425                 if (res != 0){
00426                         fprintf(stderr, "Unable to put %s up, troubles ahead...\n",DEV);
00427                 }
00428                 usleep(100000);
00429 
00430                 sprintf(cmd, "sudo ifconfig mon0 up 2>/dev/null", DEV);
00431                 res = system(cmd);
00432                 if (res != 0){
00433                         fprintf(stderr, "Unable to put mon0 up, troubles ahead...\n");
00434                 }
00435                 usleep(100000);
00436 
00437                 pcap_init("mon0", 1);
00438         } else {
00439                 pcap_init(DEV, 0);
00440         }
00441 
00442         return 1;
00443 }
00444 
00445 static int llpsend(char * f, int size, int proto) {
00446         int i;
00447         memcpy((void *) eh->h_dest, (void*) bcast_mac, ETH_ALEN);
00448         memcpy((void *) eh->h_source, (void*) src_mac, ETH_ALEN);
00449         eh->h_proto = htons(proto);
00450         memcpy(eth_data, f, size);
00451         i = sendto(s, buffer, size + ETHER_HDR_LEN, 0,
00452                         (struct sockaddr*) &socket_address, sizeof(socket_address));
00453         if (i == -1) {
00454                 perror("sendto():");
00455                 exit(1);
00456         }
00457 }
00458 
00459 int llsend(char * f, int size) {
00460         llpsend(f, size, WMP_TYPE_FIELD);
00461 }
00462 
00463 
00464 char getSimulatedRssiRX(char * f){
00465         wmpFrame * p = (wmpFrame *) f;
00466         char from = p->hdr.from;
00467         char myself = wmpGetNodeId();
00468         if (from == 0){
00469                 if (myself == 1) return 50;
00470                 if (myself == 2) return 80;
00471         }
00472         if (from == 1){
00473                 if (myself == 0) return 50;
00474                 if (myself == 2) return 25;
00475         }
00476         if (from == 2){
00477                 if (myself == 0) return 80;
00478                 if (myself == 1) return 25;
00479         }
00480         return 80;
00481 }
00482 
00483 
00484 rxInfo llreceive(char *f, int timeout) {
00485         int r = 0;
00486         rxInfo ret;
00487         struct timeval tv;
00488         if (!use_lo && use_mon) {
00489                 return pcap_sniff_packet(f, timeout);
00490         } else {
00491                 if (timeout > 0) {
00492                         fd_set fd_rx;
00493                         tv.tv_sec = 0;
00494                         tv.tv_usec = 1000 * timeout;
00495                         FD_ZERO(&fd_rx);
00496                         FD_SET(s, &fd_rx);
00497                         r = select(FD_SETSIZE, &fd_rx, NULL, NULL, &tv);
00498                 } else {
00499                         r = 1;
00500                 }
00501                 if (r) {
00502                         int rlen = recvfrom(s, buffer, MTU, 0, 0, 0);
00503                         ret.proto = ntohs(eh->h_proto);
00504                         memcpy(f, buffer + ETHER_HDR_LEN, rlen - ETHER_HDR_LEN);
00505                         ret.size = rlen - ETHER_HDR_LEN;
00506                         ret.error = 0;
00507                         ret.rate = 10;
00508                         ret.has_lq = 0;
00509                         //ret.rssi = getSimulatedRssiRX(f);
00510                         return ret;
00511                 } else {
00512                         ret.error = 1;
00513                         return ret;
00514                 }
00515         }
00516 }
00517 
00518 


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Mon Oct 6 2014 08:27:10