en10mb.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2022 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "tcpedit.h"
  22. #include "common.h"
  23. #include "tcpr.h"
  24. #include "dlt_utils.h"
  25. #include "tcpedit_stub.h"
  26. #include "../ethernet.h"
  27. #include "en10mb.h"
  28. static char dlt_name[] = "en10mb";
  29. static char dlt_prefix[] = "enet";
  30. static uint16_t dlt_value = DLT_EN10MB;
  31. /*
  32. * Function to register ourselves. This function is always called, regardless
  33. * of what DLT types are being used, so it shouldn't be allocating extra buffers
  34. * or anything like that (use the dlt_en10mb_init() function below for that).
  35. * Tasks:
  36. * - Create a new plugin struct
  37. * - Fill out the provides/requires bit masks. Note: Only specify which fields are
  38. * actually in the header.
  39. * - Add the plugin to the context's plugin chain
  40. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  41. */
  42. int
  43. dlt_en10mb_register(tcpeditdlt_t *ctx)
  44. {
  45. tcpeditdlt_plugin_t *plugin;
  46. assert(ctx);
  47. /* create a new plugin structure */
  48. plugin = tcpedit_dlt_newplugin();
  49. /* set what we provide & require */
  50. plugin->provides += PLUGIN_MASK_PROTO + PLUGIN_MASK_SRCADDR + PLUGIN_MASK_DSTADDR;
  51. plugin->requires += PLUGIN_MASK_PROTO + PLUGIN_MASK_SRCADDR + PLUGIN_MASK_DSTADDR;
  52. /* what is our dlt type? */
  53. plugin->dlt = dlt_value;
  54. /* set the prefix name of our plugin. This is also used as the prefix for our options */
  55. plugin->name = safe_strdup(dlt_prefix);
  56. /*
  57. * Point to our functions, note, you need a function for EVERY method.
  58. * Even if it is only an empty stub returning success.
  59. */
  60. plugin->plugin_init = dlt_en10mb_init;
  61. plugin->plugin_cleanup = dlt_en10mb_cleanup;
  62. plugin->plugin_parse_opts = dlt_en10mb_parse_opts;
  63. plugin->plugin_decode = dlt_en10mb_decode;
  64. plugin->plugin_encode = dlt_en10mb_encode;
  65. plugin->plugin_proto = dlt_en10mb_proto;
  66. plugin->plugin_l2addr_type = dlt_en10mb_l2addr_type;
  67. plugin->plugin_l2len = dlt_en10mb_l2len;
  68. plugin->plugin_get_layer3 = dlt_en10mb_get_layer3;
  69. plugin->plugin_merge_layer3 = dlt_en10mb_merge_layer3;
  70. plugin->plugin_get_mac = dlt_en10mb_get_mac;
  71. /* add it to the available plugin list */
  72. return tcpedit_dlt_addplugin(ctx, plugin);
  73. }
  74. /*
  75. * Initializer function. This function is called only once, if and only if
  76. * this plugin will be utilized. Remember, if you need to keep track of any state,
  77. * store it in your plugin->config, not a global!
  78. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  79. */
  80. int
  81. dlt_en10mb_init(tcpeditdlt_t *ctx)
  82. {
  83. tcpeditdlt_plugin_t *plugin;
  84. en10mb_config_t *config;
  85. assert(ctx);
  86. /* vlan tags need an additional 4 bytes */
  87. if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) {
  88. tcpedit_seterr(ctx->tcpedit, "%s", "Unable to initialize unregistered plugin en10mb");
  89. return TCPEDIT_ERROR;
  90. }
  91. if (ctx->decoded_extra_size > 0) {
  92. if (ctx->decoded_extra_size < sizeof(en10mb_extra_t)) {
  93. ctx->decoded_extra_size = sizeof(en10mb_extra_t);
  94. ctx->decoded_extra = safe_realloc(ctx->decoded_extra,
  95. ctx->decoded_extra_size);
  96. }
  97. } else {
  98. ctx->decoded_extra_size = sizeof(en10mb_extra_t);
  99. ctx->decoded_extra = safe_malloc(ctx->decoded_extra_size);
  100. }
  101. plugin->config_size = sizeof(en10mb_config_t);
  102. plugin->config = safe_malloc(plugin->config_size);
  103. config = (en10mb_config_t *)plugin->config;
  104. /* init vlan user values to -1 to indicate not set */
  105. config->vlan_tag = 65535;
  106. config->vlan_pri = 255;
  107. config->vlan_cfi = 255;
  108. /* VLAN protocol = 802.1q */
  109. config->vlan_proto = ETHERTYPE_VLAN;
  110. return TCPEDIT_OK; /* success */
  111. }
  112. /*
  113. * Since this is used in a library, we should manually clean up after ourselves
  114. * Unless you allocated some memory in dlt_en10mb_init(), this is just an stub.
  115. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  116. */
  117. int
  118. dlt_en10mb_cleanup(tcpeditdlt_t *ctx)
  119. {
  120. tcpeditdlt_plugin_t *plugin;
  121. assert(ctx);
  122. if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) {
  123. tcpedit_seterr(ctx->tcpedit, "Unable to cleanup unregistered plugin %s",
  124. dlt_name);
  125. return TCPEDIT_ERROR;
  126. }
  127. safe_free(plugin->name);
  128. plugin->name = NULL;
  129. if (plugin->config != NULL) {
  130. en10mb_config_t *config = (en10mb_config_t*)plugin->config;
  131. safe_free(config->subs.entries);
  132. safe_free(plugin->config);
  133. plugin->config = NULL;
  134. plugin->config_size = 0;
  135. }
  136. return TCPEDIT_OK; /* success */
  137. }
  138. int
  139. dlt_en10mb_parse_subsmac_entry(const char *raw, en10mb_sub_entry_t *entry)
  140. {
  141. char *candidate = safe_strdup(raw);
  142. int parse_result = dualmac2hex(candidate, entry->target, entry->rewrite, SUBSMAC_ENTRY_LEN);
  143. free(candidate);
  144. return parse_result;
  145. }
  146. en10mb_sub_entry_t *
  147. dlt_en10mb_realloc_merge(en10mb_sub_conf_t config, en10mb_sub_entry_t *new_entries, int entries_count)
  148. {
  149. int i;
  150. config.entries = safe_realloc(config.entries,
  151. (config.count + entries_count)
  152. * sizeof(en10mb_sub_entry_t));
  153. for (i = 0; i < entries_count; i++) {
  154. config.entries[config.count + i] = new_entries[i];
  155. }
  156. return config.entries;
  157. }
  158. int
  159. dlt_en10mb_parse_subsmac(tcpeditdlt_t *ctx, en10mb_config_t *config, const char *input)
  160. {
  161. int input_len = strlen(input);
  162. int possible_entries_number = (input_len / (SUBSMAC_ENTRY_LEN + 1)) + 1;
  163. int entry = 0;
  164. en10mb_sub_entry_t *entries = safe_malloc(possible_entries_number * sizeof(en10mb_sub_entry_t));
  165. for (entry = 0; entry < possible_entries_number; entry++) {
  166. const int read_offset = entry + entry * SUBSMAC_ENTRY_LEN;
  167. if (input_len - read_offset < SUBSMAC_ENTRY_LEN) {
  168. free(entries);
  169. tcpedit_seterr(ctx->tcpedit, "Unable to parse --enet-subsmac=%s", input);
  170. return TCPEDIT_ERROR;
  171. }
  172. switch(dlt_en10mb_parse_subsmac_entry(input + read_offset, &entries[entry])) {
  173. case 3:
  174. /* Both read; This is what we want */
  175. break;
  176. default:
  177. free(entries);
  178. tcpedit_seterr(ctx->tcpedit, "Unable to parse --enet-subsmac=%s", input);
  179. return TCPEDIT_ERROR;
  180. }
  181. }
  182. config->subs.entries = dlt_en10mb_realloc_merge(config->subs, entries, possible_entries_number);
  183. config->subs.count += possible_entries_number;
  184. free(entries);
  185. return TCPEDIT_OK;
  186. }
  187. /*
  188. * This is where you should define all your AutoGen AutoOpts option parsing.
  189. * Any user specified option should have it's bit turned on in the 'provides'
  190. * bit mask.
  191. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  192. */
  193. int
  194. dlt_en10mb_parse_opts(tcpeditdlt_t *ctx)
  195. {
  196. tcpeditdlt_plugin_t *plugin;
  197. en10mb_config_t *config;
  198. assert(ctx);
  199. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  200. if (!plugin)
  201. return TCPEDIT_ERROR;
  202. config = (en10mb_config_t *)plugin->config;
  203. if (plugin->config_size < sizeof(*config))
  204. return TCPEDIT_ERROR;
  205. /* --subsmacs */
  206. if (HAVE_OPT(ENET_SUBSMAC)) {
  207. int i, count = STACKCT_OPT(ENET_SUBSMAC);
  208. char **list = (char**) STACKLST_OPT(ENET_SUBSMAC);
  209. for (i = 0; i < count; i++) {
  210. int parse_result = dlt_en10mb_parse_subsmac(ctx, config, list[i]);
  211. if (parse_result == TCPEDIT_ERROR) {
  212. return TCPEDIT_ERROR;
  213. }
  214. }
  215. }
  216. /* --mac-seed */
  217. if (HAVE_OPT(ENET_MAC_SEED)) {
  218. int i,j;
  219. config->random.set = OPT_VALUE_ENET_MAC_SEED;
  220. for (i = 0; i < 6; i++) {
  221. config->random.mask[i] = (u_char)tcpr_random(&config->random.set) % 256;
  222. /* only unique numbers */
  223. for (j = 0; j < i; j++) {
  224. if (config->random.mask[i] == config->random.mask[j]) {
  225. i--;
  226. break;
  227. }
  228. }
  229. }
  230. if (HAVE_OPT(ENET_MAC_SEED_KEEP_BYTES)) {
  231. config->random.keep = OPT_VALUE_ENET_MAC_SEED_KEEP_BYTES;
  232. }
  233. }
  234. /* --dmac */
  235. if (HAVE_OPT(ENET_DMAC)) {
  236. int macparse;
  237. macparse = dualmac2hex(OPT_ARG(ENET_DMAC), config->intf1_dmac,
  238. config->intf2_dmac, strlen(OPT_ARG(ENET_DMAC)));
  239. switch (macparse) {
  240. case 1:
  241. config->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  242. break;
  243. case 2:
  244. config->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  245. break;
  246. case 3:
  247. config->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  248. config->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  249. break;
  250. case 0:
  251. /* nothing to do */
  252. break;
  253. default:
  254. tcpedit_seterr(ctx->tcpedit,
  255. "Unable to parse --enet-dmac=%s", OPT_ARG(ENET_DMAC));
  256. return TCPEDIT_ERROR;
  257. break;
  258. }
  259. plugin->requires -= PLUGIN_MASK_DSTADDR;
  260. }
  261. /* --smac */
  262. if (HAVE_OPT(ENET_SMAC)) {
  263. int macparse;
  264. macparse = dualmac2hex(OPT_ARG(ENET_SMAC), config->intf1_smac,
  265. config->intf2_smac, strlen(OPT_ARG(ENET_SMAC)));
  266. switch (macparse) {
  267. case 1:
  268. config->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  269. break;
  270. case 2:
  271. config->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  272. break;
  273. case 3:
  274. config->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  275. config->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  276. break;
  277. case 0:
  278. /* nothing to do */
  279. break;
  280. default:
  281. tcpedit_seterr(ctx->tcpedit,
  282. "Unable to parse --enet-smac=%s", OPT_ARG(ENET_SMAC));
  283. return TCPEDIT_ERROR;
  284. break;
  285. }
  286. plugin->requires -= PLUGIN_MASK_SRCADDR;
  287. }
  288. /*
  289. * Validate 802.1q vlan args and populate tcpedit->vlan_record
  290. */
  291. if (HAVE_OPT(ENET_VLAN)) {
  292. if (strcmp(OPT_ARG(ENET_VLAN), "add") == 0) { /* add or change */
  293. config->vlan = TCPEDIT_VLAN_ADD;
  294. } else if (strcmp(OPT_ARG(ENET_VLAN), "del") == 0) {
  295. config->vlan = TCPEDIT_VLAN_DEL;
  296. } else {
  297. tcpedit_seterr(ctx->tcpedit, "Invalid --enet-vlan=%s", OPT_ARG(ENET_VLAN));
  298. return -1;
  299. }
  300. if (config->vlan != TCPEDIT_VLAN_OFF) {
  301. if (config->vlan == TCPEDIT_VLAN_ADD) {
  302. if (! HAVE_OPT(ENET_VLAN_TAG)) {
  303. tcpedit_seterr(ctx->tcpedit, "%s",
  304. "Must specify a new 802.1 VLAN tag if vlan "
  305. "mode is add");
  306. return TCPEDIT_ERROR;
  307. }
  308. /*
  309. * fill out the 802.1q header
  310. */
  311. config->vlan_tag = OPT_VALUE_ENET_VLAN_TAG;
  312. dbgx(1, "We will %s 802.1q headers",
  313. config->vlan == TCPEDIT_VLAN_DEL ? "delete" : "add/modify");
  314. if (HAVE_OPT(ENET_VLAN_PRI))
  315. config->vlan_pri = OPT_VALUE_ENET_VLAN_PRI;
  316. if (HAVE_OPT(ENET_VLAN_CFI))
  317. config->vlan_cfi = OPT_VALUE_ENET_VLAN_CFI;
  318. }
  319. if (HAVE_OPT(ENET_VLAN_PROTO)) {
  320. if (strcasecmp(OPT_ARG(ENET_VLAN_PROTO), "802.1q") == 0) {
  321. config->vlan_proto = ETHERTYPE_VLAN;
  322. } else if (strcasecmp(OPT_ARG(ENET_VLAN_PROTO), "802.1ad") == 0) {
  323. config->vlan_proto = ETHERTYPE_Q_IN_Q;
  324. } else {
  325. tcpedit_seterr(ctx->tcpedit, "VLAN protocol \"%s\" is invalid",
  326. OPT_ARG(ENET_VLAN_PROTO));
  327. return TCPEDIT_ERROR;
  328. }
  329. }
  330. }
  331. }
  332. return TCPEDIT_OK; /* success */
  333. }
  334. /*
  335. * Function to decode the layer 2 header in the packet
  336. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  337. */
  338. int
  339. dlt_en10mb_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  340. {
  341. struct tcpr_ethernet_hdr *eth_hdr;
  342. uint32_t pkt_len = pktlen;
  343. en10mb_extra_t *extra;
  344. uint32_t vlan_offset;
  345. uint16_t protcol;
  346. uint32_t l2offset;
  347. uint32_t l2len;
  348. int res;
  349. assert(ctx);
  350. assert(packet);
  351. extra = (en10mb_extra_t *)ctx->decoded_extra;
  352. if (ctx->decoded_extra_size < sizeof(*extra)) {
  353. tcpedit_seterr(ctx->tcpedit, "Decode extra size too short! %d < %u",
  354. ctx->decoded_extra_size, sizeof(*extra));
  355. return TCPEDIT_ERROR;
  356. }
  357. res = get_l2len_protocol(packet,
  358. pkt_len,
  359. dlt_value,
  360. &protcol,
  361. &l2len,
  362. &l2offset,
  363. &vlan_offset);
  364. if (res == -1)
  365. return TCPEDIT_ERROR;
  366. if (pkt_len < TCPR_802_3_H + l2offset)
  367. return TCPEDIT_ERROR;
  368. eth_hdr = (struct tcpr_ethernet_hdr*)(packet + l2offset);
  369. protcol = ntohs(eth_hdr->ether_type);
  370. memcpy(&(ctx->dstaddr.ethernet), eth_hdr, ETHER_ADDR_LEN);
  371. memcpy(&(ctx->srcaddr.ethernet), &(eth_hdr->ether_shost), ETHER_ADDR_LEN);
  372. ctx->proto_vlan_tag = ntohs(eth_hdr->ether_type);
  373. if (vlan_offset != 0) {
  374. if (vlan_offset == l2offset + sizeof(*eth_hdr)) {
  375. vlan_hdr_t *vlan_hdr;
  376. vlan_hdr = (vlan_hdr_t*)(packet + vlan_offset);
  377. if (pkt_len < vlan_offset + sizeof(*vlan_hdr)) {
  378. tcpedit_seterr(ctx->tcpedit,
  379. "Frame is too short for VLAN headers! %d < %d",
  380. pktlen,
  381. vlan_offset + sizeof(*vlan_hdr));
  382. return TCPEDIT_ERROR;
  383. }
  384. extra->vlan = 1;
  385. extra->vlan_offset = vlan_offset;
  386. extra->vlan_proto = ntohs(vlan_hdr->vlan_tpid);
  387. extra->vlan_tag = htons(vlan_hdr->vlan_tci) & TCPR_802_1Q_VIDMASK;
  388. extra->vlan_pri = htons(vlan_hdr->vlan_tci) & TCPR_802_1Q_PRIMASK;
  389. extra->vlan_cfi = htons(vlan_hdr->vlan_tci) & TCPR_802_1Q_CFIMASK;
  390. } else {
  391. /* VLAN headers cannot be after MPLS. There are other protocols such
  392. * Cisco Metatdata that could be before VLAN, but we don't support
  393. * them yet.
  394. */
  395. return TCPEDIT_ERROR;
  396. }
  397. } else {
  398. extra->vlan = 0;
  399. extra->vlan_offset = l2offset + sizeof(*eth_hdr);
  400. extra->vlan_proto = protcol;
  401. }
  402. ctx->proto = ntohs(protcol);
  403. ctx->l2offset = l2offset;
  404. ctx->l2len = l2len;
  405. return TCPEDIT_OK; /* success */
  406. }
  407. /*
  408. * Function to encode the layer 2 header back into the packet.
  409. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  410. */
  411. int
  412. dlt_en10mb_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, tcpr_dir_t dir)
  413. {
  414. struct tcpr_802_1q_hdr *vlan_hdr;
  415. struct tcpr_ethernet_hdr *eth;
  416. tcpeditdlt_plugin_t *plugin;
  417. en10mb_config_t *config;
  418. en10mb_extra_t *extra;
  419. int newl2len = 0;
  420. int oldl2len = 0;
  421. assert(ctx);
  422. assert(packet);
  423. if (pktlen < TCPR_802_3_H) {
  424. tcpedit_seterr(ctx->tcpedit,
  425. "Unable to process packet #" COUNTER_SPEC " since it is less then 14 bytes.",
  426. ctx->tcpedit->runtime.packetnum);
  427. return TCPEDIT_ERROR;
  428. }
  429. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  430. if (!plugin)
  431. return TCPEDIT_ERROR;
  432. config = plugin->config;
  433. if (plugin->config_size < sizeof(*config))
  434. return TCPEDIT_ERROR;
  435. extra = (en10mb_extra_t *)ctx->decoded_extra;
  436. if (ctx->decoded_extra_size < sizeof(*extra))
  437. return TCPEDIT_ERROR;
  438. /* figure out the new layer2 length, first for the case: ethernet -> ethernet? */
  439. if (ctx->decoder->dlt == dlt_value) {
  440. switch (config->vlan) {
  441. case TCPEDIT_VLAN_ADD:
  442. oldl2len = extra->vlan_offset;
  443. newl2len = extra->vlan_offset + sizeof(vlan_hdr_t);
  444. break;
  445. case TCPEDIT_VLAN_DEL:
  446. if (extra->vlan) {
  447. oldl2len = extra->vlan_offset + sizeof(vlan_hdr_t);
  448. newl2len = extra->vlan_offset;
  449. }
  450. break;
  451. case TCPEDIT_VLAN_OFF:
  452. if (extra->vlan) {
  453. oldl2len = extra->vlan_offset;
  454. newl2len = extra->vlan_offset;
  455. }
  456. break;
  457. }
  458. }
  459. /* newl2len for some other DLT -> ethernet */
  460. else if (config->vlan == TCPEDIT_VLAN_ADD) {
  461. /* if add a vlan then 18, */
  462. newl2len = TCPR_802_1Q_H;
  463. }
  464. if (pktlen < newl2len || pktlen + newl2len - ctx->l2len > MAXPACKET) {
  465. tcpedit_seterr(ctx->tcpedit,
  466. "Unable to process packet #" COUNTER_SPEC " since its new length is %d bytes.",
  467. ctx->tcpedit->runtime.packetnum, newl2len);
  468. return TCPEDIT_ERROR;
  469. }
  470. if (pktlen < ctx->l2len) {
  471. tcpedit_seterr(ctx->tcpedit,
  472. "Unable to process packet #" COUNTER_SPEC " since its new length less then %d L2 bytes.",
  473. ctx->tcpedit->runtime.packetnum, ctx->l2len);
  474. return TCPEDIT_ERROR;
  475. }
  476. /* Make space for our new L2 header */
  477. if (newl2len > 0 && newl2len != oldl2len) {
  478. if (pktlen + (newl2len - oldl2len) > MAXPACKET) {
  479. tcpedit_seterr(ctx->tcpedit, "New frame too big, new length %d exceeds %d",
  480. pktlen + (newl2len - ctx->l2len), MAXPACKET);
  481. return TCPEDIT_ERROR;
  482. }
  483. memmove(packet + newl2len, packet + oldl2len, pktlen - oldl2len);
  484. }
  485. /* update the total packet length */
  486. pktlen += newl2len - oldl2len;
  487. ctx->l2len += newl2len - oldl2len;
  488. /* set the src & dst address as the first 12 bytes */
  489. eth = (struct tcpr_ethernet_hdr *)(packet + ctx->l2offset);
  490. if (dir == TCPR_DIR_C2S) {
  491. /* copy user supplied SRC MAC if provided or from original packet */
  492. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC1) {
  493. if ((ctx->addr_type == ETHERNET &&
  494. ((ctx->skip_broadcast &&
  495. is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  496. || ctx->addr_type != ETHERNET) {
  497. memcpy(eth->ether_shost, config->intf1_smac, ETHER_ADDR_LEN);
  498. } else {
  499. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  500. }
  501. } else if (ctx->addr_type == ETHERNET) {
  502. extra->src_modified = memcmp(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  503. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  504. } else {
  505. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  506. return TCPEDIT_ERROR;
  507. }
  508. /* copy user supplied DMAC MAC if provided or from original packet */
  509. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC1) {
  510. if ((ctx->addr_type == ETHERNET &&
  511. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  512. || ctx->addr_type != ETHERNET) {
  513. memcpy(eth->ether_dhost, config->intf1_dmac, ETHER_ADDR_LEN);
  514. } else {
  515. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  516. }
  517. } else if (ctx->addr_type == ETHERNET) {
  518. extra->dst_modified = memcmp(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  519. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  520. } else {
  521. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  522. return TCPEDIT_ERROR;
  523. }
  524. } else if (dir == TCPR_DIR_S2C) {
  525. /* copy user supplied SRC MAC if provided or from original packet */
  526. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC2) {
  527. if ((ctx->addr_type == ETHERNET &&
  528. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  529. || ctx->addr_type != ETHERNET) {
  530. memcpy(eth->ether_shost, config->intf2_smac, ETHER_ADDR_LEN);
  531. } else {
  532. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  533. }
  534. } else if (ctx->addr_type == ETHERNET) {
  535. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  536. } else {
  537. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  538. return TCPEDIT_ERROR;
  539. }
  540. /* copy user supplied DMAC MAC if provided or from original packet */
  541. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC2) {
  542. if ((ctx->addr_type == ETHERNET &&
  543. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  544. || ctx->addr_type != ETHERNET) {
  545. memcpy(eth->ether_dhost, config->intf2_dmac, ETHER_ADDR_LEN);
  546. } else {
  547. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  548. }
  549. } else if (ctx->addr_type == ETHERNET) {
  550. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  551. } else {
  552. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  553. return TCPEDIT_ERROR;
  554. }
  555. } else {
  556. tcpedit_seterr(ctx->tcpedit, "%s", "Encoders only support C2S or C2S!");
  557. return TCPEDIT_ERROR;
  558. }
  559. if (config->subs.entries) {
  560. int entry = 0;
  561. for (entry = 0 ; entry < config->subs.count; entry++) {
  562. en10mb_sub_entry_t *current = &config->subs.entries[entry];
  563. if (!memcmp(eth->ether_dhost, current->target, ETHER_ADDR_LEN)) {
  564. memcpy(eth->ether_dhost, current->rewrite, ETHER_ADDR_LEN);
  565. }
  566. if (!memcmp(eth->ether_shost, current->target, ETHER_ADDR_LEN)) {
  567. memcpy(eth->ether_shost, current->rewrite, ETHER_ADDR_LEN);
  568. }
  569. }
  570. }
  571. if (config->random.set) {
  572. int unicast_src = is_unicast_ethernet(ctx, eth->ether_shost);
  573. int unicast_dst = is_unicast_ethernet(ctx, eth->ether_dhost);
  574. int i = config->random.keep;
  575. for ( ; i < ETHER_ADDR_LEN; i++) {
  576. eth->ether_shost[i] = MAC_MASK_APPLY(eth->ether_shost[i], config->random.mask[i], unicast_src);
  577. eth->ether_dhost[i] = MAC_MASK_APPLY(eth->ether_dhost[i], config->random.mask[i], unicast_dst);
  578. }
  579. /* avoid making unicast packets multicast */
  580. if (!config->random.keep) {
  581. eth->ether_shost[0] &= ~(0x01 * unicast_src);
  582. eth->ether_dhost[0] &= ~(0x01 * unicast_dst);
  583. }
  584. }
  585. if (config->vlan == TCPEDIT_VLAN_ADD
  586. || (config->vlan == TCPEDIT_VLAN_OFF && extra->vlan)) {
  587. vlan_hdr = (struct tcpr_802_1q_hdr *)(packet + extra->vlan_offset);
  588. if (config->vlan == TCPEDIT_VLAN_ADD) {
  589. struct tcpr_ethernet_hdr *eth_hdr;
  590. eth_hdr = (struct tcpr_ethernet_hdr*)(packet + ctx->l2offset);
  591. eth_hdr->ether_type = htons(config->vlan_proto);
  592. vlan_hdr->vlan_tpid = htons(ctx->proto_vlan_tag);
  593. }
  594. /* are we changing VLAN info? */
  595. if (config->vlan_tag < 65535) {
  596. vlan_hdr->vlan_tci =
  597. htons((uint16_t)config->vlan_tag & TCPR_802_1Q_VIDMASK);
  598. } else if (extra->vlan) {
  599. vlan_hdr->vlan_tci = htons(extra->vlan_tag);
  600. } else {
  601. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-tag");
  602. return TCPEDIT_ERROR;
  603. }
  604. if (config->vlan_pri < 255) {
  605. vlan_hdr->vlan_tci += htons((uint16_t)config->vlan_pri << 13);
  606. } else if (extra->vlan) {
  607. vlan_hdr->vlan_tci += htons(extra->vlan_pri);
  608. } else {
  609. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-pri");
  610. return TCPEDIT_ERROR;
  611. }
  612. if (config->vlan_cfi < 255) {
  613. vlan_hdr->vlan_tci += htons((uint16_t)config->vlan_cfi << 12);
  614. } else if (extra->vlan) {
  615. vlan_hdr->vlan_tci += htons(extra->vlan_cfi);
  616. } else {
  617. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-cfi");
  618. return TCPEDIT_ERROR;
  619. }
  620. } else if (config->vlan == TCPEDIT_VLAN_DEL && newl2len > 0) {
  621. /* all we need for 802.3 is the proto */
  622. eth->ether_type = htons(extra->vlan_proto);
  623. }
  624. return pktlen;
  625. }
  626. /*
  627. * Function returns the Layer 3 protocol type of the given packet, or TCPEDIT_ERROR on error
  628. */
  629. int
  630. dlt_en10mb_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  631. {
  632. uint32_t _U_ vlan_offset;
  633. uint16_t ether_type;
  634. uint32_t _U_ l2offset;
  635. uint32_t _U_ l2len;
  636. int res;
  637. assert(ctx);
  638. assert(packet);
  639. if (pktlen < (int) sizeof(struct tcpr_ethernet_hdr)) {
  640. tcpedit_seterr(ctx->tcpedit, "Ethernet packet length too short: %d",
  641. pktlen);
  642. return TCPEDIT_ERROR;
  643. }
  644. res = get_l2len_protocol(packet,
  645. pktlen,
  646. dlt_value,
  647. &ether_type,
  648. &l2len,
  649. &l2offset,
  650. &vlan_offset);
  651. if (res == -1)
  652. return TCPEDIT_ERROR;
  653. return htons(ether_type);
  654. }
  655. /*
  656. * Function returns a pointer to the layer 3 protocol header or NULL on error
  657. */
  658. u_char *
  659. dlt_en10mb_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen)
  660. {
  661. int l2len;
  662. assert(ctx);
  663. assert(packet);
  664. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  665. if (l2len == -1 || pktlen < l2len)
  666. return NULL;
  667. return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len);
  668. }
  669. /*
  670. * Modify MAC address if IPv4 address is Multicast (#563)
  671. * ip: 32-bit IP address in network order
  672. * mac: pointer to packet ethernet source or destination address (6 bytes)
  673. */
  674. static void dlt_en10mb_ipv4_multicast_mac_update(const uint32_t ip,
  675. uint8_t mac[])
  676. {
  677. /* only modify multicast packets */
  678. if ((ntohl(ip) & 0xf0000000) != 0xe0000000)
  679. return;
  680. mac[2] = (ntohl(ip) & 0x7fffff);
  681. mac[0] =0x01;
  682. mac[1] =0x0;
  683. mac[2] =0x5e;
  684. }
  685. /*
  686. * Modify MAC address if IPv4 address is Multicast (#563)
  687. * ip6: 128-bit IPv6 address in network order
  688. * mac: pointer to packet ethernet source or destination address (6 bytes)
  689. */
  690. static void dlt_en10mb_ipv6_multicast_mac_update(const struct tcpr_in6_addr *ip6,
  691. uint8_t mac[])
  692. {
  693. /* only modify multicast packets */
  694. if (ip6->tcpr_s6_addr[0] == 0xff)
  695. return;
  696. mac[0] = 0x33;
  697. mac[1] = 0x33;
  698. mac[2] = ip6->tcpr_s6_addr[12];
  699. mac[3] = ip6->tcpr_s6_addr[13];
  700. mac[4] = ip6->tcpr_s6_addr[14];
  701. mac[5] = ip6->tcpr_s6_addr[15];
  702. }
  703. /*
  704. * function merges the packet (containing L2 and old L3) with the l3data buffer
  705. * containing the new l3 data. Note, if L2 % 4 == 0, then they're pointing to the
  706. * same buffer, otherwise there was a memcpy involved on strictly aligned architectures
  707. * like SPARC
  708. */
  709. u_char *
  710. dlt_en10mb_merge_layer3(tcpeditdlt_t *ctx,
  711. u_char *packet,
  712. const int pktlen,
  713. u_char *ipv4_data,
  714. u_char *ipv6_data)
  715. {
  716. en10mb_extra_t *extra;
  717. struct tcpr_ethernet_hdr *eth;
  718. int l2len;
  719. assert(ctx);
  720. assert(packet);
  721. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  722. if (l2len == -1 || pktlen < l2len)
  723. return NULL;
  724. assert(ctx->decoded_extra_size == sizeof(*extra));
  725. extra = (en10mb_extra_t *)ctx->decoded_extra;
  726. eth = (struct tcpr_ethernet_hdr *)(packet + ctx->l2offset);
  727. assert(eth);
  728. /* modify source/destination MAC if source/destination IP is multicast */
  729. if (ipv4_data) {
  730. if ((size_t)pktlen >= sizeof(*eth) + sizeof(struct tcpr_ipv4_hdr)) {
  731. struct tcpr_ipv4_hdr *ip_hdr = (struct tcpr_ipv4_hdr*)ipv4_data;
  732. if (!extra->src_modified)
  733. dlt_en10mb_ipv4_multicast_mac_update(ip_hdr->ip_src.s_addr,
  734. eth->ether_shost);
  735. if (!extra->dst_modified)
  736. dlt_en10mb_ipv4_multicast_mac_update(ip_hdr->ip_dst.s_addr,
  737. eth->ether_dhost);
  738. }
  739. return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, ipv4_data, l2len);
  740. } else if (ipv6_data) {
  741. if ((size_t)pktlen >= sizeof(*eth) + sizeof(struct tcpr_ipv6_hdr)) {
  742. struct tcpr_ipv6_hdr *ip6_hdr = (struct tcpr_ipv6_hdr*)ipv6_data;
  743. if (!extra->src_modified)
  744. dlt_en10mb_ipv6_multicast_mac_update(&ip6_hdr->ip_src,
  745. eth->ether_shost);
  746. if (!extra->dst_modified)
  747. dlt_en10mb_ipv6_multicast_mac_update(&ip6_hdr->ip_dst,
  748. eth->ether_dhost);
  749. }
  750. return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, ipv6_data, l2len);
  751. }
  752. return NULL;
  753. }
  754. /*
  755. * return a static pointer to the source/destination MAC address
  756. * return NULL on error/address doesn't exist
  757. */
  758. u_char *
  759. dlt_en10mb_get_mac(tcpeditdlt_t *ctx, tcpeditdlt_mac_type_t mac, const u_char *packet, const int pktlen)
  760. {
  761. assert(ctx);
  762. assert(packet);
  763. if (pktlen < 14)
  764. return NULL;
  765. /* FIXME: return a ptr to the source or dest mac address. */
  766. switch(mac) {
  767. case SRC_MAC:
  768. memcpy(ctx->srcmac, &packet[6], ETHER_ADDR_LEN);
  769. return(ctx->srcmac);
  770. break;
  771. case DST_MAC:
  772. memcpy(ctx->dstmac, packet, ETHER_ADDR_LEN);
  773. return(ctx->dstmac);
  774. break;
  775. default:
  776. errx(1, "Invalid tcpeditdlt_mac_type_t: %d", mac);
  777. }
  778. return(NULL);
  779. }
  780. /*
  781. * return the length of the L2 header of the current packet
  782. */
  783. int
  784. dlt_en10mb_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  785. {
  786. int l2len;
  787. assert(ctx);
  788. assert(packet);
  789. if (pktlen < (int)sizeof(eth_hdr_t)) {
  790. tcpedit_seterr(ctx->tcpedit, "dlt_en10mb_l2len: pktlen=%u is less than size of Ethernet header",
  791. pktlen);
  792. return TCPEDIT_ERROR;
  793. }
  794. l2len = get_l2len(packet, pktlen, dlt_value);
  795. if (l2len > 0) {
  796. if (pktlen < l2len) {
  797. /* can happen if fuzzing is enabled */
  798. tcpedit_seterr(ctx->tcpedit, "dlt_en10mb_l2len: pktlen=%u is less than l2len=%u",
  799. pktlen, l2len);
  800. return TCPEDIT_ERROR;
  801. }
  802. return l2len;
  803. }
  804. tcpedit_seterr(ctx->tcpedit, "dlt_en10mb_l2len: %s", "Whoops! Bug in my code!");
  805. return TCPEDIT_ERROR;
  806. }
  807. tcpeditdlt_l2addr_type_t
  808. dlt_en10mb_l2addr_type(void)
  809. {
  810. return ETHERNET;
  811. }