en10mb.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /* $Id: en10mb.c 2105 2009-01-07 05:48:32Z aturner $ */
  2. /*
  3. * Copyright (c) 2006-2007 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 <stdlib.h>
  32. #include <string.h>
  33. #include "en10mb.h"
  34. #include "dlt_plugins-int.h"
  35. #include "tcpedit.h"
  36. #include "common.h"
  37. #include "tcpr.h"
  38. #include "dlt_utils.h"
  39. #include "tcpedit_stub.h"
  40. #include "../ethernet.h"
  41. static char _U_ dlt_name[] = "en10mb";
  42. static char dlt_prefix[] = "enet";
  43. static u_int16_t dlt_value = DLT_EN10MB;
  44. /*
  45. * Function to register ourselves. This function is always called, regardless
  46. * of what DLT types are being used, so it shouldn't be allocating extra buffers
  47. * or anything like that (use the dlt_en10mb_init() function below for that).
  48. * Tasks:
  49. * - Create a new plugin struct
  50. * - Fill out the provides/requires bit masks. Note: Only specify which fields are
  51. * actually in the header.
  52. * - Add the plugin to the context's plugin chain
  53. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  54. */
  55. int
  56. dlt_en10mb_register(tcpeditdlt_t *ctx)
  57. {
  58. tcpeditdlt_plugin_t *plugin;
  59. assert(ctx);
  60. /* create a new plugin structure */
  61. plugin = tcpedit_dlt_newplugin();
  62. /* set what we provide & require */
  63. plugin->provides += PLUGIN_MASK_PROTO + PLUGIN_MASK_SRCADDR + PLUGIN_MASK_DSTADDR;
  64. plugin->requires += PLUGIN_MASK_PROTO + PLUGIN_MASK_SRCADDR + PLUGIN_MASK_DSTADDR;
  65. /* what is our dlt type? */
  66. plugin->dlt = dlt_value;
  67. /* set the prefix name of our plugin. This is also used as the prefix for our options */
  68. plugin->name = safe_strdup(dlt_prefix);
  69. /*
  70. * Point to our functions, note, you need a function for EVERY method.
  71. * Even if it is only an empty stub returning success.
  72. */
  73. plugin->plugin_init = dlt_en10mb_init;
  74. plugin->plugin_cleanup = dlt_en10mb_cleanup;
  75. plugin->plugin_parse_opts = dlt_en10mb_parse_opts;
  76. plugin->plugin_decode = dlt_en10mb_decode;
  77. plugin->plugin_encode = dlt_en10mb_encode;
  78. plugin->plugin_proto = dlt_en10mb_proto;
  79. plugin->plugin_l2addr_type = dlt_en10mb_l2addr_type;
  80. plugin->plugin_l2len = dlt_en10mb_l2len;
  81. plugin->plugin_get_layer3 = dlt_en10mb_get_layer3;
  82. plugin->plugin_merge_layer3 = dlt_en10mb_merge_layer3;
  83. plugin->plugin_get_mac = dlt_en10mb_get_mac;
  84. /* add it to the available plugin list */
  85. return tcpedit_dlt_addplugin(ctx, plugin);
  86. }
  87. /*
  88. * Initializer function. This function is called only once, if and only iif
  89. * this plugin will be utilized. Remember, if you need to keep track of any state,
  90. * store it in your plugin->config, not a global!
  91. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  92. */
  93. int
  94. dlt_en10mb_init(tcpeditdlt_t *ctx)
  95. {
  96. tcpeditdlt_plugin_t *plugin;
  97. en10mb_config_t *config;
  98. assert(ctx);
  99. /* vlan tags need an additional 4 bytes */
  100. if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) {
  101. tcpedit_seterr(ctx->tcpedit, "%s", "Unable to initalize unregistered plugin en10mb");
  102. return TCPEDIT_ERROR;
  103. }
  104. ctx->decoded_extra = safe_malloc(sizeof(en10mb_extra_t));
  105. plugin->config = safe_malloc(sizeof(en10mb_config_t));
  106. config = (en10mb_config_t *)plugin->config;
  107. /* init vlan user values to -1 to indicate not set */
  108. config->vlan_tag = 65535;
  109. config->vlan_pri = 255;
  110. config->vlan_cfi = 255;
  111. return TCPEDIT_OK; /* success */
  112. }
  113. /*
  114. * Since this is used in a library, we should manually clean up after ourselves
  115. * Unless you allocated some memory in dlt_en10mb_init(), this is just an stub.
  116. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  117. */
  118. int
  119. dlt_en10mb_cleanup(tcpeditdlt_t *ctx)
  120. {
  121. tcpeditdlt_plugin_t *plugin;
  122. assert(ctx);
  123. if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL)
  124. return TCPEDIT_OK;
  125. if (ctx->decoded_extra != NULL) {
  126. safe_free(ctx->decoded_extra);
  127. ctx->decoded_extra = NULL;
  128. }
  129. if (plugin->config != NULL) {
  130. safe_free(plugin->config);
  131. plugin->config = NULL;
  132. }
  133. return TCPEDIT_OK; /* success */
  134. }
  135. /*
  136. * This is where you should define all your AutoGen AutoOpts option parsing.
  137. * Any user specified option should have it's bit turned on in the 'provides'
  138. * bit mask.
  139. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  140. */
  141. int
  142. dlt_en10mb_parse_opts(tcpeditdlt_t *ctx)
  143. {
  144. tcpeditdlt_plugin_t *plugin;
  145. en10mb_config_t *config;
  146. assert(ctx);
  147. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  148. config = (en10mb_config_t *)plugin->config;
  149. /* --dmac */
  150. if (HAVE_OPT(ENET_DMAC)) {
  151. int macparse;
  152. macparse = dualmac2hex(OPT_ARG(ENET_DMAC), config->intf1_dmac,
  153. config->intf2_dmac, strlen(OPT_ARG(ENET_DMAC)));
  154. switch (macparse) {
  155. case 1:
  156. config->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  157. break;
  158. case 2:
  159. config->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  160. break;
  161. case 3:
  162. config->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  163. config->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  164. break;
  165. case 0:
  166. /* nothing to do */
  167. break;
  168. default:
  169. tcpedit_seterr(ctx->tcpedit,
  170. "Unable to parse --enet-dmac=%s", OPT_ARG(ENET_DMAC));
  171. return TCPEDIT_ERROR;
  172. break;
  173. }
  174. plugin->requires -= PLUGIN_MASK_DSTADDR;
  175. }
  176. /* --smac */
  177. if (HAVE_OPT(ENET_SMAC)) {
  178. int macparse;
  179. macparse = dualmac2hex(OPT_ARG(ENET_SMAC), config->intf1_smac,
  180. config->intf2_smac, strlen(OPT_ARG(ENET_SMAC)));
  181. switch (macparse) {
  182. case 1:
  183. config->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  184. break;
  185. case 2:
  186. config->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  187. break;
  188. case 3:
  189. config->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  190. config->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  191. break;
  192. case 0:
  193. /* nothing to do */
  194. break;
  195. default:
  196. tcpedit_seterr(ctx->tcpedit,
  197. "Unable to parse --enet-smac=%s", OPT_ARG(ENET_SMAC));
  198. return TCPEDIT_ERROR;
  199. break;
  200. }
  201. plugin->requires -= PLUGIN_MASK_SRCADDR;
  202. }
  203. /*
  204. * Validate 802.1q vlan args and populate tcpedit->vlan_record
  205. */
  206. if (HAVE_OPT(ENET_VLAN)) {
  207. if (strcmp(OPT_ARG(ENET_VLAN), "add") == 0) { // add or change
  208. config->vlan = TCPEDIT_VLAN_ADD;
  209. } else if (strcmp(OPT_ARG(ENET_VLAN), "del") == 0) {
  210. config->vlan = TCPEDIT_VLAN_DEL;
  211. } else {
  212. tcpedit_seterr(ctx->tcpedit, "Invalid --enet-vlan=%s", OPT_ARG(ENET_VLAN));
  213. return -1;
  214. }
  215. if (config->vlan != TCPEDIT_VLAN_OFF) {
  216. if (config->vlan == TCPEDIT_VLAN_ADD) {
  217. if (! HAVE_OPT(ENET_VLAN_TAG)) {
  218. tcpedit_seterr(ctx->tcpedit, "%s",
  219. "Must specify a new 802.1 VLAN tag if vlan "
  220. "mode is add");
  221. return TCPEDIT_ERROR;
  222. }
  223. /*
  224. * fill out the 802.1q header
  225. */
  226. config->vlan_tag = OPT_VALUE_ENET_VLAN_TAG;
  227. dbgx(1, "We will %s 802.1q headers",
  228. config->vlan == TCPEDIT_VLAN_DEL ? "delete" : "add/modify");
  229. if (HAVE_OPT(ENET_VLAN_PRI))
  230. config->vlan_pri = OPT_VALUE_ENET_VLAN_PRI;
  231. if (HAVE_OPT(ENET_VLAN_CFI))
  232. config->vlan_cfi = OPT_VALUE_ENET_VLAN_CFI;
  233. }
  234. }
  235. }
  236. return TCPEDIT_OK; /* success */
  237. }
  238. /*
  239. * Function to decode the layer 2 header in the packet
  240. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  241. */
  242. int
  243. dlt_en10mb_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  244. {
  245. tcpeditdlt_plugin_t *plugin = NULL;
  246. struct tcpr_ethernet_hdr *eth = NULL;
  247. struct tcpr_802_1q_hdr *vlan = NULL;
  248. en10mb_extra_t *extra = NULL;
  249. en10mb_config_t *config = NULL;
  250. assert(ctx);
  251. assert(packet);
  252. assert(pktlen >= 14);
  253. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  254. config = plugin->config;
  255. /* get our src & dst address */
  256. eth = (struct tcpr_ethernet_hdr *)packet;
  257. memcpy(&(ctx->dstaddr.ethernet), eth, ETHER_ADDR_LEN);
  258. memcpy(&(ctx->srcaddr.ethernet), &(eth->ether_shost), ETHER_ADDR_LEN);
  259. extra = (en10mb_extra_t *)ctx->decoded_extra;
  260. extra->vlan = 0;
  261. /* get the L3 protocol type & L2 len*/
  262. switch (ntohs(eth->ether_type)) {
  263. case ETHERTYPE_VLAN:
  264. vlan = (struct tcpr_802_1q_hdr *)packet;
  265. ctx->proto = vlan->vlan_len;
  266. /* Get VLAN tag info */
  267. extra->vlan = 1;
  268. /* must use these mask values, rather then what's in the tcpr.h since it assumes you're shifting */
  269. extra->vlan_tag = vlan->vlan_priority_c_vid & 0x0FFF;
  270. extra->vlan_pri = vlan->vlan_priority_c_vid & 0xE000;
  271. extra->vlan_cfi = vlan->vlan_priority_c_vid & 0x1000;
  272. ctx->l2len = TCPR_802_1Q_H;
  273. break;
  274. /* we don't properly handle SNAP encoding */
  275. default:
  276. ctx->proto = eth->ether_type;
  277. ctx->l2len = TCPR_802_3_H;
  278. break;
  279. }
  280. return TCPEDIT_OK; /* success */
  281. }
  282. /*
  283. * Function to encode the layer 2 header back into the packet.
  284. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  285. */
  286. int
  287. dlt_en10mb_encode(tcpeditdlt_t *ctx, u_char *packet, int pktlen, tcpr_dir_t dir)
  288. {
  289. tcpeditdlt_plugin_t *plugin = NULL;
  290. struct tcpr_ethernet_hdr *eth = NULL;
  291. struct tcpr_802_1q_hdr *vlan = NULL;
  292. en10mb_config_t *config = NULL;
  293. en10mb_extra_t *extra = NULL;
  294. int newl2len = 0;
  295. assert(ctx);
  296. assert(pktlen >= 14);
  297. assert(packet);
  298. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  299. config = plugin->config;
  300. extra = (en10mb_extra_t *)ctx->decoded_extra;
  301. /* figure out the new layer2 length, first for the case: ethernet -> ethernet? */
  302. if (ctx->decoder->dlt == dlt_value) {
  303. if ((ctx->l2len == TCPR_802_1Q_H && config->vlan == TCPEDIT_VLAN_OFF) ||
  304. (config->vlan == TCPEDIT_VLAN_ADD)) {
  305. newl2len = TCPR_802_1Q_H;
  306. } else if ((ctx->l2len == TCPR_802_3_H && config->vlan == TCPEDIT_VLAN_OFF) ||
  307. (config->vlan == TCPEDIT_VLAN_DEL)) {
  308. newl2len = TCPR_802_3_H;
  309. }
  310. }
  311. /* newl2len for some other DLT -> ethernet */
  312. else {
  313. /* if add a vlan then 18, else 14 bytes */
  314. newl2len = config->vlan == TCPEDIT_VLAN_ADD ? TCPR_802_1Q_H : TCPR_802_3_H;
  315. }
  316. /* Make space for our new L2 header */
  317. if (newl2len != ctx->l2len)
  318. memmove(packet + newl2len, packet + ctx->l2len, pktlen - ctx->l2len);
  319. /* update the total packet length */
  320. pktlen += newl2len - ctx->l2len;
  321. /* always set the src & dst address as the first 12 bytes */
  322. eth = (struct tcpr_ethernet_hdr *)packet;
  323. if (dir == TCPR_DIR_C2S) {
  324. /* copy user supplied SRC MAC if provided or from original packet */
  325. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC1) {
  326. if ((ctx->addr_type == ETHERNET &&
  327. ((ctx->skip_broadcast &&
  328. is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  329. || ctx->addr_type != ETHERNET) {
  330. memcpy(eth->ether_shost, config->intf1_smac, ETHER_ADDR_LEN);
  331. } else {
  332. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  333. }
  334. } else if (ctx->addr_type == ETHERNET) {
  335. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  336. } else {
  337. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  338. return TCPEDIT_ERROR;
  339. }
  340. /* copy user supplied DMAC MAC if provided or from original packet */
  341. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC1) {
  342. if ((ctx->addr_type == ETHERNET &&
  343. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  344. || ctx->addr_type != ETHERNET) {
  345. memcpy(eth->ether_dhost, config->intf1_dmac, ETHER_ADDR_LEN);
  346. } else {
  347. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  348. }
  349. } else if (ctx->addr_type == ETHERNET) {
  350. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  351. } else {
  352. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  353. return TCPEDIT_ERROR;
  354. }
  355. } else if (dir == TCPR_DIR_S2C) {
  356. /* copy user supplied SRC MAC if provided or from original packet */
  357. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC2) {
  358. if ((ctx->addr_type == ETHERNET &&
  359. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  360. || ctx->addr_type != ETHERNET) {
  361. memcpy(eth->ether_shost, config->intf2_smac, ETHER_ADDR_LEN);
  362. } else {
  363. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  364. }
  365. } else if (ctx->addr_type == ETHERNET) {
  366. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  367. } else {
  368. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  369. return TCPEDIT_ERROR;
  370. }
  371. /* copy user supplied DMAC MAC if provided or from original packet */
  372. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC2) {
  373. if ((ctx->addr_type == ETHERNET &&
  374. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  375. || ctx->addr_type != ETHERNET) {
  376. memcpy(eth->ether_dhost, config->intf2_dmac, ETHER_ADDR_LEN);
  377. } else {
  378. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  379. }
  380. } else if (ctx->addr_type == ETHERNET) {
  381. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  382. } else {
  383. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  384. return TCPEDIT_ERROR;
  385. }
  386. } else {
  387. tcpedit_seterr(ctx->tcpedit, "%s", "Encoders only support C2S or C2S!");
  388. return TCPEDIT_ERROR;
  389. }
  390. if (newl2len == TCPR_802_3_H) {
  391. /* all we need for 802.3 is the proto */
  392. eth->ether_type = ctx->proto;
  393. } else if (newl2len == TCPR_802_1Q_H) {
  394. /* VLAN tags need a bit more */
  395. vlan = (struct tcpr_802_1q_hdr *)packet;
  396. vlan->vlan_len = ctx->proto;
  397. vlan->vlan_tpi = htons(ETHERTYPE_VLAN);
  398. /* are we changing VLAN info? */
  399. if (config->vlan_tag < 65535) {
  400. vlan->vlan_priority_c_vid =
  401. htons((u_int16_t)config->vlan_tag & TCPR_802_1Q_VIDMASK);
  402. } else if (extra->vlan) {
  403. vlan->vlan_priority_c_vid = extra->vlan_tag;
  404. } else {
  405. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-tag");
  406. return TCPEDIT_ERROR;
  407. }
  408. if (config->vlan_pri < 255) {
  409. vlan->vlan_priority_c_vid += htons((u_int16_t)config->vlan_pri << 13);
  410. } else if (extra->vlan) {
  411. vlan->vlan_priority_c_vid += extra->vlan_pri;
  412. } else {
  413. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-pri");
  414. return TCPEDIT_ERROR;
  415. }
  416. if (config->vlan_cfi < 255) {
  417. vlan->vlan_priority_c_vid += htons((u_int16_t)config->vlan_cfi << 12);
  418. } else if (extra->vlan) {
  419. vlan->vlan_priority_c_vid += extra->vlan_cfi;
  420. } else {
  421. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-cfi");
  422. return TCPEDIT_ERROR;
  423. }
  424. } else {
  425. tcpedit_seterr(ctx->tcpedit, "Unsupported new layer 2 length: %d", newl2len);
  426. return TCPEDIT_ERROR;
  427. }
  428. return pktlen;
  429. }
  430. /*
  431. * Function returns the Layer 3 protocol type of the given packet, or TCPEDIT_ERROR on error
  432. */
  433. int
  434. dlt_en10mb_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  435. {
  436. struct tcpr_ethernet_hdr *eth = NULL;
  437. struct tcpr_802_1q_hdr *vlan = NULL;
  438. assert(ctx);
  439. assert(packet);
  440. assert(pktlen);
  441. eth = (struct tcpr_ethernet_hdr *)packet;
  442. switch (ntohs(eth->ether_type)) {
  443. case ETHERTYPE_VLAN:
  444. vlan = (struct tcpr_802_1q_hdr *)packet;
  445. return vlan->vlan_len;
  446. break;
  447. default:
  448. return eth->ether_type;
  449. break;
  450. }
  451. return TCPEDIT_ERROR;
  452. }
  453. /*
  454. * Function returns a pointer to the layer 3 protocol header or NULL on error
  455. */
  456. u_char *
  457. dlt_en10mb_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen)
  458. {
  459. int l2len;
  460. assert(ctx);
  461. assert(packet);
  462. assert(pktlen);
  463. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  464. return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len);
  465. }
  466. /*
  467. * function merges the packet (containing L2 and old L3) with the l3data buffer
  468. * containing the new l3 data. Note, if L2 % 4 == 0, then they're pointing to the
  469. * same buffer, otherwise there was a memcpy involved on strictly aligned architectures
  470. * like SPARC
  471. */
  472. u_char *
  473. dlt_en10mb_merge_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen, u_char *l3data)
  474. {
  475. int l2len;
  476. assert(ctx);
  477. assert(packet);
  478. assert(l3data);
  479. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  480. assert(pktlen >= l2len);
  481. return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, l3data, l2len);
  482. }
  483. /*
  484. * return a static pointer to the source/destination MAC address
  485. * return NULL on error/address doesn't exist
  486. */
  487. u_char *
  488. dlt_en10mb_get_mac(tcpeditdlt_t *ctx, tcpeditdlt_mac_type_t mac, const u_char *packet, const int pktlen)
  489. {
  490. assert(ctx);
  491. assert(packet);
  492. assert(pktlen);
  493. /* FIXME: return a ptr to the source or dest mac address. */
  494. switch(mac) {
  495. case SRC_MAC:
  496. memcpy(ctx->srcmac, &packet[6], ETHER_ADDR_LEN);
  497. return(ctx->srcmac);
  498. break;
  499. case DST_MAC:
  500. memcpy(ctx->dstmac, packet, ETHER_ADDR_LEN);
  501. return(ctx->dstmac);
  502. break;
  503. default:
  504. errx(1, "Invalid tcpeditdlt_mac_type_t: %d", mac);
  505. }
  506. return(NULL);
  507. }
  508. /*
  509. * return the length of the L2 header of the current packet
  510. */
  511. int
  512. dlt_en10mb_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  513. {
  514. struct tcpr_ethernet_hdr *eth = NULL;
  515. assert(ctx);
  516. assert(packet);
  517. assert(pktlen);
  518. eth = (struct tcpr_ethernet_hdr *)packet;
  519. switch (ntohs(eth->ether_type)) {
  520. case ETHERTYPE_VLAN:
  521. return 18;
  522. break;
  523. default:
  524. return 14;
  525. break;
  526. }
  527. tcpedit_seterr(ctx->tcpedit, "%s", "Whoops! Bug in my code!");
  528. return -1;
  529. }
  530. tcpeditdlt_l2addr_type_t
  531. dlt_en10mb_l2addr_type(void)
  532. {
  533. return ETHERNET;
  534. }