efsu.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or
  8. * without modification, are permitted (subject to the limitations
  9. * in the disclaimer below) provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer in the documentation and/or other materials
  18. * provided with the distribution.
  19. *
  20. * * Neither the name of Qualcomm Atheros nor the names of
  21. * its contributors may be used to endorse or promote products
  22. * derived from this software without specific prior written
  23. * permission.
  24. *
  25. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  26. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
  27. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  28. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  29. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  31. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  37. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. *--------------------------------------------------------------------*/
  41. /*====================================================================*
  42. *
  43. * efsu.c - Ethernet Frame Send Utility;
  44. *
  45. * convert hexadecimal text files to ethernet frames and transmit
  46. * them over the network; basically, it is a 'send your own frame'
  47. * utility;
  48. *
  49. * the program works like cat, sending file after file to a given
  50. * interface; as each file is read, all hexadecimal octets in the
  51. * file are converted to bytes and buffered; a semicolon causes a
  52. * buffer transmit as does the end of file; script-style comments
  53. * starting with hash (#) and c-language-style comments starting
  54. * with slash-slash or slash-asterisk are consumed and discard as
  55. * the file is read; the errors that can occur are non-hex digits
  56. * and odd number of hex digits;
  57. *
  58. *
  59. *--------------------------------------------------------------------*/
  60. /*====================================================================*
  61. * system header files;
  62. *--------------------------------------------------------------------*/
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <limits.h>
  66. /*====================================================================*
  67. * custom header files;
  68. *--------------------------------------------------------------------*/
  69. #include "../tools/getoptv.h"
  70. #include "../tools/putoptv.h"
  71. #include "../tools/error.h"
  72. #include "../tools/memory.h"
  73. #include "../tools/number.h"
  74. #include "../tools/symbol.h"
  75. #include "../tools/flags.h"
  76. #include "../ether/channel.h"
  77. /*====================================================================*
  78. * custom source files;
  79. *--------------------------------------------------------------------*/
  80. #ifndef MAKEFILE
  81. #include "../tools/getoptv.c"
  82. #include "../tools/putoptv.c"
  83. #include "../tools/version.c"
  84. #include "../tools/error.c"
  85. #include "../tools/hexencode.c"
  86. #include "../tools/hexload.c"
  87. #include "../tools/hexdump.c"
  88. #include "../tools/todigit.c"
  89. #include "../tools/uintspec.c"
  90. #include "../tools/basespec.c"
  91. #include "../tools/synonym.c"
  92. #endif
  93. #ifndef MAKEFILE
  94. #include "../ether/openchannel.c"
  95. #include "../ether/closechannel.c"
  96. #include "../ether/readpacket.c"
  97. #include "../ether/sendpacket.c"
  98. #include "../ether/channel.c"
  99. #endif
  100. /*====================================================================*
  101. * program contants;
  102. *--------------------------------------------------------------------*/
  103. #define EFSU_INTERFACE "PLC"
  104. #define EFSU_ETHERTYPE 0x88E1
  105. #define EFSU_PAUSE 0
  106. #define EFSU_DELAY 0
  107. #define EFSU_LOOP 1
  108. #ifndef ETHER_CRC_LEN
  109. #define ETHER_CRC_LEN 4
  110. #endif
  111. /*====================================================================*
  112. * program variables;
  113. *--------------------------------------------------------------------*/
  114. static const struct _term_ protocols [] =
  115. {
  116. {
  117. "hp10",
  118. "887B"
  119. },
  120. {
  121. "hpav",
  122. "88E1"
  123. }
  124. };
  125. /*====================================================================*
  126. *
  127. * void function (struct channel * channel, void * memory, ssize_t extent);
  128. *
  129. * read Ethernet frame descriptions from stdin and transmit them
  130. * as raw ethernet frames; wait for a response if CHANNEL_LISTEN
  131. * flagword bit is set;
  132. *
  133. *
  134. *--------------------------------------------------------------------*/
  135. static void function (struct channel * channel, void * memory, ssize_t extent)
  136. {
  137. struct ether_header * frame = (struct ether_header *)(memory);
  138. unsigned length;
  139. while ((length = (unsigned)(hexload (memory, extent, stdin))) > 0)
  140. {
  141. if (length < (ETHER_MIN_LEN - ETHER_CRC_LEN))
  142. {
  143. error (1, ENOTSUP, "Frame size of %d is less than %d bytes", length, (ETHER_MIN_LEN - ETHER_CRC_LEN));
  144. }
  145. if (length > (ETHER_MAX_LEN - ETHER_CRC_LEN))
  146. {
  147. error (1, ENOTSUP, "Frame size of %d is more than %d bytes", length, (ETHER_MAX_LEN - ETHER_CRC_LEN));
  148. }
  149. if (_anyset (channel->flags, CHANNEL_UPDATE_TARGET))
  150. {
  151. memcpy (frame->ether_dhost, channel->peer, sizeof (frame->ether_dhost));
  152. }
  153. if (_anyset (channel->flags, CHANNEL_UPDATE_SOURCE))
  154. {
  155. memcpy (frame->ether_shost, channel->host, sizeof (frame->ether_shost));
  156. }
  157. sendpacket (channel, memory, length);
  158. if (_anyset (channel->flags, CHANNEL_LISTEN))
  159. {
  160. while (readpacket (channel, memory, extent) > 0);
  161. }
  162. }
  163. return;
  164. }
  165. /*====================================================================*
  166. *
  167. * void iterate (int argc, char const * argv [], void * memory, ssize_t extent, unsigned pause);
  168. *
  169. *
  170. *
  171. *--------------------------------------------------------------------*/
  172. static void iterate (int argc, char const * argv [], struct channel * channel, unsigned pause)
  173. {
  174. byte buffer [ETHER_MAX_LEN];
  175. if (!argc)
  176. {
  177. function (channel, buffer, sizeof (buffer));
  178. }
  179. while ((argc) && (* argv))
  180. {
  181. if (!freopen (* argv, "rb", stdin))
  182. {
  183. error (1, errno, "Can't open %s", * argv);
  184. }
  185. function (channel, buffer, sizeof (buffer));
  186. argc--;
  187. argv++;
  188. if ((argc) && (* argv))
  189. {
  190. sleep (pause);
  191. }
  192. }
  193. return;
  194. }
  195. /*====================================================================*
  196. *
  197. * int main (int argc, char const * argv []);
  198. *
  199. *
  200. *
  201. *--------------------------------------------------------------------*/
  202. int main (int argc, char const * argv [])
  203. {
  204. extern struct channel channel;
  205. static char const * optv [] =
  206. {
  207. "d:e:hi:l:p:t:vw:",
  208. PUTOPTV_S_FUNNEL,
  209. "Ethernet Frame Send Utility",
  210. "d x\treplace destination address with (x)",
  211. "e x\techo return frames having ethertype (x) [" LITERAL (EFSU_ETHERTYPE) "]",
  212. "h\treplace source address with host address",
  213. #if defined (WINPCAP) || defined (LIBPCAP)
  214. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  215. #else
  216. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  217. #endif
  218. "l n\trepeat file sequence (n) times [" LITERAL (EFSU_LOOP) "]",
  219. "p n\twait (n) seconds between files [" LITERAL (EFSU_PAUSE) "]",
  220. "t n\tread timeout is (n) milliseconds [" LITERAL (CHANNEL_TIMEOUT) "]",
  221. "v\tverbose messages",
  222. "w n\twait (n) seconds between loops [" LITERAL (EFSU_DELAY) "]",
  223. (char const *) (0)
  224. };
  225. unsigned pause = EFSU_PAUSE;
  226. unsigned delay = EFSU_DELAY;
  227. unsigned loop = EFSU_LOOP;
  228. signed c;
  229. channel.type = EFSU_ETHERTYPE;
  230. if (getenv (EFSU_INTERFACE))
  231. {
  232. #if defined (WINPCAP) || defined (LIBPCAP)
  233. channel.ifindex = atoi (getenv (EFSU_INTERFACE));
  234. #else
  235. channel.ifname = strdup (getenv (EFSU_INTERFACE));
  236. #endif
  237. }
  238. optind = 1;
  239. while ((c = getoptv (argc, argv, optv)) != -1)
  240. {
  241. switch (c)
  242. {
  243. case 'd':
  244. _setbits (channel.flags, CHANNEL_UPDATE_TARGET);
  245. if (!hexencode (channel.peer, sizeof (channel.peer), optarg))
  246. {
  247. error (1, errno, "%s", optarg);
  248. }
  249. break;
  250. case 'e':
  251. _setbits (channel.flags, CHANNEL_LISTEN);
  252. channel.type = (uint16_t)(basespec (synonym (optarg, protocols, SIZEOF (protocols)), 16, sizeof (channel.type)));
  253. break;
  254. case 'h':
  255. _setbits (channel.flags, CHANNEL_UPDATE_SOURCE);
  256. break;
  257. case 'i':
  258. #if defined (WINPCAP) || defined (LIBPCAP)
  259. channel.ifindex = atoi (optarg);
  260. #else
  261. channel.ifname = optarg;
  262. #endif
  263. break;
  264. case 'l':
  265. loop = (unsigned)(uintspec (optarg, 0, UINT_MAX));
  266. break;
  267. case 'p':
  268. pause = (unsigned)(uintspec (optarg, 0, 1200));
  269. break;
  270. case 'q':
  271. _setbits (channel.flags, CHANNEL_SILENCE);
  272. break;
  273. case 't':
  274. channel.timeout = (signed)(uintspec (optarg, 0, UINT_MAX));
  275. break;
  276. case 'v':
  277. _setbits (channel.flags, CHANNEL_VERBOSE);
  278. break;
  279. case 'w':
  280. delay = (unsigned)(uintspec (optarg, 0, 1200));
  281. break;
  282. default:
  283. break;
  284. }
  285. }
  286. argc -= optind;
  287. argv += optind;
  288. openchannel (&channel);
  289. while (loop--)
  290. {
  291. iterate (argc, argv, &channel, pause);
  292. if (loop)
  293. {
  294. sleep (delay);
  295. }
  296. }
  297. closechannel (&channel);
  298. return (0);
  299. }