Owl Positioning System: a Wi-Fi-based, infrastructure-centred indoor positioning system. http://owlps.pu-pm.univ-fcomte.fr/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

owlps-listenerd.c 61KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961
  1. /*
  2. * This file is part of the Owl Positioning System (OwlPS) project.
  3. * It is subject to the copyright notice and license terms in the
  4. * COPYRIGHT.t2t file found in the top-level directory of this
  5. * distribution and at
  6. * https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t
  7. * No part of the OwlPS Project, including this file, may be copied,
  8. * modified, propagated, or distributed except according to the terms
  9. * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
  10. * distributed along with this file, either separately or by replacing
  11. * this notice by the COPYRIGHT.t2t file's contents.
  12. *
  13. ***********************************************************************
  14. *
  15. * This is the main source file of OwlPS Listener, the program that
  16. * captures the requests sent by the mobile terminals and forwards them
  17. * to the Aggregator.
  18. */
  19. #include "owlps-listener.h"
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <inttypes.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <signal.h>
  26. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  27. # include <confuse.h>
  28. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  29. #ifdef OWLPS_LISTENER_USES_PTHREAD
  30. # include <pthread.h>
  31. #endif // OWLPS_LISTENER_USES_PTHREAD
  32. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  33. # include <iwlib.h>
  34. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  35. #include <sys/ioctl.h>
  36. #include <net/if.h>
  37. #include <netinet/if_ether.h>
  38. #define __FAVOR_BSD
  39. #include <netinet/udp.h>
  40. #include <netinet/in_systm.h> // for n_time on BSD (used in ip.h)
  41. #include <netinet/ip.h>
  42. #include <arpa/inet.h>
  43. #ifndef __GLIBC__
  44. # include <sys/sysctl.h>
  45. # include <net/if_dl.h>
  46. #endif // __GLIBC__
  47. #include <assert.h>
  48. char *program_name = NULL ;
  49. uint8_t my_mac_bytes[ETHER_ADDR_LEN] ; // CP MAC address
  50. char my_ip[INET_ADDRSTRLEN] ; // CP IP address
  51. /* Will we dump the configuration?
  52. * Note that we declare this option as a global variable because
  53. * it must not appear in Confuse's options (to avoid dumping the
  54. * dump_configuration option itself).
  55. */
  56. bool dump_configuration = false ;
  57. pcap_t *capture_handler = NULL ; // Packet capture descriptor
  58. int aggregation_sockfd ;
  59. struct sockaddr aggregation_server ;
  60. #ifdef OWLPS_LISTENER_USES_PTHREAD
  61. int autocalibration_send_sockfd ;
  62. struct sockaddr autocalibration_send_server ;
  63. // true if the coordinates of the listener were provided by the user:
  64. bool coordinates_provided = false ;
  65. #endif // OWLPS_LISTENER_USES_PTHREAD
  66. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  67. cfg_t *cfg = NULL ; // Configuration structure
  68. #else // OWLPS_LISTENER_USES_CONFIG_FILE
  69. /* If we do not use libconfuse, we declare a structure to store getopt
  70. * options.
  71. */
  72. // TODO: the size of this structure could be reduced by reordering its fields.
  73. // Note: the alignment comments below are for the case where all the #ifdef
  74. // match.
  75. struct {
  76. bool daemon ;
  77. char mode ;
  78. char aggregation_host[MAXHOSTNAMELEN] ;
  79. // 6 bytes alignment
  80. uint_fast16_t aggregation_port ;
  81. uint_fast16_t listening_port ;
  82. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  83. bool keep_monitor ;
  84. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  85. char rtap_iface[IFNAMSIZ + 1] ;
  86. // 7 bytes alignment
  87. char *pcap_file ;
  88. char wifi_iface[IFNAMSIZ + 1] ;
  89. #ifdef OWLPS_LISTENER_USES_PTHREAD
  90. bool autocalibration ;
  91. char autocalibration_host[MAXHOSTNAMELEN] ;
  92. // 6 bytes alignment
  93. uint_fast16_t autocalibration_request_port ;
  94. uint_fast16_t autocalibration_order_port ;
  95. uint_fast16_t autocalibration_hello_port ;
  96. uint_fast32_t autocalibration_hello_delay ;
  97. uint_fast32_t autocalibration_delay ;
  98. uint_fast16_t autocalibration_nb_packets ;
  99. owl_direction my_direction ;
  100. // 3 bytes alignment
  101. float my_position_x ;
  102. float my_position_y ;
  103. float my_position_z ;
  104. #endif // OWLPS_LISTENER_USES_PTHREAD
  105. uint_fast8_t verbose ;
  106. // 7 bytes alignment
  107. } options = { // Initalise default options:
  108. false, // daemon
  109. MODE_ACTIVE, // mode
  110. DEFAULT_AGGREGATION_HOST, // aggregation_host
  111. OWL_DEFAULT_LISTENER_PORT, // aggregation_port
  112. OWL_DEFAULT_REQUEST_PORT, // listening_port
  113. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  114. false, // keep_monitor
  115. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  116. "", // rtap_iface
  117. NULL, // pcap_file
  118. "", // wifi_iface
  119. #ifdef OWLPS_LISTENER_USES_PTHREAD
  120. false, // autocalibration
  121. "", // autocalibration_host
  122. 0, // autocalibration_request_port
  123. OWL_DEFAULT_AUTOCALIBRATION_ORDER_PORT, // autocalibration_order_port
  124. OWL_DEFAULT_AUTOCALIBRATION_HELLO_PORT, // autocalibration_hello_port
  125. DEFAULT_AUTOCALIBRATION_HELLO_DELAY, // autocalibration_hello_delay
  126. DEFAULT_AUTOCALIBRATION_DELAY, // autocalibration_delay
  127. DEFAULT_AUTOCALIBRATION_NBPKT, // autocalibration_nb_packets
  128. 0, 0, 0, 0, // Calibration data
  129. #endif // OWLPS_LISTENER_USES_PTHREAD
  130. 0 // verbose
  131. } ;
  132. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  133. int main(int argc, char *argv[])
  134. {
  135. struct sigaction action ; // Signal handler structure
  136. int ret ; // Program return value
  137. #ifdef OWLPS_LISTENER_USES_PTHREAD
  138. pthread_t
  139. autocalibration_thread,
  140. autocalibration_hello_thread ;
  141. #endif // OWLPS_LISTENER_USES_PTHREAD
  142. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  143. pthread_t keep_monitor_thread ;
  144. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  145. owl_run = true ;
  146. program_name = argv[0] ;
  147. ret = initialise_configuration(argc, argv) ;
  148. if (! owl_run)
  149. goto exit ;
  150. if (GET_DAEMON())
  151. {
  152. if (VERBOSE_WARNING)
  153. fprintf(stderr, "Detaching to background...\n") ;
  154. if (daemon(0, 0))
  155. perror("Cannot daemonize") ;
  156. }
  157. /* Set up signal handlers */
  158. action.sa_flags = 0 ;
  159. sigemptyset(&action.sa_mask) ;
  160. action.sa_handler = sigint_handler ;
  161. sigaction(SIGINT, &action, NULL) ;
  162. action.sa_handler = sigterm_handler ;
  163. sigaction(SIGTERM, &action, NULL) ;
  164. if (LIVE_CAPTURING)
  165. {
  166. get_mac_addr(GET_WIFI_IFACE(), my_mac_bytes) ;
  167. get_ip_addr(GET_WIFI_IFACE(), my_ip) ;
  168. if (VERBOSE_INFO)
  169. printf("My MAC address is: %s\n"
  170. "My IP address is: %s\n",
  171. owl_mac_bytes_to_string(my_mac_bytes),
  172. my_ip) ;
  173. }
  174. #ifdef OWLPS_LISTENER_USES_PTHREAD
  175. /* Set up threads */
  176. # ifdef OWLPS_LISTENER_KEEPS_MONITOR
  177. if (GET_KEEP_MONITOR())
  178. {
  179. ret = pthread_create(&keep_monitor_thread, NULL,
  180. &keep_mode_monitor, GET_WIFI_IFACE()) ;
  181. if (ret != 0)
  182. {
  183. perror("Cannot create keep monitor thread") ;
  184. ret = OWL_ERR_THREAD_CREATE ;
  185. goto exit ;
  186. }
  187. }
  188. # endif // OWLPS_LISTENER_KEEPS_MONITOR
  189. if (GET_AUTOCALIBRATION())
  190. {
  191. ret = pthread_create(&autocalibration_thread, NULL,
  192. &autocalibrate, NULL) ;
  193. if (ret != 0)
  194. {
  195. perror("Cannot create autocalibration thread") ;
  196. ret = OWL_ERR_THREAD_CREATE ;
  197. goto exit ;
  198. }
  199. ret = pthread_create(&autocalibration_hello_thread, NULL,
  200. &autocalibrate_hello, NULL) ;
  201. if (ret != 0)
  202. {
  203. perror("Cannot create autocalibration hello thread") ;
  204. ret = OWL_ERR_THREAD_CREATE ;
  205. goto exit ;
  206. }
  207. }
  208. #endif // OWLPS_LISTENER_USES_PTHREAD
  209. ret = capture() ; // Capture loop
  210. /* Wait for the threads to terminate */
  211. #ifdef OWLPS_LISTENER_USES_PTHREAD
  212. # ifdef OWLPS_LISTENER_KEEPS_MONITOR
  213. if (GET_KEEP_MONITOR())
  214. {
  215. if (VERBOSE_WARNING)
  216. fprintf(stderr,
  217. "Waiting for the keep mode monitor thread...\n") ;
  218. if (pthread_join(keep_monitor_thread, NULL) != 0)
  219. perror("Cannot join keep mode monitor thread") ;
  220. else if (VERBOSE_WARNING)
  221. fprintf(stderr, "Keep monitor thread done.\n") ;
  222. }
  223. # endif // OWLPS_LISTENER_KEEPS_MONITOR
  224. if (GET_AUTOCALIBRATION())
  225. {
  226. // We must cancel this thread because it can be blocked on the
  227. // recvfrom() call:
  228. if (VERBOSE_WARNING)
  229. fprintf(stderr, "Cancelling the autocalibration thread...\n") ;
  230. if (pthread_cancel(autocalibration_thread) != 0)
  231. perror("Cannot cancel autocalibration thread") ;
  232. else if (VERBOSE_WARNING)
  233. fprintf(stderr, "Autocalibration thread cancelled.\n") ;
  234. if (VERBOSE_WARNING)
  235. fprintf(stderr, "Waiting for the autocalibration thread...\n") ;
  236. if (pthread_join(autocalibration_thread, NULL) != 0)
  237. perror("Cannot join autocalibration thread") ;
  238. else if (VERBOSE_WARNING)
  239. fprintf(stderr, "Autocalibration thread done.\n") ;
  240. // We must cancel this thread if we do not want to wait
  241. // autocalibration_hello_delay seconds (in the worst case):
  242. if (VERBOSE_WARNING)
  243. fprintf(stderr,
  244. "Cancelling the autocalibration hello thread...\n") ;
  245. if (pthread_cancel(autocalibration_hello_thread) != 0)
  246. perror("Cannot cancel autocalibration hello thread") ;
  247. else if (VERBOSE_WARNING)
  248. fprintf(stderr, "Autocalibration hello thread cancelled.\n") ;
  249. if (VERBOSE_WARNING)
  250. fprintf(stderr,
  251. "Waiting for the autocalibration hello thread...\n") ;
  252. if (pthread_join(autocalibration_hello_thread, NULL) != 0)
  253. perror("Cannot join autocalibration hello thread") ;
  254. else if (VERBOSE_WARNING)
  255. fprintf(stderr, "Autocalibration hello thread done.\n") ;
  256. }
  257. #else // OWLPS_LISTENER_USES_PTHREAD
  258. // Just to avoid a warning when compiling without threads' support:
  259. goto exit ;
  260. #endif // OWLPS_LISTENER_USES_PTHREAD
  261. /* Last cleaning tasks */
  262. exit:
  263. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  264. /* If called with -h, cfg won't be initialised, so we must check if
  265. * cfg is NULL */
  266. if (cfg && VERBOSE_CHATTERBOX)
  267. #else // OWLPS_LISTENER_USES_CONFIG_FILE
  268. if (VERBOSE_CHATTERBOX)
  269. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  270. fprintf(stderr, "%s: exiting.\n", program_name) ;
  271. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  272. cfg_free(cfg) ; // Clean configuration
  273. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  274. return ret ;
  275. }
  276. /*
  277. * Read the configuration from both the command line and the
  278. * configuration file.
  279. * Returns an error code, or 0 in case of success. If the program should
  280. * stop (because of a special option or a configuration error), owl_run
  281. * is set to false.
  282. */
  283. int initialise_configuration(const int argc, char *const *argv)
  284. {
  285. int ret ;
  286. ret = parse_config_file(argc, argv) ;
  287. if (! owl_run)
  288. return ret ;
  289. ret = parse_command_line(argc, argv) ;
  290. if (! owl_run)
  291. return ret ;
  292. ret = check_configuration() ;
  293. if (! owl_run)
  294. return ret ;
  295. /* Configuration dumping */
  296. if (dump_configuration)
  297. {
  298. print_configuration(stdout) ;
  299. owl_run = false ;
  300. return 0 ;
  301. }
  302. /* Configuration printing */
  303. if (VERBOSE_INFO)
  304. {
  305. fprintf(stderr, "Configuration:\n") ;
  306. print_configuration(stderr) ;
  307. }
  308. return 0 ;
  309. }
  310. int parse_config_file(const int argc, char *const *argv)
  311. {
  312. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  313. // If we use libconfuse, we declare options:
  314. cfg_opt_t opts[] =
  315. {
  316. // Daemon mode:
  317. CFG_BOOL("daemon", cfg_false, CFGF_NONE),
  318. // Listening mode: a for active, p for passive, m for mixed
  319. // (default: a):
  320. CFG_INT("mode", MODE_ACTIVE, CFGF_NONE),
  321. // Aggregation server host (default: loopback):
  322. CFG_STR("aggregation_host", DEFAULT_AGGREGATION_HOST, CFGF_NONE),
  323. // Port on which the aggregator listens:
  324. CFG_INT("aggregation_port", OWL_DEFAULT_LISTENER_PORT, CFGF_NONE),
  325. // Port to which mobiles send active requests:
  326. CFG_INT("listening_port", OWL_DEFAULT_REQUEST_PORT, CFGF_NONE),
  327. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  328. // Activate the active monitor mode keeping-up (read the code if
  329. // you do not understand what I mean):
  330. CFG_BOOL("keep_monitor", cfg_false, CFGF_NONE),
  331. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  332. // Radiotap interface to capture from:
  333. CFG_STR("rtap_iface", "", CFGF_NONE),
  334. // Pcap file to read packets from:
  335. CFG_STR("pcap_file", "", CFGF_NONE),
  336. // Physical interface corresponding to the radiotap interface (used
  337. // to get the MAC address):
  338. CFG_STR("wifi_iface", "", CFGF_NONE),
  339. #ifdef OWLPS_LISTENER_USES_PTHREAD
  340. // Autocalibration activated?
  341. CFG_BOOL("autocalibration", cfg_false, CFGF_NONE),
  342. // Destination host of the autocalibration requests (default:
  343. // none, but will be set to aggregation_ip in the config check):
  344. CFG_STR("autocalibration_host", "", CFGF_NONE),
  345. // Port to which autocalibration requests are sent (default: 0,
  346. // but will be set to listening_port in the config check):
  347. CFG_INT("autocalibration_request_port", 0, CFGF_NONE),
  348. // Port on which autocalibration orders are received:
  349. CFG_INT("autocalibration_order_port",
  350. OWL_DEFAULT_AUTOCALIBRATION_ORDER_PORT, CFGF_NONE),
  351. // Port to which autocalibration hello are sent:
  352. CFG_INT("autocalibration_hello_port",
  353. OWL_DEFAULT_AUTOCALIBRATION_HELLO_PORT, CFGF_NONE),
  354. // Delay between two hello messages:
  355. CFG_INT("autocalibration_hello_delay",
  356. DEFAULT_AUTOCALIBRATION_HELLO_DELAY,
  357. CFGF_NONE),
  358. // Delay between two calibration packet transmission:
  359. CFG_INT("autocalibration_delay", DEFAULT_AUTOCALIBRATION_DELAY,
  360. CFGF_NONE),
  361. // Number of packets for a calibration request:
  362. CFG_INT("autocalibration_nb_packets",
  363. DEFAULT_AUTOCALIBRATION_NBPKT, CFGF_NONE),
  364. // Direction
  365. CFG_INT("my_direction", 0, CFGF_NONE),
  366. // Position X
  367. CFG_FLOAT("my_position_x", 0, CFGF_NONE),
  368. // Position Y
  369. CFG_FLOAT("my_position_y", 0, CFGF_NONE),
  370. // Position Z
  371. CFG_FLOAT("my_position_z", 0, CFGF_NONE),
  372. #endif // OWLPS_LISTENER_USES_PTHREAD
  373. // Verbose level:
  374. CFG_INT("verbose", 0, CFGF_NONE),
  375. CFG_END()
  376. } ;
  377. // Configuration file name
  378. char *config_file = NULL ;
  379. // True if we are using the default configuration file, false if the
  380. // user specified a different one with -f
  381. bool default_config_file = false ;
  382. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  383. // Option -f specifies a config file, options -h and -V exit the
  384. // program, so we search for them first
  385. int opt ;
  386. while ((opt = getopt(argc, argv, OPTIONS)) != -1)
  387. {
  388. switch (opt)
  389. {
  390. case 'f' :
  391. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  392. config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ;
  393. if (! config_file)
  394. {
  395. perror("Cannot allocate memory") ;
  396. owl_run = false ;
  397. return errno ;
  398. }
  399. strcpy(config_file, optarg) ;
  400. #else // OWLPS_LISTENER_USES_CONFIG_FILE
  401. fprintf(stderr, "Warning! Program was not compiled with"
  402. " configuration file support, so -f is not available."
  403. " You must specify all options on the command line,"
  404. " or default value will be used.\n") ;
  405. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  406. break ;
  407. case 'h' :
  408. print_usage() ;
  409. owl_run = false ;
  410. return EXIT_SUCCESS ;
  411. case 'V' :
  412. print_version() ;
  413. owl_run = false ;
  414. return EXIT_SUCCESS ;
  415. }
  416. }
  417. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  418. // If -f isn't found, we use the default config file
  419. if (config_file == NULL)
  420. {
  421. default_config_file = true ;
  422. config_file =
  423. malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ;
  424. if (! config_file)
  425. {
  426. perror("Cannot allocate memory") ;
  427. owl_run = false ;
  428. return errno ;
  429. }
  430. strcpy(config_file, DEFAULT_CONFIG_FILE) ;
  431. }
  432. /* Parse config file */
  433. cfg = cfg_init(opts, CFGF_NONE) ; // Initialise options
  434. switch (cfg_parse(cfg, config_file))
  435. {
  436. case CFG_FILE_ERROR :
  437. /* If we can't open the file, we display a message only if
  438. * the user used -f. In verbose mode, it would be nice to
  439. * display the message even if the user didn't use -f, but
  440. * the command-line options are not parsed yet so the verbose
  441. * level is always zero. */
  442. if (! default_config_file)
  443. fprintf(stderr,
  444. "Warning! Cannot open configuration file \"%s\": %s.\n",
  445. config_file, strerror(errno)) ;
  446. break ;
  447. case CFG_PARSE_ERROR :
  448. fprintf(stderr,
  449. "Error! Parsing of configuration file \"%s\" failed!\n",
  450. config_file) ;
  451. free(config_file) ;
  452. owl_run = false ;
  453. return OWL_ERR_CONFIG_FILE ;
  454. }
  455. free(config_file) ;
  456. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  457. return 0 ;
  458. }
  459. int parse_command_line(const int argc, char *const *argv)
  460. {
  461. int ret ;
  462. ret = parse_main_options(argc, argv) ;
  463. if (! owl_run)
  464. return ret ;
  465. #ifdef OWLPS_LISTENER_USES_PTHREAD
  466. ret = parse_calibration_data(argc, argv) ;
  467. if (! owl_run)
  468. return ret ;
  469. #endif // OWLPS_LISTENER_USES_PTHREAD
  470. return 0 ;
  471. }
  472. int parse_main_options(const int argc, char *const *argv)
  473. {
  474. int opt ;
  475. long arg_long ; // Integer value of optarg
  476. char *endptr ; // Return value of strtol()
  477. optind = 1 ; // Rewind argument parsing
  478. while ((opt = getopt(argc, argv, OPTIONS)) != -1)
  479. {
  480. switch (opt)
  481. {
  482. case 'A' :
  483. #ifdef OWLPS_LISTENER_USES_PTHREAD
  484. SET_AUTOCALIBRATION() ;
  485. #else // OWLPS_LISTENER_USES_PTHREAD
  486. fprintf(stderr, "Warning! The program was compiled without"
  487. " support of POSIX threads, so -A (autocalibration)"
  488. " is not available and will be ignored. All other"
  489. " autocalibration-related options will also be"
  490. " ignored.\n") ;
  491. #endif // OWLPS_LISTENER_USES_PTHREAD
  492. break ;
  493. case 'D' :
  494. SET_DAEMON() ;
  495. break ;
  496. case 'f' : // Config file
  497. break ; // (already parsed)
  498. case 'G' :
  499. dump_configuration = true ;
  500. /* We must not turn owl_run false here, to avoid the default
  501. * check on its value in initialise_configuration(). */
  502. break ;
  503. case 'H' :
  504. #ifdef OWLPS_LISTENER_USES_PTHREAD
  505. SET_AUTOCALIBRATION_HELLO_PORT(strtol(optarg, NULL, 10)) ;
  506. #endif // OWLPS_LISTENER_USES_PTHREAD
  507. break ;
  508. case 'i' :
  509. SET_AGGREGATION_HOST(optarg) ;
  510. break ;
  511. case 'I' :
  512. #ifdef OWLPS_LISTENER_USES_PTHREAD
  513. SET_AUTOCALIBRATION_HOST(optarg) ;
  514. #endif // OWLPS_LISTENER_USES_PTHREAD
  515. break ;
  516. case 'K' :
  517. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  518. SET_KEEP_MONITOR() ;
  519. #else // OWLPS_LISTENER_KEEPS_MONITOR
  520. fprintf(stderr, "Warning! The program was compiled without"
  521. " enabling the -K option (monitor mode keeping-up)."
  522. "\n") ;
  523. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  524. break ;
  525. case 'l' :
  526. SET_LISTENING_PORT(strtol(optarg, NULL, 10)) ;
  527. break ;
  528. case 'm' :
  529. SET_MODE(optarg[0]) ;
  530. break ;
  531. case 'n' :
  532. #ifdef OWLPS_LISTENER_USES_PTHREAD
  533. SET_AUTOCALIBRATION_NBPKT(strtol(optarg, NULL, 10)) ;
  534. #endif // OWLPS_LISTENER_USES_PTHREAD
  535. break ;
  536. case 'O' :
  537. #ifdef OWLPS_LISTENER_USES_PTHREAD
  538. SET_AUTOCALIBRATION_ORDER_PORT(strtol(optarg, NULL, 10)) ;
  539. #endif // OWLPS_LISTENER_USES_PTHREAD
  540. break ;
  541. case 'p' :
  542. SET_AGGREGATION_PORT(strtol(optarg, NULL, 10)) ;
  543. break ;
  544. case 'P' :
  545. #ifdef OWLPS_LISTENER_USES_PTHREAD
  546. SET_AUTOCALIBRATION_REQUEST_PORT(strtol(optarg, NULL, 10)) ;
  547. #endif // OWLPS_LISTENER_USES_PTHREAD
  548. break ;
  549. case 'q' :
  550. RESET_VERBOSE() ;
  551. break ;
  552. case 'r' :
  553. SET_RTAP_IFACE(optarg) ;
  554. break ;
  555. case 'R' :
  556. SET_PCAP_FILE(optarg) ;
  557. break ;
  558. case 't' :
  559. #ifdef OWLPS_LISTENER_USES_PTHREAD
  560. arg_long = strtol(optarg, &endptr, 10) ;
  561. if (endptr != optarg)
  562. SET_AUTOCALIBRATION_DELAY(arg_long) ;
  563. else
  564. fprintf(stderr, "Warning! Bad autocalibration_delay:"
  565. " failing back to the default value.\n") ;
  566. #endif // OWLPS_LISTENER_USES_PTHREAD
  567. break ;
  568. case 'T' :
  569. #ifdef OWLPS_LISTENER_USES_PTHREAD
  570. arg_long = strtol(optarg, &endptr, 10) ;
  571. if (endptr != optarg)
  572. SET_AUTOCALIBRATION_HELLO_DELAY(arg_long) ;
  573. else
  574. fprintf(stderr, "Warning! Bad autocalibration_hello_delay:"
  575. " failing back to the default value.\n") ;
  576. #endif // OWLPS_LISTENER_USES_PTHREAD
  577. break ;
  578. case 'v' :
  579. INCREMENT_VERBOSE() ;
  580. break ;
  581. case 'w' :
  582. SET_WIFI_IFACE(optarg) ;
  583. break ;
  584. default :
  585. print_usage() ;
  586. owl_run = false ;
  587. return OWL_ERR_BAD_USAGE ;
  588. }
  589. }
  590. return 0 ;
  591. }
  592. #ifdef OWLPS_LISTENER_USES_PTHREAD
  593. /* Parses remaining arguments (possible calibration data) */
  594. int parse_calibration_data(const int argc, char *const *argv)
  595. {
  596. /* No more arguments to parse */
  597. if (argc - optind == 0)
  598. return 0 ;
  599. /* Exactly 4 more arguments */
  600. if (argc - optind == 4)
  601. {
  602. char *endptr ;
  603. unsigned long arg_ulong ;
  604. double arg_double ;
  605. coordinates_provided = true ;
  606. arg_ulong = strtoul(argv[optind], &endptr, 10) ;
  607. if (endptr == argv[optind])
  608. {
  609. fprintf(stderr,
  610. "Error in calibration data: wrong direction!\n") ;
  611. goto error ;
  612. }
  613. SET_MY_DIRECTION(arg_ulong) ;
  614. optind++ ;
  615. arg_double = strtod(argv[optind], &endptr) ;
  616. if (endptr == argv[optind])
  617. {
  618. fprintf(stderr,
  619. "Error in calibration data: wrong X coordinate!\n") ;
  620. goto error ;
  621. }
  622. SET_MY_POSITION_X(arg_double) ;
  623. optind++ ;
  624. arg_double = strtod(argv[optind], &endptr) ;
  625. if (endptr == argv[optind])
  626. {
  627. fprintf(stderr,
  628. "Error in calibration data: wrong Y coordinate!\n") ;
  629. goto error ;
  630. }
  631. SET_MY_POSITION_Y(arg_double) ;
  632. optind++ ;
  633. arg_double = strtod(argv[optind], &endptr) ;
  634. if (endptr == argv[optind])
  635. {
  636. fprintf(stderr,
  637. "Error in calibration data: wrong Z coordinate!\n") ;
  638. goto error ;
  639. }
  640. SET_MY_POSITION_Z(arg_double) ;
  641. return 0 ; // No error occurred
  642. }
  643. /* Bad number of arguments or parse error */
  644. error:
  645. print_usage() ;
  646. owl_run = false ;
  647. return OWL_ERR_BAD_USAGE ;
  648. }
  649. #endif // OWLPS_LISTENER_USES_PTHREAD
  650. int check_configuration()
  651. {
  652. // Capture mode //
  653. switch (GET_MODE())
  654. {
  655. case MODE_ACTIVE :
  656. case MODE_MIXED :
  657. case MODE_PASSIVE :
  658. break ;
  659. default :
  660. fprintf(stderr, "Error! Unknown mode \"%c\".\n", (char) GET_MODE()) ;
  661. print_usage() ;
  662. owl_run = false ;
  663. return OWL_ERR_BAD_USAGE ;
  664. }
  665. // Packet source //
  666. if (GET_PCAP_FILE() && GET_PCAP_FILE()[0] != '\0')
  667. {
  668. if (GET_RTAP_IFACE()[0] != '\0')
  669. {
  670. if (VERBOSE_WARNING)
  671. fprintf(stderr, "Warning! Cannot read both from a pcap file"
  672. " and a capture interface: ignoring network-related"
  673. " options.\n") ;
  674. GET_RTAP_IFACE()[0] = '\0' ;
  675. }
  676. // Ignoring the Wi-Fi interface too:
  677. GET_WIFI_IFACE()[0] = '\0' ;
  678. #ifdef OWLPS_LISTENER_USES_PTHREAD
  679. if (GET_AUTOCALIBRATION())
  680. {
  681. if (VERBOSE_WARNING)
  682. fprintf(stderr, "Warning! Cannot send autocalibration"
  683. " requests when reading from a pcap file: disabling"
  684. " autocalibration.\n") ;
  685. UNSET_AUTOCALIBRATION() ;
  686. }
  687. # ifdef OWLPS_LISTENER_KEEPS_MONITOR
  688. UNSET_KEEP_MONITOR() ;
  689. # endif // OWLPS_LISTENER_KEEPS_MONITOR
  690. #endif // OWLPS_LISTENER_USES_PTHREAD
  691. if (GET_DAEMON())
  692. {
  693. if (VERBOSE_WARNING)
  694. fprintf(stderr, "Warning! Reading from a pcap file: will"
  695. " stay in foreground.\n") ;
  696. UNSET_DAEMON() ;
  697. }
  698. }
  699. // pcap_file is empty
  700. else if (GET_RTAP_IFACE()[0] == '\0')
  701. {
  702. fprintf(stderr, "Error! You must specify either a radiotap"
  703. " interface or a pcap file to read packets from.\n") ;
  704. print_usage() ;
  705. owl_run = false ;
  706. return OWL_ERR_BAD_USAGE ;
  707. }
  708. else if (GET_WIFI_IFACE()[0] == '\0')
  709. {
  710. if (VERBOSE_WARNING)
  711. fprintf(stderr, "No Wi-Fi interface was specified. Failing back"
  712. " to the radiotap interface (%s) instead.\n",
  713. GET_RTAP_IFACE()) ;
  714. SET_WIFI_IFACE(GET_RTAP_IFACE()) ;
  715. }
  716. // Port numbers //
  717. if (GET_AGGREGATION_PORT() < 1 || GET_AGGREGATION_PORT() > 65535)
  718. {
  719. if (VERBOSE_WARNING)
  720. fprintf(stderr, "Warning! Bad aggregation_port:"
  721. " failing back to the default value.\n") ;
  722. SET_AGGREGATION_PORT(OWL_DEFAULT_LISTENER_PORT) ;
  723. }
  724. if (GET_LISTENING_PORT() < 1 || GET_LISTENING_PORT() > 65535)
  725. {
  726. if (VERBOSE_WARNING)
  727. fprintf(stderr, "Warning! Bad listening_port:"
  728. " failing back to the default value.\n") ;
  729. SET_LISTENING_PORT(OWL_DEFAULT_REQUEST_PORT) ;
  730. }
  731. // Autocalibration stuff //
  732. #ifdef OWLPS_LISTENER_USES_PTHREAD
  733. if (GET_AUTOCALIBRATION())
  734. {
  735. if (GET_AUTOCALIBRATION_HOST()[0] == '\0')
  736. {
  737. if (VERBOSE_WARNING)
  738. fprintf(stderr, "No autocalibration host specified, the"
  739. " aggregation host will be used as the destination"
  740. " of autocalibration requests.\n") ;
  741. SET_AUTOCALIBRATION_HOST(GET_AGGREGATION_HOST()) ;
  742. }
  743. if (GET_AUTOCALIBRATION_NBPKT() < 1)
  744. fprintf(stderr, "Warning! autocalibration_nb_packets is zero,"
  745. " no autocalibration request will be sent!\n") ;
  746. if (coordinates_provided)
  747. if (GET_MY_DIRECTION() < OWL_DIRECTION_MIN ||
  748. GET_MY_DIRECTION() > OWL_DIRECTION_MAX)
  749. fprintf(stderr, "Warning! \"%d\" is not a valid"
  750. " direction.\n", (int) GET_MY_DIRECTION()) ;
  751. // Autocalibration port numbers
  752. if (GET_AUTOCALIBRATION_REQUEST_PORT() > 65535 && VERBOSE_WARNING)
  753. fprintf(stderr, "Warning! Bad autocalibration_request_port:"
  754. " failing back to the default value.\n") ;
  755. if (GET_AUTOCALIBRATION_REQUEST_PORT() < 1 ||
  756. GET_AUTOCALIBRATION_REQUEST_PORT() > 65535)
  757. SET_AUTOCALIBRATION_REQUEST_PORT(GET_LISTENING_PORT()) ;
  758. if (GET_AUTOCALIBRATION_ORDER_PORT() < 1 ||
  759. GET_AUTOCALIBRATION_ORDER_PORT() > 65535)
  760. {
  761. if (VERBOSE_WARNING)
  762. fprintf(stderr, "Warning! Bad autocalibration_order_port:"
  763. " failing back to the default value.\n") ;
  764. SET_AUTOCALIBRATION_ORDER_PORT(OWL_DEFAULT_AUTOCALIBRATION_ORDER_PORT) ;
  765. }
  766. if (GET_AUTOCALIBRATION_HELLO_PORT() < 1 ||
  767. GET_AUTOCALIBRATION_HELLO_PORT() > 65535)
  768. {
  769. if (VERBOSE_WARNING)
  770. fprintf(stderr, "Warning! Bad autocalibration_hello_port:"
  771. " failing back to the default value.\n") ;
  772. SET_AUTOCALIBRATION_HELLO_PORT(OWL_DEFAULT_AUTOCALIBRATION_HELLO_PORT) ;
  773. }
  774. }
  775. #endif // OWLPS_LISTENER_USES_PTHREAD
  776. return 0 ;
  777. }
  778. void print_configuration(FILE *const stream)
  779. {
  780. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  781. cfg_print(cfg, stream) ;
  782. #else // OWLPS_LISTENER_USES_CONFIG_FILE
  783. fprintf(stream,
  784. "mode = %c\n"
  785. "aggregation_host = \"%s\"\n"
  786. "aggregation_port = %"PRIuFAST16"\n"
  787. "listening_port = %"PRIuFAST16"\n"
  788. "rtap_iface = \"%s\"\n"
  789. "wifi_iface = \"%s\"\n"
  790. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  791. "keep_monitor = %s\n"
  792. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  793. #ifdef OWLPS_LISTENER_USES_PTHREAD
  794. "autocalibration = %s\n"
  795. "autocalibration_host = \"%s\"\n"
  796. "autocalibration_request_port = %"PRIuFAST16"\n"
  797. "autocalibration_order_port = %"PRIuFAST16"\n"
  798. "autocalibration_hello_port = %"PRIuFAST16"\n"
  799. "autocalibration_hello_delay = %"PRIuFAST32"\n"
  800. "autocalibration_delay = %"PRIuFAST32"\n"
  801. "autocalibration_nb_packets = %"PRIuFAST16"\n"
  802. "my_direction = %"PRIu8"\n"
  803. "my_position_x = %f\n"
  804. "my_position_y = %f\n"
  805. "my_position_z = %f\n"
  806. #endif // OWLPS_LISTENER_USES_PTHREAD
  807. "verbose = %"PRIuFAST8"\n"
  808. ,
  809. GET_MODE(),
  810. GET_AGGREGATION_HOST(),
  811. GET_AGGREGATION_PORT(),
  812. GET_LISTENING_PORT(),
  813. GET_RTAP_IFACE(),
  814. GET_WIFI_IFACE(),
  815. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  816. OWL_BOOL_TO_STRING(GET_KEEP_MONITOR()),
  817. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  818. #ifdef OWLPS_LISTENER_USES_PTHREAD
  819. OWL_BOOL_TO_STRING(GET_AUTOCALIBRATION()),
  820. GET_AUTOCALIBRATION_HOST(),
  821. GET_AUTOCALIBRATION_REQUEST_PORT(),
  822. GET_AUTOCALIBRATION_ORDER_PORT(),
  823. GET_AUTOCALIBRATION_HELLO_PORT(),
  824. GET_AUTOCALIBRATION_HELLO_DELAY(),
  825. GET_AUTOCALIBRATION_DELAY(),
  826. GET_AUTOCALIBRATION_NBPKT(),
  827. GET_MY_DIRECTION(),
  828. GET_MY_POSITION_X(),
  829. GET_MY_POSITION_Y(),
  830. GET_MY_POSITION_Z(),
  831. #endif // OWLPS_LISTENER_USES_PTHREAD
  832. GET_VERBOSE()
  833. ) ;
  834. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  835. }
  836. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  837. /*
  838. * Thread function. Switches interface 'iface' to monitor mode every
  839. * second. `iface` must be passed as a const char *const.
  840. */
  841. void* keep_mode_monitor(void *const iface)
  842. {
  843. if (VERBOSE_WARNING)
  844. fprintf(stderr, "Thread for keeping monitor mode launched.\n") ;
  845. while (owl_run)
  846. {
  847. // Switch the interface to monitor mode:
  848. iface_mode_monitor((char*) iface) ;
  849. sleep(1) ; // Wait for 1 second
  850. }
  851. pthread_exit(NULL) ;
  852. }
  853. /*
  854. * Switches the IEEE 802.11 interface 'iface' to Monitor mode.
  855. *
  856. * This function uses iwlib, which is Linux-specific. In case we want
  857. * this on BSD, there is some example code there:
  858. * http://www.unixgarden.com/index.php/gnu-linux-magazine-hs/introduction-a-la-programmation-wifi-en-c-sous-netbsd#7-exemple-n°4-activer-et-utiliser-le-monitoring-aka-rf_mon
  859. * The thing is that we would have to switch the interface down and up
  860. * each time, so let's hope we will never need that. But even on Linux,
  861. * this function was only needed with the buggy ipw2200 driver (for Intel
  862. * BG2200 chips) and it hopefully won't be needed any more.
  863. */
  864. int iface_mode_monitor(const char *const iface)
  865. {
  866. struct iwreq wrq ;
  867. int sockfd = iw_sockets_open() ;
  868. strncpy((&wrq)->ifr_name, iface, IFNAMSIZ) ;
  869. if (ioctl(sockfd, SIOCGIWMODE, &wrq) == -1) // Get current mode
  870. {
  871. perror("Error reading interface mode") ;
  872. return OWL_ERR_IFACE_MODE_GET ;
  873. }
  874. // If interface is not yet in Monitor mode
  875. if (wrq.u.mode != IW_MODE_MONITOR)
  876. {
  877. wrq.u.mode = IW_MODE_MONITOR ;
  878. if (ioctl(sockfd, SIOCSIWMODE, &wrq) == -1) // Set up Monitor mode
  879. {
  880. perror("Error setting up Monitor mode") ;
  881. return OWL_ERR_IFACE_MODE_SET ;
  882. }
  883. }
  884. close(sockfd) ;
  885. return 0 ;
  886. }
  887. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  888. /*
  889. * Captures packets using the radiotap interface.
  890. * Captured data is transmitted to the aggregator.
  891. */
  892. int capture()
  893. {
  894. char errbuf[PCAP_ERRBUF_SIZE] ; // Error message
  895. char *source ;
  896. struct pcap_pkthdr *pkt_header ;
  897. const u_char *pkt_data ;
  898. // Open the capture handler:
  899. if (LIVE_CAPTURING)
  900. {
  901. source = GET_RTAP_IFACE() ;
  902. capture_handler = pcap_open_live(source, BUFSIZ, 1, 1000, errbuf) ;
  903. }
  904. else
  905. {
  906. source = GET_PCAP_FILE() ;
  907. capture_handler = pcap_open_offline(source, errbuf) ;
  908. }
  909. if (capture_handler == NULL) // Capture starting failed
  910. {
  911. fprintf(stderr, "Cannot create capture handler on '%s': %s\n",
  912. source, errbuf) ;
  913. return OWL_ERR_IFACE_PCAP_OPEN ;
  914. }
  915. /* Open UDP socket to the aggregator */
  916. aggregation_sockfd =
  917. owl_create_trx_socket(GET_AGGREGATION_HOST(), GET_AGGREGATION_PORT(),
  918. &aggregation_server, NULL) ;
  919. while (owl_run)
  920. {
  921. // Capture one packet at time, and call read_packet() on it:
  922. int ret = pcap_next_ex(capture_handler, &pkt_header, &pkt_data) ;
  923. switch (ret)
  924. {
  925. case 1: // packet read successfuly
  926. read_packet(pkt_header, pkt_data) ;
  927. break ;
  928. case 0: // timeout reached
  929. break ;
  930. case -2: // no more packet to read from input file
  931. owl_run = false ;
  932. break ;
  933. case -1: // an error occured
  934. pcap_perror(capture_handler, "Error during capture") ;
  935. }
  936. }
  937. pcap_close(capture_handler) ; // Stop capture
  938. close(aggregation_sockfd) ; // Close socket
  939. return 0 ;
  940. }
  941. /*
  942. * Treats a packet and sends it to the aggregator.
  943. */
  944. void read_packet(const struct pcap_pkthdr *const pkt_header,
  945. const u_char *const pkt_data)
  946. {
  947. owl_captured_request request ; // Message to send to the aggregator
  948. uint16_t rtap_bytes ; // Radiotap header size
  949. uint_fast16_t offset ; // Offset to read the packet
  950. uint8_t raw_packet_fc1 ; // First byte of the received frame's FC
  951. uint8_t raw_packet_fc2 ; // Second byte of the received frame's FC
  952. // Size of the IEEE 802.11 header:
  953. uint_fast8_t ieee80211_header_size = IEEE80211_HEADER_SIZE_DATA ;
  954. uint16_t llc_packet_type = 0 ;
  955. // Pointer to the (possible) IP header of the packet:
  956. struct ip *packet_ip_header = NULL ;
  957. // Pointer to the (possible) UDP header of the packet:
  958. struct udphdr *packet_udp_header = NULL ;
  959. // Localisation request type (request, calibration, autocalibration):
  960. // Is the packet an explicit request?
  961. bool is_explicit_packet = true ;
  962. // Is the packet an autocalibration positioning request?
  963. bool uses_autocalibration_request_port = false ;
  964. ssize_t nsent ; // sendto return value
  965. // Blank the request:
  966. memset(&request, 0, sizeof(request)) ;
  967. /* Common treatements */
  968. // Copy 2 bytes from the 3rd packet byte, that is the size of the rtap
  969. // header (changes with the flags):
  970. offset = 2 ;
  971. memcpy(&rtap_bytes, &pkt_data[offset], sizeof(rtap_bytes)) ;
  972. // Radiotap header is little-endian
  973. rtap_bytes = le16toh(rtap_bytes) ;
  974. // Check rtap_bytes for buggy values
  975. if (rtap_bytes > 100)
  976. return ;
  977. // After the rtap header, there is the 802.11 header; the first byte
  978. // is the first byte of the Frame Control (FC) field, which contains
  979. // the type of the packet (Management, Control or Data) and its subtype
  980. // (QoS, etc.):
  981. offset = rtap_bytes ;
  982. raw_packet_fc1 = pkt_data[offset] ;
  983. // The second byte of the FC field contains the frame flags. The two
  984. // first bits indicate the frame source and destination types: the
  985. // first bit is "To DS" and the second is "From DS", so if the second
  986. // bit is 0 the frame comes from a STA. That's what we want for an
  987. // explicit packet:
  988. offset = rtap_bytes + 1 ;
  989. raw_packet_fc2 = pkt_data[offset] ;
  990. if (! IS_DATA_FRAME(raw_packet_fc1)) // Data frame?
  991. goto not_explicit_packet ;
  992. if (DATA_FRAME_IS_QOS(raw_packet_fc1)) // QoS Data frame?
  993. ieee80211_header_size += 2 ; // 2 bytes of QoS information
  994. if (! IS_FRAME_FROM_STA(raw_packet_fc2))
  995. goto not_explicit_packet ;
  996. // Get the packet type (protocol, 2 bytes) from the LLC header:
  997. offset = rtap_bytes + ieee80211_header_size + 6 ;
  998. memcpy(&llc_packet_type, &pkt_data[offset], 2) ;
  999. llc_packet_type = ntohs(llc_packet_type) ;
  1000. if (llc_packet_type != ETHERTYPE_IP) // IP packet?
  1001. goto not_explicit_packet ;
  1002. offset = rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE ;
  1003. packet_ip_header = (struct ip *) &pkt_data[offset] ;
  1004. // Get the source IP:
  1005. memcpy(request.mobile_ip_addr_bytes, &packet_ip_header->ip_src, 4) ;
  1006. if (GET_MODE() != MODE_PASSIVE) // If mode is active or mixed
  1007. {
  1008. uint_fast16_t dest_port ;
  1009. // Protocol for an explicit request is UDP
  1010. if (packet_ip_header->ip_p != IPPROTO_UDP)
  1011. goto not_explicit_packet ;
  1012. // Check destination port:
  1013. offset =
  1014. rtap_bytes + ieee80211_header_size +
  1015. LLC_HEADER_SIZE + sizeof(struct ip) ;
  1016. packet_udp_header = (struct udphdr *) &pkt_data[offset] ;
  1017. dest_port = ntohs(packet_udp_header->uh_dport) ;
  1018. #ifdef OWLPS_LISTENER_USES_PTHREAD
  1019. if (GET_AUTOCALIBRATION() && dest_port ==
  1020. (uint_fast16_t) GET_AUTOCALIBRATION_REQUEST_PORT())
  1021. uses_autocalibration_request_port = true ;
  1022. else
  1023. #endif // OWLPS_LISTENER_USES_PTHREAD
  1024. if (dest_port != (uint_fast16_t) GET_LISTENING_PORT())
  1025. goto not_explicit_packet ;
  1026. }
  1027. goto process_packet ;
  1028. not_explicit_packet :
  1029. if (GET_MODE() == MODE_ACTIVE)
  1030. return ;
  1031. is_explicit_packet = false ;
  1032. process_packet :
  1033. if (IS_RETRY(raw_packet_fc2) && VERBOSE_CHATTERBOX)
  1034. printf("This packet is a Retry.\n") ;
  1035. // Source MAC address is 10 bytes after the 802.11 packet type:
  1036. offset = rtap_bytes + 10 ;
  1037. memcpy(request.mobile_mac_addr_bytes, &pkt_data[offset],
  1038. ETHER_ADDR_LEN) ;
  1039. // Drop the packet if it comes from the CP itself:
  1040. if (owl_mac_equals(my_mac_bytes, request.mobile_mac_addr_bytes))
  1041. return ;
  1042. // Copy CP MAC :
  1043. memcpy(request.cp_mac_addr_bytes, my_mac_bytes, ETHER_ADDR_LEN) ;
  1044. // Capture time is in the pcap header (host-endian):
  1045. owl_timeval_to_timestamp(&pkt_header->ts, &request.capture_time) ;
  1046. /* Note on the line above: on OpenBSD, the ts field of struct
  1047. * pcap_pkthdr (defined in <pcap.h>) is a struct bpf_timeval* instead
  1048. * of a struct timeval*. struct bpf_timeval is defined in
  1049. * /usr/include/net/bpf.h and is a clone of struct timeval with
  1050. * fixed-size fields (u_int32_t). We *could* override the warning by
  1051. * casting, but I prefer to leave it as a reminder in case something
  1052. * went wrong at some point. */
  1053. owl_hton_timestamp(&request.capture_time) ;
  1054. /* Active mode */
  1055. if (is_explicit_packet
  1056. && (GET_MODE() == MODE_ACTIVE || GET_MODE() == MODE_MIXED)
  1057. // FIXME: should we really ignore Retries?
  1058. && ! IS_RETRY(raw_packet_fc2))
  1059. {
  1060. offset =
  1061. rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE +
  1062. sizeof(struct ip) + sizeof(struct udphdr) ;
  1063. request.type = pkt_data[offset] ;
  1064. extract_packet_numbers(&pkt_data[++offset], &request) ;
  1065. offset += 2 * sizeof(uint16_t) ;
  1066. // Copy the timestamp "as is" (i.e. without changing endianness)
  1067. // because it will return to the network soon:
  1068. memcpy(&request.request_time, &pkt_data[offset],
  1069. sizeof(owl_timestamp)) ;
  1070. offset += sizeof(owl_timestamp) ;
  1071. switch(request.type)
  1072. {
  1073. case OWL_REQUEST_NORMAL :
  1074. if (VERBOSE_INFO)
  1075. printf("\nExplicit packet received.\n") ;
  1076. break ;
  1077. case OWL_REQUEST_CALIBRATION :
  1078. if (VERBOSE_INFO)
  1079. printf("\nExplicit calibration packet received.\n") ;
  1080. extract_calibration_data(&pkt_data[offset], &request) ;
  1081. break ;
  1082. case OWL_REQUEST_AUTOCALIBRATION :
  1083. if (VERBOSE_INFO)
  1084. {
  1085. printf("\nAutocalibration packet received.") ;
  1086. if (! uses_autocalibration_request_port)
  1087. printf(".. on the wrong port!") ;
  1088. putchar('\n') ;
  1089. }
  1090. extract_calibration_data(&pkt_data[offset], &request) ;
  1091. break ;
  1092. default :
  1093. if (VERBOSE_INFO)
  1094. printf("\nStrange explicit packet received\n") ;
  1095. fprintf(stderr,
  1096. "Error! Unknown request type (%d).\n", request.type) ;
  1097. if (GET_MODE() == MODE_ACTIVE)
  1098. return ;
  1099. else
  1100. {
  1101. if (VERBOSE_INFO)
  1102. printf("\nThis strange explicit packet will be handled"
  1103. " as an implicit one.\n") ;
  1104. request.type = OWL_REQUEST_IMPLICIT ;
  1105. }
  1106. }
  1107. }
  1108. else if (GET_MODE() == MODE_PASSIVE || GET_MODE() == MODE_MIXED)
  1109. {
  1110. if (VERBOSE_CHATTERBOX)
  1111. printf("\nImplicit packet received.\n") ;
  1112. request.type = OWL_REQUEST_IMPLICIT ;
  1113. }
  1114. else // Active mode, packet was not an explicit request
  1115. return ;
  1116. /* Radiotap header handling */
  1117. if (! extract_radiotap_ss(pkt_data, &request))
  1118. fprintf(stderr, "Warning! The antenna signal field is absent from"
  1119. " the radiotap header!\n") ;
  1120. /* Display the packet details */
  1121. if (VERBOSE_DISPLAY_CAPTURED)
  1122. display_captured_request(&request, pkt_header) ;
  1123. /* Send the request to the aggregator */
  1124. nsent =
  1125. sendto(aggregation_sockfd, &request, sizeof(request), 0,
  1126. &aggregation_server, (socklen_t) sizeof(aggregation_server)) ;
  1127. if (nsent != (ssize_t) sizeof(request))
  1128. {
  1129. perror("Error sending request to the aggregation server") ;
  1130. return ;
  1131. }
  1132. }
  1133. /*
  1134. * Fills 'request' with the calibration data extracted from 'pkt_data'.
  1135. * Note: 'pkt_data' is read from its first byte, therefore you must not
  1136. * pass the whole received packet to this function.
  1137. */
  1138. void extract_calibration_data(const u_char *const pkt_data,
  1139. owl_captured_request *const request)
  1140. {
  1141. request->direction = pkt_data[0] ;
  1142. assert(sizeof(float) == 4) ;
  1143. memcpy(&request->x_position, &pkt_data[1], sizeof(float)) ;
  1144. memcpy(&request->y_position, &pkt_data[5], sizeof(float)) ;
  1145. memcpy(&request->z_position, &pkt_data[9], sizeof(float)) ;
  1146. }
  1147. /*
  1148. * Fills 'request' with the number of packets and packet ID extracted
  1149. * from 'pkt_data'.
  1150. * Note: 'pkt_data' is read from its first byte, therefore you must not
  1151. * pass the whole received packet to this function.
  1152. */
  1153. void extract_packet_numbers(const u_char *const pkt_data,
  1154. owl_captured_request *const request)
  1155. {
  1156. // Current packet's ID:
  1157. memcpy(&request->packet_id, pkt_data,
  1158. sizeof(uint16_t)) ;
  1159. request->packet_id = request->packet_id ;
  1160. // Number of packets:
  1161. memcpy(&request->nb_packets, &pkt_data[sizeof(uint16_t)],
  1162. sizeof(uint16_t)) ;
  1163. request->nb_packets = request->nb_packets ;
  1164. }
  1165. /*
  1166. * Fills 'request' with the signal strength extracted from the radiotap
  1167. * header of 'pkt_data'.
  1168. * Returns true if the antenna signal radiotap field was found, false
  1169. * otherwhise.
  1170. *
  1171. * Ideas of improvement:
  1172. * http://www.unixgarden.com/index.php/gnu-linux-magazine-hs/introduction-a-la-programmation-wifi-en-c-sous-netbsd#8-exemple-n°5-radiotap
  1173. */
  1174. bool extract_radiotap_ss(const u_char *const pkt_data,
  1175. owl_captured_request *const request)
  1176. {
  1177. uint32_t rtap_presentflags ;
  1178. uint_fast16_t rtap_position ;
  1179. bool rtap_ext ;
  1180. // Get the first Present Flags field from the Radiotap header:
  1181. memcpy(&rtap_presentflags,
  1182. &pkt_data[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ;
  1183. // The Radiotap header is little-endian
  1184. rtap_presentflags = le32toh(rtap_presentflags) ;
  1185. // The optional fields start right after the Present Flags field:
  1186. rtap_position =
  1187. RTAP_L_HREVISION + RTAP_L_HPAD +
  1188. RTAP_L_HLENGTH + RTAP_L_PRESENTFLAGS ;
  1189. // Skip the potential additional Present Flags fields:
  1190. rtap_ext = FIELD_PRESENT(rtap_presentflags, RTAP_EXT) ;
  1191. while (rtap_ext)
  1192. {
  1193. // Get the additional Present Flags field:
  1194. uint32_t rtap_presentflags_ext ;
  1195. memcpy(&rtap_presentflags_ext,
  1196. &pkt_data[rtap_position], RTAP_L_PRESENTFLAGS) ;
  1197. rtap_presentflags_ext = le32toh(rtap_presentflags_ext) ;
  1198. // Check if there is another one after it:
  1199. rtap_ext = FIELD_PRESENT(rtap_presentflags_ext, RTAP_EXT) ;
  1200. // Skip the current field:
  1201. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_PRESENTFLAGS) ;
  1202. }
  1203. // Test the first bits of the flag field in order to check their
  1204. // presence, up to the antenna signal field which is the only one
  1205. // we need:
  1206. if (FIELD_PRESENT(rtap_presentflags, RTAP_TSFT))
  1207. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_TSFT) ;
  1208. if (FIELD_PRESENT(rtap_presentflags, RTAP_FLAGS))
  1209. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FLAGS) ;
  1210. if (FIELD_PRESENT(rtap_presentflags, RTAP_RATE))
  1211. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_RATE) ;
  1212. if (FIELD_PRESENT(rtap_presentflags, RTAP_CHANNEL))
  1213. {
  1214. // The channel field is actually two fields that must be
  1215. // aligned independently
  1216. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_CHANNEL) ;
  1217. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_CHANNELFLAGS) ;
  1218. }
  1219. if (FIELD_PRESENT(rtap_presentflags, RTAP_FHSS))
  1220. {
  1221. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FHSSHOPSET) ;
  1222. rtap_position += SKIP_FIELD(rtap_position, RTAP_L_FHSSHOPPATTERN) ;
  1223. }
  1224. if (FIELD_PRESENT(rtap_presentflags, RTAP_ANTENNASIGNAL))
  1225. {
  1226. rtap_position += nat_align(rtap_position, RTAP_L_ANTENNASIGNAL) ;
  1227. memcpy(&request->ss_dbm, &pkt_data[rtap_position],
  1228. RTAP_L_ANTENNASIGNAL) ;
  1229. if (VERBOSE_INFO)
  1230. printf("Antenna signal: %"PRId8" dBm\n", request->ss_dbm) ;
  1231. return true ;
  1232. }
  1233. // Antenna signal not extracted
  1234. request->ss_dbm = 127 ; // maximum, improbable value
  1235. return false ;
  1236. }
  1237. /*
  1238. * Computes the number of padding bytes required to achieve natural
  1239. * alignment of a field of length 'field_len', given the position
  1240. * 'offset' it should normally be at in the buffer. The aligned
  1241. * position is the sum of 'offset' and the returned value.
  1242. *
  1243. * To advance to the next available position, you can also use the macro
  1244. * SKIP_FIELD(), which is a simple wrapper around this function.
  1245. */
  1246. uint_fast16_t nat_align(const uint_fast16_t offset,
  1247. const uint_fast8_t field_len)
  1248. {
  1249. uint_fast8_t alignment = offset % field_len ;
  1250. if (alignment == 0)
  1251. return 0 ;
  1252. return field_len - alignment ;
  1253. }
  1254. void display_captured_request(const owl_captured_request *const request,
  1255. const struct pcap_pkthdr *const pkt_header)
  1256. {
  1257. owl_timestamp tmp_time ;
  1258. char
  1259. request_time_str[OWL_TIMESTAMP_STRLEN],
  1260. capture_time_str[OWL_TIMESTAMP_STRLEN],
  1261. cp_mac_addr_str[OWL_ETHER_ADDR_STRLEN],
  1262. mobile_mac_addr_str[OWL_ETHER_ADDR_STRLEN],
  1263. mobile_ip_str[INET_ADDRSTRLEN] ;
  1264. tmp_time = request->request_time ;
  1265. owl_ntoh_timestamp(&tmp_time) ;
  1266. owl_timestamp_to_string(&tmp_time, request_time_str) ;
  1267. tmp_time = request->capture_time ;
  1268. owl_ntoh_timestamp(&tmp_time) ;
  1269. owl_timestamp_to_string(&tmp_time, capture_time_str) ;
  1270. owl_mac_bytes_to_string_r(request->cp_mac_addr_bytes,
  1271. cp_mac_addr_str) ;
  1272. owl_mac_bytes_to_string_r(request->mobile_mac_addr_bytes,
  1273. mobile_mac_addr_str) ;
  1274. inet_ntop(AF_INET, &request->mobile_ip_addr_bytes,
  1275. mobile_ip_str, INET_ADDRSTRLEN) ;
  1276. printf("*** Request to send ***\n"
  1277. "\tType: %"PRIu8"\n"
  1278. "\tCP's MAC: %s\n"
  1279. "\tMobile's MAC: %s\n"
  1280. "\tMobile's IP: %s\n"
  1281. "\tRequest timestamp: %s\n"
  1282. "\tRequest arrival time on the CP: %s\n"
  1283. "\tSignal: %"PRId8" dBm\n"
  1284. "\tPosition X: %f\n"
  1285. "\tPosition Y: %f\n"
  1286. "\tPosition Z: %f\n"
  1287. "\tDirection: %hhd\n"
  1288. "\tPacket number: %"PRIu16"/%"PRIu16"\n"
  1289. "\tPacket size: %"PRIu32"\n"
  1290. ,
  1291. request->type,
  1292. cp_mac_addr_str,
  1293. mobile_mac_addr_str,
  1294. mobile_ip_str,
  1295. request_time_str,
  1296. capture_time_str,
  1297. request->ss_dbm,
  1298. owl_ntohf(request->x_position),
  1299. owl_ntohf(request->y_position),
  1300. owl_ntohf(request->z_position),
  1301. request->direction,
  1302. ntohs(request->packet_id),
  1303. ntohs(request->nb_packets),
  1304. pkt_header->len
  1305. ) ;
  1306. }
  1307. /*
  1308. * Gets the MAC address of the interface `iface` and copies it to
  1309. * `mac_bytes`.
  1310. */
  1311. void get_mac_addr(const char *const iface,
  1312. uint8_t mac_bytes[ETHER_ADDR_LEN])
  1313. #ifdef linux
  1314. {
  1315. struct ifreq ifr;
  1316. int sockfd ;
  1317. // Empty mac_bytes:
  1318. memset(mac_bytes, 0, sizeof(uint8_t) * ETHER_ADDR_LEN) ;
  1319. sockfd = socket(AF_INET, SOCK_DGRAM, 0) ;
  1320. if(sockfd < 0)
  1321. {
  1322. perror("Cannot open socket to read MAC address") ;
  1323. return ;
  1324. }
  1325. strncpy(ifr.ifr_name, iface, IFNAMSIZ) ;
  1326. // Note: the SIOCGIFHWADDR ioctl is Linux-specific
  1327. if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0)
  1328. {
  1329. perror("ioctl(SIOCGIFHWADDR) error getting MAC address") ;
  1330. return ;
  1331. }
  1332. memcpy(mac_bytes, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN) ;
  1333. }
  1334. #else // linux
  1335. {
  1336. #define HWADDR_MIB_SIZE 6
  1337. int mib[HWADDR_MIB_SIZE] ;
  1338. int ifindex ; // iface's index
  1339. char *buf = NULL ;
  1340. size_t buflen = 0 ;
  1341. // Empty mac_bytes:
  1342. memset(mac_bytes, 0, sizeof(uint8_t) * ETHER_ADDR_LEN) ;
  1343. ifindex = if_nametoindex(iface) ;
  1344. if (ifindex == 0)
  1345. {
  1346. perror("Cannot get interface's index to get its MAC address") ;
  1347. return ;
  1348. }
  1349. // See sysctl(7) for more information
  1350. mib[0] = CTL_NET ; // First level = the net subtree
  1351. mib[1] = PF_ROUTE ; // Second level = route
  1352. mib[2] = 0 ; // Third level = protocol (always 0)
  1353. mib[3] = AF_LINK ; // Fourth level = address family
  1354. mib[4] = NET_RT_IFLIST ; // Fifth level = type of info
  1355. mib[5] = ifindex ; /* sysctl(7) says there is no sixth level with
  1356. * NET_RT_IFLIST, but actually it has to be the
  1357. * interface's index */
  1358. // Get the size of the available data
  1359. if (sysctl(mib, HWADDR_MIB_SIZE, NULL, &buflen, NULL, 0))
  1360. {
  1361. perror("sysctl() error getting MAC address") ;
  1362. return ;
  1363. }
  1364. buf = malloc(buflen) ;
  1365. if (! buf)
  1366. {
  1367. perror("Cannot allocate memory") ;
  1368. return ;
  1369. }
  1370. if (sysctl(mib, HWADDR_MIB_SIZE, buf, &buflen, NULL, 0))
  1371. perror("sysctl() error getting MAC address") ;
  1372. else
  1373. {
  1374. struct if_msghdr *ifm = (struct if_msghdr*)buf ;
  1375. struct sockaddr_dl *sdl = (struct sockaddr_dl*)(ifm + 1) ;
  1376. unsigned char *hwaddr = (unsigned char*)(LLADDR(sdl)) ;
  1377. int i ;
  1378. for (i = 0 ; i < 6 ; ++i)
  1379. mac_bytes[i] = (uint8_t)hwaddr[i] ;
  1380. }
  1381. free(buf) ;
  1382. }
  1383. #endif // linux
  1384. /*
  1385. * Gets the IP address of the interface `iface` and copies it to `ip`.
  1386. */
  1387. void get_ip_addr(const char *const iface, char ip[INET_ADDRSTRLEN])
  1388. {
  1389. struct ifreq ifr;
  1390. int sockfd ;
  1391. struct sockaddr_in sa ;
  1392. struct in_addr ip_addr ;
  1393. sockfd = socket(AF_INET, SOCK_DGRAM, 0) ;
  1394. if(sockfd < 0)
  1395. perror("Cannot open socket to read IP address") ;
  1396. strncpy(ifr.ifr_name, iface, IFNAMSIZ) ;
  1397. if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0)
  1398. {
  1399. perror("ioctl(SIOCGIFADDR) error getting IP address") ;
  1400. return ;
  1401. }
  1402. memcpy(&ip_addr, &ifr.ifr_addr.sa_data[sizeof(sa.sin_port)],
  1403. sizeof(ip_addr)) ;
  1404. if (inet_ntop(AF_INET, &ip_addr, ip, INET_ADDRSTRLEN) == NULL)
  1405. perror("inet_ntop() error getting IP address") ;
  1406. }
  1407. /* *** Autocalibration functions *** */
  1408. #ifdef OWLPS_LISTENER_USES_PTHREAD
  1409. void* autocalibrate_hello(void *const NULL_value)
  1410. {
  1411. int send_sockfd ;
  1412. struct sockaddr serv;
  1413. owl_autocalibration_hello message ;
  1414. if (VERBOSE_WARNING)
  1415. fprintf(stderr, "Autocalibration Hello thread launched.\n") ;
  1416. send_sockfd =
  1417. owl_create_trx_socket(GET_AGGREGATION_HOST(),
  1418. GET_AUTOCALIBRATION_HELLO_PORT(),
  1419. &serv, NULL) ;
  1420. pthread_cleanup_push(&owl_close_fd, &send_sockfd) ;
  1421. memcpy(&message.cp_mac_addr_bytes, my_mac_bytes, ETHER_ADDR_LEN) ;
  1422. while (owl_run)
  1423. {
  1424. owl_send_packet(send_sockfd, &serv,
  1425. &message, sizeof(message), VERBOSE_INFO) ;
  1426. sleep(GET_AUTOCALIBRATION_HELLO_DELAY()) ;
  1427. }
  1428. /* Close the socket */
  1429. pthread_cleanup_pop(1) ;
  1430. pthread_exit(NULL_value) ;
  1431. }
  1432. void* autocalibrate(void *const NULL_value)
  1433. {
  1434. int nread ; // recvfrom return value
  1435. int listen_sockfd ;
  1436. owl_autocalibration_order message ;
  1437. if (VERBOSE_WARNING)
  1438. fprintf(stderr, "Autocalibration thread launched.\n") ;
  1439. // Socket to send autocalibration positioning requests
  1440. autocalibration_send_sockfd =
  1441. owl_create_trx_socket(GET_AUTOCALIBRATION_HOST(),
  1442. GET_AUTOCALIBRATION_REQUEST_PORT(),
  1443. &autocalibration_send_server,
  1444. GET_WIFI_IFACE()) ;
  1445. // Socket to receive orders from the aggregator
  1446. listen_sockfd =
  1447. owl_create_udp_listening_socket(GET_AUTOCALIBRATION_ORDER_PORT()) ;
  1448. if (listen_sockfd < 0)
  1449. {
  1450. perror("Error! Cannot create UDP listening socket from the"
  1451. " aggregation server") ;
  1452. exit(OWL_ERR_SOCKET_CREATE) ;
  1453. }
  1454. pthread_cleanup_push(&owl_close_fd, &listen_sockfd) ;
  1455. while (owl_run)
  1456. {
  1457. nread = recvfrom(listen_sockfd, &message, sizeof(message), 0,
  1458. NULL, NULL) ;
  1459. if (nread <= 0 && owl_run)
  1460. {
  1461. if (owl_run)
  1462. perror("No message received from aggregator") ;
  1463. continue ;
  1464. }
  1465. if (message.order == AUTOCALIBRATION_ORDER_SEND)
  1466. {
  1467. if (VERBOSE_INFO)
  1468. fprintf(stderr, "I was just ordered to send an"
  1469. " autocalibration request...\n") ;
  1470. send_autocalibration_request() ;
  1471. }
  1472. else
  1473. fprintf(stderr,
  1474. "Autocalibration order unknown: %d.\n", message.order) ;
  1475. }
  1476. /* Close the socket */
  1477. pthread_cleanup_pop(1) ;
  1478. pthread_exit(NULL_value) ;
  1479. }
  1480. void send_autocalibration_request()
  1481. {
  1482. uint8_t *packet ;
  1483. uint_fast16_t packet_size = make_packet(&packet) ;
  1484. owl_send_request(autocalibration_send_sockfd,
  1485. &autocalibration_send_server,
  1486. packet, packet_size,
  1487. GET_AUTOCALIBRATION_NBPKT(),
  1488. GET_AUTOCALIBRATION_DELAY(),
  1489. VERBOSE_INFO) ;
  1490. free(packet) ;
  1491. }
  1492. /*
  1493. * Creates the calibration packet to send.
  1494. * 'packet' must not be NULL. '*packet' must be freed by the calling
  1495. * function.
  1496. * Returns the size of the packet.
  1497. * In case of error, 0 is returned and *packet is not updated.
  1498. */
  1499. uint_fast16_t make_packet(uint8_t **const packet)
  1500. {
  1501. uint8_t *pkt ;
  1502. uint_fast16_t size ; // Packet size
  1503. uint_fast16_t offset ; // Index used to create the packet
  1504. owl_timestamp request_time ;
  1505. float
  1506. my_position_x = owl_htonf(GET_MY_POSITION_X()),
  1507. my_position_y = owl_htonf(GET_MY_POSITION_Y()),
  1508. my_position_z = owl_htonf(GET_MY_POSITION_Z()) ;
  1509. uint16_t npkt ;
  1510. assert(packet) ;
  1511. owl_timestamp_now(&request_time) ;
  1512. if (VERBOSE_CHATTERBOX)
  1513. {
  1514. char request_time_str[OWL_TIMESTAMP_STRLEN] ;
  1515. owl_timestamp_to_string(&request_time, request_time_str) ;
  1516. printf("Autocalibration time: %s\n", request_time_str) ;
  1517. }
  1518. owl_hton_timestamp(&request_time) ;
  1519. offset = 0 ;
  1520. size =
  1521. sizeof(uint8_t) * 2 + sizeof(owl_timestamp) + sizeof(float) * 3 +
  1522. sizeof(uint16_t) * 2 ;
  1523. pkt = malloc(size) ;
  1524. if (! pkt)
  1525. {
  1526. perror("Cannot allocate memory") ;
  1527. return 0 ;
  1528. }
  1529. // Request type:
  1530. memset(&pkt[offset++], OWL_REQUEST_AUTOCALIBRATION, 1) ;
  1531. // Number of the current packet (1 for the first):
  1532. npkt = htons(1u) ;
  1533. memcpy(&pkt[offset], &npkt, sizeof(uint16_t)) ;
  1534. offset += sizeof(uint16_t) ;
  1535. // Number of packets:
  1536. npkt = htons(GET_AUTOCALIBRATION_NBPKT()) ;
  1537. memcpy(&pkt[offset], &npkt, sizeof(uint16_t)) ;
  1538. offset += sizeof(uint16_t) ;
  1539. // Timestamp:
  1540. memcpy(&pkt[offset], &request_time, sizeof(request_time)) ;
  1541. offset += sizeof(request_time) ;
  1542. // Coordinates:
  1543. pkt[offset++] = GET_MY_DIRECTION() ;
  1544. memcpy(&pkt[offset], &my_position_x, sizeof(float)) ;
  1545. offset += sizeof(float) ;
  1546. memcpy(&pkt[offset], &my_position_y, sizeof(float)) ;
  1547. offset += sizeof(float) ;
  1548. memcpy(&pkt[offset], &my_position_z, sizeof(float)) ;
  1549. #ifndef NDEBUG
  1550. offset += sizeof(float) ;
  1551. assert(offset == size) ;
  1552. #endif // NDEBUG
  1553. *packet = pkt ;
  1554. return size ;
  1555. }
  1556. #endif // OWLPS_LISTENER_USES_PTHREAD
  1557. /* *** End of autocalibration functions *** */
  1558. void sigint_handler(const int num)
  1559. {
  1560. owl_sigint_handler(num) ;
  1561. pcap_breakloop(capture_handler) ;
  1562. }
  1563. void sigterm_handler(const int num)
  1564. {
  1565. owl_sigterm_handler(num) ;
  1566. pcap_breakloop(capture_handler) ;
  1567. }
  1568. void print_usage()
  1569. {
  1570. printf("Usage :\n"
  1571. "\t%s"
  1572. " [-f config_file]"
  1573. " [-G]"
  1574. " [-D]"
  1575. " [-v[v[v[v]]] | -q]"
  1576. "\n\t"
  1577. " <-r rtap_iface [-w wifi_iface] | -R pcap_file>"
  1578. " [-K]"
  1579. " [-m mode]"
  1580. "\n\t"
  1581. " [-l listening_port]"
  1582. " [-i aggregation_host]"
  1583. " [-p aggregation_port]"
  1584. "\n\t"
  1585. " [-A]"
  1586. " [-I autocalibration_host]"
  1587. " [-P autocalibration_request_port]"
  1588. "\n\t"
  1589. " [-O autocalibration_order_port]"
  1590. " [-H hello_port]"
  1591. " [-T hello_delay]"
  1592. "\n\t"
  1593. " [-t autocalibration_delay]"
  1594. " [-n autocalibration_nb_packets]"
  1595. "\n\t"
  1596. " [direction x y z]\n"
  1597. "\t%s -h\n"
  1598. "\t%s -V\n"
  1599. "Main options:\n"
  1600. "\t-h\t\tPrint this help message and exit.\n"
  1601. "\t-V\t\tShow version information and exit.\n"
  1602. "\t-f config_file\tUse 'config_file' instead of the default"
  1603. " configuration\n\t\t\tfile (%s).\n\t\t\tAvailable only if the"
  1604. " program was linked against\n\t\t\tlibconfuse.\n"
  1605. "\t-G\t\tDump the configuration on the standard output and exit"
  1606. "\n\t\t\t(useful to generate a configuration file from the"
  1607. "\n\t\t\tcurrent set of options).\n"
  1608. "\t-D\t\tDaemon mode.\n"
  1609. "\t-v\t\tBe verbose. You can use this option up to 4 times to"
  1610. "\n\t\t\tincrease the level of verbosity (1 = warnings,"
  1611. "\n\t\t\t2 = useful information, 3 = a lot of information,"
  1612. "\n\t\t\t4 = display each captured packet).\n"
  1613. "\t-q\t\tQuiet mode (default): sets the verbose level to 0.\n"
  1614. "Capture options:\n"
  1615. "\t-m mode\t\t\tCapture mode: a(ctive), p(assive), m(ixed)"
  1616. "\n\t\t\t\t(default: a).\n"
  1617. "\t-l listening_port\tPort to which explicit positioning"
  1618. " requests are\n\t\t\t\tsent by the mobiles (default: %d).\n"
  1619. "\t-i aggregation_host\tHost name or IP address of the"
  1620. " aggregation\n\t\t\t\tserver (default: %s).\n"
  1621. "\t-p aggregation_port\tRequests are transmitted to the"
  1622. " aggregation\n\t\t\t\tserver on this port (default: %d).\n"
  1623. "\t-r rtap_iface\t\tRadiotap-enabled capture interface.\n"
  1624. "\t-w wifi_iface\t\tPhysical interface behind rtap_iface"
  1625. " (default:\n\t\t\t\trtap_iface).\n"
  1626. "\t-R pcap_file\t\tPcap file to read packets from.\n"
  1627. "Autocalibration options:\n"
  1628. "(These options are available only if the program was compiled"
  1629. " with support of\nthe POSIX threads and the adequate"
  1630. " compilation-time option.)\n"
  1631. "\t-A\t\t\tEnable autocalibration (default: disabled).\n"
  1632. "\t-I ac_host\t\tHost name or IP address of the destination"
  1633. " of\n\t\t\t\tthe autocalibration requests"
  1634. " (default:\n\t\t\t\taggregation_host).\n"
  1635. "\t-P ac_request_port\tPort to which autocalibration"
  1636. " requests are sent\n\t\t\t\t(default: listening_port).\n"
  1637. "\t-O ac_order_port\tPort on which autocalibration orders are"
  1638. "\n\t\t\t\treceived from the aggregation server (default:"
  1639. "\n\t\t\t\t%d).\n"
  1640. "\t-H hello_port\t\tPort to which hello messages are sent to"
  1641. " the\n\t\t\t\taggregation server (default: %d).\n"
  1642. "\t-T hello_delay\t\tTime between each hello message sent to"
  1643. " the\n\t\t\t\taggregation server, in seconds (default:"
  1644. " %d s).\n"
  1645. "\t-t ac_delay\t\tTime between two autocalibration"
  1646. " packets,\n\t\t\t\tin milliseconds (default: %d ms).\n"
  1647. "\t-n ac_nb_packets\tNumber of packets transmitted"
  1648. " for one\n\t\t\t\tautocalibration request (default: %d).\n"
  1649. "\tdirection x y z\t\tThe coordinates of the listener"
  1650. " (direction is an\n\t\t\t\tinteger; x, y, z are floats).\n"
  1651. "Miscelanneous options:\n"
  1652. "\t-K\tKeep the monitor mode up on wifi_iface. Use it with"
  1653. " buggy\n\t\tdrivers that disable monitor mode periodically."
  1654. " Available only\n\t\tif the program was compiled with the"
  1655. " option\n\t\tOWLPS_LISTENER_KEEPS_MONITOR.\n"
  1656. ,
  1657. program_name,
  1658. program_name,
  1659. program_name,
  1660. DEFAULT_CONFIG_FILE,
  1661. OWL_DEFAULT_REQUEST_PORT,
  1662. DEFAULT_AGGREGATION_HOST,
  1663. OWL_DEFAULT_LISTENER_PORT,
  1664. OWL_DEFAULT_AUTOCALIBRATION_ORDER_PORT,
  1665. OWL_DEFAULT_AUTOCALIBRATION_HELLO_PORT,
  1666. DEFAULT_AUTOCALIBRATION_HELLO_DELAY,
  1667. DEFAULT_AUTOCALIBRATION_DELAY,
  1668. DEFAULT_AUTOCALIBRATION_NBPKT
  1669. ) ;
  1670. }
  1671. void print_version()
  1672. {
  1673. printf("This is OwlPS Listener, part of the Owl Positioning System"
  1674. " project.\n"
  1675. "Version: %s.\n"
  1676. "Compilation-time options:\n"
  1677. "\tSupport for configuration file (libconfuse): %s.\n"
  1678. "\tSupport for POSIX threads: %s.\n"
  1679. "\tOption -K: %s.\n",
  1680. #ifdef OWLPS_VERSION
  1681. OWLPS_VERSION
  1682. #else // OWLPS_VERSION
  1683. "unknown version"
  1684. #endif // OWLPS_VERSION
  1685. ,
  1686. #ifdef OWLPS_LISTENER_USES_CONFIG_FILE
  1687. "YES"
  1688. #else // OWLPS_LISTENER_USES_CONFIG_FILE
  1689. "NO"
  1690. #endif // OWLPS_LISTENER_USES_CONFIG_FILE
  1691. ,
  1692. #ifdef OWLPS_LISTENER_USES_PTHREAD
  1693. "YES"
  1694. #else // OWLPS_LISTENER_USES_PTHREAD
  1695. "NO"
  1696. #endif // OWLPS_LISTENER_USES_PTHREAD
  1697. ,
  1698. #ifdef OWLPS_LISTENER_KEEPS_MONITOR
  1699. "YES"
  1700. #else // OWLPS_LISTENER_KEEPS_MONITOR
  1701. "NO"
  1702. #endif // OWLPS_LISTENER_KEEPS_MONITOR
  1703. ) ;
  1704. }