arpc.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * arpc.c -
  11. *
  12. * Contributor(s):
  13. * Charles Maier <cmaier@qca.qualcomm.com>
  14. * Nathaniel Houghton <nhoughto@qca.qualcomm.com>
  15. *
  16. *--------------------------------------------------------------------*/
  17. /*====================================================================*
  18. * system header files;
  19. *--------------------------------------------------------------------*/
  20. #include <unistd.h>
  21. #include <stdio.h>
  22. #include <stdint.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <limits.h>
  26. #include <time.h>
  27. #include <sys/time.h>
  28. /*====================================================================*
  29. * custom header files;
  30. *--------------------------------------------------------------------*/
  31. #include "../tools/getoptv.h"
  32. #include "../tools/putoptv.h"
  33. #include "../tools/memory.h"
  34. #include "../tools/number.h"
  35. #include "../tools/types.h"
  36. #include "../tools/flags.h"
  37. #include "../tools/files.h"
  38. #include "../tools/error.h"
  39. #include "../ether/channel.h"
  40. #include "../mme/mme.h"
  41. #include "../plc/plc.h"
  42. /*====================================================================*
  43. * custom source files;
  44. *--------------------------------------------------------------------*/
  45. #ifndef MAKEFILE
  46. #include "../tools/getoptv.c"
  47. #include "../tools/putoptv.c"
  48. #include "../tools/version.c"
  49. #include "../tools/hexdump.c"
  50. #include "../tools/uintspec.c"
  51. #include "../tools/todigit.c"
  52. #include "../tools/hexwrite.c"
  53. #include "../tools/error.c"
  54. #endif
  55. #ifndef MAKEFILE
  56. #include "../ether/channel.c"
  57. #include "../ether/openchannel.c"
  58. #include "../ether/closechannel.c"
  59. #include "../ether/sendpacket.c"
  60. #include "../ether/readpacket.c"
  61. #endif
  62. #ifndef MAKEFILE
  63. #include "../mme/ARPCPrint.c"
  64. #include "../mme/ARPCWrite.c"
  65. #include "../mme/ARPCPeek.c"
  66. #endif
  67. /*====================================================================*
  68. * program constants;
  69. *--------------------------------------------------------------------*/
  70. #define PLCDEVICE "PLC"
  71. #if defined (WIN32)
  72. #define TIMEVALUE "%012ld.%06ld"
  73. #elif defined (__APPLE__)
  74. #define TIMEVALUE "%012lu.%06u"
  75. #elif defined (__linux__)
  76. #define TIMEVALUE "%012ld.%06ld"
  77. #elif defined (__OpenBSD__)
  78. #define TIMEVALUE "%012ld.%06ld"
  79. #else
  80. #error "Unknown environment"
  81. #endif
  82. /*====================================================================*
  83. *
  84. * void ARPCDump (struct channel * channel, void const * memory, size_t extent);
  85. *
  86. * print or write ARPC messages based on ARPCID.
  87. *
  88. *--------------------------------------------------------------------*/
  89. static void ARPCDump (struct channel * channel, void const * memory, size_t extent)
  90. {
  91. #ifndef __GNUC__
  92. #pragma pack (push,1)
  93. #endif
  94. struct __packed vs_arpc_data
  95. {
  96. uint32_t BYPASS;
  97. uint16_t ARPCID;
  98. uint16_t DATALENGTH;
  99. uint8_t DATAOFFSET;
  100. uint8_t RESERVED [3];
  101. uint16_t ARGOFFSET;
  102. uint16_t STROFFSET;
  103. uint16_t ARGLENGTH;
  104. uint16_t STRLENGTH;
  105. uint8_t LIST [1];
  106. }
  107. * data = (struct vs_arpc_data *) (memory);
  108. #ifndef __GNUC__
  109. #pragma pack (pop)
  110. #endif
  111. struct timeval tv;
  112. gettimeofday (& tv, NULL);
  113. if (LE16TOH (data->ARPCID) == 1)
  114. {
  115. if (_anyset (channel->flags, CHANNEL_MONITOR))
  116. {
  117. fprintf (stdout, TIMEVALUE " ", tv.tv_sec, tv.tv_usec);
  118. }
  119. ARPCPrint (stdout, memory, extent);
  120. return;
  121. }
  122. if (LE16TOH (data->ARPCID) == 2)
  123. {
  124. if (_anyset (channel->flags, CHANNEL_MONITOR))
  125. {
  126. if (isatty (fileno (stdout)))
  127. {
  128. hexwrite (fileno (stdout), & tv, sizeof (tv));
  129. }
  130. else
  131. {
  132. fwrite (& tv, sizeof (tv), 1, stdout);
  133. }
  134. }
  135. ARPCWrite (stdout, memory, extent);
  136. return;
  137. }
  138. return;
  139. }
  140. /*====================================================================*
  141. *
  142. * void function (struct channel * channel, signed fd);
  143. *
  144. * capture and record VS_ARPC messages from any Atheros powerline
  145. * device; devices must be programmed to send these messages;
  146. *
  147. * this function has no practical use under operation conditions;
  148. *
  149. *--------------------------------------------------------------------*/
  150. static void function (struct channel * channel)
  151. {
  152. struct message message;
  153. #ifndef __GNUC__
  154. #pragma pack (push,1)
  155. #endif
  156. struct __packed vs_arpc_ind
  157. {
  158. struct ethernet_hdr ethernet;
  159. struct qualcomm_hdr qualcomm;
  160. uint16_t RDATALENGTH;
  161. uint8_t RDATAOFFSET;
  162. uint8_t RDATA [1];
  163. }
  164. * indicate = (struct vs_arpc_ind *) (& message);
  165. #ifndef __GNUC__
  166. #pragma pack (pop)
  167. #endif
  168. signed length;
  169. while ((length = readpacket (channel, & message, sizeof (message))) >= 0)
  170. {
  171. if (! length)
  172. {
  173. continue;
  174. }
  175. if (ntohs (indicate->ethernet.MTYPE) != ETH_P_HPAV)
  176. {
  177. continue;
  178. }
  179. if (indicate->qualcomm.MMV != 0)
  180. {
  181. continue;
  182. }
  183. if (LE16TOH (indicate->qualcomm.MMTYPE) != (VS_ARPC | MMTYPE_IND))
  184. {
  185. continue;
  186. }
  187. ARPCDump (channel, & indicate->RDATA [indicate->RDATAOFFSET], LE16TOH (indicate->RDATALENGTH) - indicate->RDATAOFFSET);
  188. }
  189. return;
  190. }
  191. /*====================================================================*
  192. *
  193. * void timeout ();
  194. *
  195. * print current time as both hh:mm:ss and seconds.milliseconds;
  196. *
  197. * POSIX says ...
  198. *
  199. * struct { time_t tv_sec; suseconds_t tv_usec; } timeval;
  200. *
  201. * on OSX ...
  202. *
  203. * typedef __darwin_time_t time_t;
  204. * typesef __darwin_suseconds_t suseconds_t;
  205. *
  206. * typedef long __darwin_time_t;
  207. * typedef __int32_t __darwin_suseconds_t;
  208. *
  209. * on Windows ...
  210. *
  211. * on Linux ...
  212. *
  213. *--------------------------------------------------------------------*/
  214. static void timeout ()
  215. {
  216. char time [9];
  217. struct timeval tv;
  218. gettimeofday (& tv, NULL);
  219. strftime (time, sizeof (time), "%H:%M:%S", localtime ((const time_t *) (& tv.tv_sec)));
  220. printf ("%s " TIMEVALUE "\n", time, tv.tv_sec, tv.tv_usec);
  221. printf ("sizeof (tv.tv_sec) is " SIZE_T_SPEC " bytes\n", sizeof (tv.tv_sec));
  222. printf ("sizeof (tv.tv_usec) is " SIZE_T_SPEC " bytes\n", sizeof (tv.tv_usec));
  223. return;
  224. }
  225. /*====================================================================*
  226. *
  227. * int main (int argc, char * argv[]);
  228. *
  229. *--------------------------------------------------------------------*/
  230. int main (int argc, char const * argv [])
  231. {
  232. extern struct channel channel;
  233. static char const * optv [] =
  234. {
  235. "i:mqt:vz",
  236. PUTOPTV_S_DIVINE,
  237. "Qualcomm Atheros Asynchronous Remote Procedure Call Monitor",
  238. #if defined (WINPCAP) || defined (LIBPCAP)
  239. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  240. #else
  241. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  242. #endif
  243. "m\tprefix messages with system time in seconds.milliseconds",
  244. "q\tsuppress output on stdout",
  245. "t n\tread timeout is (n) milliseconds [" LITERAL (CHANNEL_TIMEOUT) "]",
  246. "v\tverbose messages on stderr",
  247. "z\tprint sample time as hh:mm:ss and seconds.milliseconds then exit",
  248. (char const *) (0)
  249. };
  250. signed c;
  251. if (getenv (PLCDEVICE))
  252. {
  253. #if defined (WINPCAP) || defined (LIBPCAP)
  254. channel.ifindex = atoi (getenv (PLCDEVICE));
  255. #else
  256. channel.ifname = strdup (getenv (PLCDEVICE));
  257. #endif
  258. }
  259. optind = 1;
  260. while (~ (c = getoptv (argc, argv, optv)))
  261. {
  262. switch (c)
  263. {
  264. case 'i':
  265. #if defined (WINPCAP) || defined (LIBPCAP)
  266. channel.ifindex = atoi (optarg);
  267. #else
  268. channel.ifname = optarg;
  269. #endif
  270. break;
  271. case 'm':
  272. _setbits (channel.flags, CHANNEL_MONITOR);
  273. break;
  274. case 'q':
  275. _setbits (channel.flags, CHANNEL_SILENCE);
  276. break;
  277. case 't':
  278. channel.timeout = (signed) (uintspec (optarg, 0, UINT_MAX));
  279. break;
  280. case 'v':
  281. _setbits (channel.flags, CHANNEL_VERBOSE);
  282. break;
  283. case 'z':
  284. timeout ();
  285. return (0);
  286. default:
  287. break;
  288. }
  289. }
  290. argc -= optind;
  291. argv += optind;
  292. if (argc)
  293. {
  294. error (1, ENOTSUP, ERROR_TOOMANY);
  295. }
  296. #ifdef WIN32
  297. setmode (STDOUT_FILENO, O_BINARY);
  298. #endif
  299. openchannel (& channel);
  300. function (& channel);
  301. closechannel (& channel);
  302. fflush (stdout);
  303. return (0);
  304. }