parse_args.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /* $Id: parse_args.c 1572 2006-08-05 20:24:28Z aturner $ */
  2. /*
  3. * Copyright (c) 2006 Aaron Turner.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include "defines.h"
  33. #include "common.h"
  34. #include "tcpedit.h"
  35. #include "tcpedit_stub.h"
  36. #include "../mac.h"
  37. #include "parse_args.h"
  38. #include "portmap.h"
  39. #include <string.h>
  40. /*
  41. * returns 0 for sucess w/o errors
  42. * returns 1 for sucess w/ warnings
  43. * returns -1 for error
  44. */
  45. int
  46. tcpedit_post_args(tcpedit_t **tcpedit_ex) {
  47. tcpedit_t *tcpedit;
  48. int rcode = 0;
  49. assert(tcpedit_ex);
  50. tcpedit = *tcpedit_ex;
  51. assert(tcpedit);
  52. /* --dmac */
  53. if (HAVE_OPT(DMAC)) {
  54. int macparse;
  55. macparse = dualmac2hex(OPT_ARG(DMAC), tcpedit->intf1_dmac,
  56. tcpedit->intf2_dmac, strlen(OPT_ARG(DMAC)));
  57. switch (macparse) {
  58. case 1:
  59. tcpedit->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  60. break;
  61. case 2:
  62. tcpedit->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  63. break;
  64. case 3:
  65. tcpedit->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  66. tcpedit->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  67. break;
  68. case 0:
  69. /* nothing to do */
  70. break;
  71. default:
  72. tcpedit_seterr(tcpedit,
  73. "Unable to parse --dmac=%s", OPT_ARG(DMAC));
  74. return -1;
  75. break;
  76. }
  77. }
  78. /* --smac */
  79. if (HAVE_OPT(SMAC)) {
  80. int macparse;
  81. macparse = dualmac2hex(OPT_ARG(SMAC), tcpedit->intf1_smac,
  82. tcpedit->intf2_smac, strlen(OPT_ARG(SMAC)));
  83. switch (macparse) {
  84. case 1:
  85. tcpedit->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  86. break;
  87. case 2:
  88. tcpedit->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  89. break;
  90. case 3:
  91. tcpedit->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  92. tcpedit->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  93. break;
  94. case 0:
  95. /* nothing to do */
  96. break;
  97. default:
  98. tcpedit_seterr(tcpedit,
  99. "Unable to parse --smac=%s", OPT_ARG(SMAC));
  100. return -1;
  101. break;
  102. }
  103. }
  104. /* --dlink */
  105. if (HAVE_OPT(DLINK)) {
  106. int ct = STACKCT_OPT(DLINK);
  107. char **list = STACKLST_OPT(DLINK);
  108. int first = 1;
  109. tcpedit->l2.enabled = 1;
  110. tcpedit->l2.dlt = DLT_USER;
  111. do {
  112. char *p = *list++;
  113. if (first) {
  114. tcpedit->l2.len = read_hexstring(p, tcpedit->l2.data1,
  115. L2DATALEN);
  116. memcpy(tcpedit->l2.data2, tcpedit->l2.data1, tcpedit->l2.len);
  117. } else {
  118. if (tcpedit->l2.len != read_hexstring(p, tcpedit->l2.data2,
  119. L2DATALEN)) {
  120. tcpedit_seterr(tcpedit,
  121. "both --dlink's must contain the same number of bytes");
  122. return -1;
  123. }
  124. }
  125. first = 0;
  126. } while (--ct > 0);
  127. }
  128. /* --pnat */
  129. if (HAVE_OPT(PNAT)) {
  130. int ct = STACKCT_OPT(PNAT);
  131. char **list = STACKLST_OPT(PNAT);
  132. int first = 1;
  133. tcpedit->rewrite_ip ++;
  134. do {
  135. char *p = *list++;
  136. if (first) {
  137. if (! parse_cidr_map(&tcpedit->cidrmap1, p)) {
  138. tcpedit_seterr(tcpedit,
  139. "Unable to parse first --pnat=%s", p);
  140. return -1;
  141. }
  142. } else {
  143. if (! parse_cidr_map(&tcpedit->cidrmap2, p)) {
  144. tcpedit_seterr(tcpedit,
  145. "Unable to parse second --pnat=%s", p);
  146. return -1;
  147. }
  148. }
  149. first = 0;
  150. } while (--ct > 0);
  151. }
  152. /*
  153. * If we have one and only one -N, then use the same map data
  154. * for both interfaces/files
  155. */
  156. if ((tcpedit->cidrmap1 != NULL) && (tcpedit->cidrmap2 == NULL))
  157. tcpedit->cidrmap2 = tcpedit->cidrmap1;
  158. /* --fixcsum */
  159. if (HAVE_OPT(FIXCSUM))
  160. tcpedit->fixcsum = 1;
  161. #ifdef ENABLE_EFCS
  162. /* --efcs */
  163. if (HAVE_OPT(EFCS))
  164. tcpedit->efcs = 1;
  165. #endif
  166. /* --mtu */
  167. if (HAVE_OPT(MTU))
  168. tcpedit->mtu = OPT_VALUE_MTU;
  169. /* --skipbroadcast */
  170. if (HAVE_OPT(SKIPBROADCAST))
  171. tcpedit->skip_broadcast = 1;
  172. /* --fixlen */
  173. if (HAVE_OPT(FIXLEN)) {
  174. if (strcmp(OPT_ARG(FIXLEN), "pad") == 0) {
  175. tcpedit->fixlen = TCPEDIT_FIXLEN_PAD;
  176. } else if (strcmp(OPT_ARG(FIXLEN), "trunc") == 0) {
  177. tcpedit->fixlen = TCPEDIT_FIXLEN_TRUNC;
  178. } else if (strcmp(OPT_ARG(FIXLEN), "del") == 0) {
  179. tcpedit->fixlen = TCPEDIT_FIXLEN_DEL;
  180. } else {
  181. tcpedit_seterr(tcpedit, "Invalid --fixlen=%s", OPT_ARG(FIXLEN));
  182. return -1;
  183. }
  184. }
  185. /* Layer two protocol */
  186. if (HAVE_OPT(PROTO))
  187. tcpedit->l2proto = OPT_VALUE_PROTO;
  188. /* TCP/UDP port rewriting */
  189. if (HAVE_OPT(PORTMAP)) {
  190. if (! parse_portmap(&tcpedit->portmap, OPT_ARG(PORTMAP))) {
  191. tcpedit_seterr(tcpedit,
  192. "Unable to parse --portmap=%s", OPT_ARG(PORTMAP));
  193. return -1;
  194. }
  195. }
  196. /*
  197. * IP address rewriting processing. Call srandom() then add up
  198. * 5 calls to random() as our mixer for randomizing. This should
  199. * work better since most people aren't going to write out values
  200. * close to 32bit integers.
  201. */
  202. if (HAVE_OPT(SEED)) {
  203. tcpedit->rewrite_ip = TCPEDIT_REWRITE_IP_ON;
  204. srandom(OPT_VALUE_SEED);
  205. tcpedit->seed = random() + random() + random() + random() + random();
  206. }
  207. if (HAVE_OPT(ENDPOINTS)) {
  208. tcpedit->rewrite_ip = TCPEDIT_REWRITE_IP_ON;
  209. if (! parse_endpoints(&tcpedit->cidrmap1, &tcpedit->cidrmap2,
  210. OPT_ARG(ENDPOINTS))) {
  211. tcpedit_seterr(tcpedit,
  212. "Unable to parse --endpoints=%s", OPT_ARG(ENDPOINTS));
  213. return -1;
  214. }
  215. }
  216. /*
  217. * Validate 802.1q vlan args and populate tcpedit->vlan_record
  218. */
  219. if (HAVE_OPT(VLAN)) {
  220. if (strcmp(OPT_ARG(VLAN), "add") == 0) {
  221. tcpedit->vlan = TCPEDIT_VLAN_ADD;
  222. } else if (strcmp(OPT_ARG(VLAN), "del") == 0) {
  223. tcpedit->vlan = TCPEDIT_VLAN_DEL;
  224. } else {
  225. tcpedit_seterr(tcpedit, "Invalid --vlan=%s", OPT_ARG(VLAN));
  226. return -1;
  227. }
  228. if (tcpedit->vlan != TCPEDIT_VLAN_OFF) {
  229. tcpedit->l2.dlt = DLT_VLAN;
  230. if (tcpedit->vlan == TCPEDIT_VLAN_ADD) {
  231. if (! HAVE_OPT(VLAN_TAG)) {
  232. tcpedit_seterr(tcpedit,
  233. "Must specify a new 802.1 VLAN tag if vlan "
  234. "mode is add");
  235. return -1;
  236. }
  237. /*
  238. * fill out the 802.1q header
  239. */
  240. tcpedit->l2.vlan_tag = OPT_VALUE_VLAN_TAG;
  241. /* if TCPEDIT_VLAN_ADD then 802.1q header, else 802.3 header len */
  242. tcpedit->l2.len = tcpedit->vlan == TCPEDIT_VLAN_ADD ? TCPR_802_1Q_H : TCPR_ETH_H;
  243. dbgx(1, "We will %s 802.1q headers",
  244. tcpedit->vlan == TCPEDIT_VLAN_DEL ? "delete" :
  245. "add/modify");
  246. if (HAVE_OPT(VLAN_PRI))
  247. tcpedit->l2.vlan_pri = OPT_VALUE_VLAN_PRI;
  248. if (HAVE_OPT(VLAN_CFI))
  249. tcpedit->l2.vlan_cfi = OPT_VALUE_VLAN_CFI;
  250. }
  251. }
  252. }
  253. /*
  254. * figure out the max packet len
  255. */
  256. if (tcpedit->l2.enabled) {
  257. /* custom l2 header */
  258. dbg(1, "Using custom L2 header to calculate max frame size\n");
  259. tcpedit->maxpacket = tcpedit->mtu + tcpedit->l2.len;
  260. }
  261. else if (tcpedit->l2.dlt == DLT_EN10MB || tcpedit->l2.dlt == DLT_VLAN) {
  262. /* ethernet */
  263. dbg(1, "Using Ethernet to calculate max frame size\n");
  264. tcpedit->maxpacket = tcpedit->mtu + TCPR_ETH_H;
  265. } else {
  266. /*
  267. * uh, wtf is this now? we'll just assume ethernet and hope things
  268. * work
  269. */
  270. tcpedit->maxpacket = tcpedit->mtu + TCPR_ETH_H;
  271. tcpedit_seterr(tcpedit,
  272. "Unsupported DLT type: %s. We'll just treat it as ethernet.\n"
  273. "You may need to increase the MTU (-t <size>) if you get errors\n",
  274. pcap_datalink_val_to_name(tcpedit->l2.dlt));
  275. rcode = 1;
  276. }
  277. return rcode;
  278. }