en10mb.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. /* $Id$ */
  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 __attribute__((unused)) 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. /* add it to the available plugin list */
  84. return tcpedit_dlt_addplugin(ctx, plugin);
  85. }
  86. /*
  87. * Initializer function. This function is called only once, if and only iif
  88. * this plugin will be utilized. Remember, if you need to keep track of any state,
  89. * store it in your plugin->config, not a global!
  90. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  91. */
  92. int
  93. dlt_en10mb_init(tcpeditdlt_t *ctx)
  94. {
  95. tcpeditdlt_plugin_t *plugin;
  96. en10mb_config_t *config;
  97. assert(ctx);
  98. /* vlan tags need an additional 4 bytes */
  99. if ((plugin = tcpedit_dlt_getplugin(ctx, dlt_value)) == NULL) {
  100. tcpedit_seterr(ctx->tcpedit, "%s", "Unable to initalize unregistered plugin en10mb");
  101. return TCPEDIT_ERROR;
  102. }
  103. ctx->decoded_extra = safe_malloc(sizeof(en10mb_extra_t));
  104. plugin->config = safe_malloc(sizeof(en10mb_config_t));
  105. config = (en10mb_config_t *)plugin->config;
  106. /* init vlan user values to -1 to indicate not set */
  107. config->vlan_tag = 65535;
  108. config->vlan_pri = 255;
  109. config->vlan_cfi = 255;
  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. return TCPEDIT_OK;
  124. if (ctx->decoded_extra != NULL) {
  125. free(ctx->decoded_extra);
  126. ctx->decoded_extra = NULL;
  127. }
  128. if (plugin->config != NULL) {
  129. free(plugin->config);
  130. plugin->config = NULL;
  131. }
  132. return TCPEDIT_OK; /* success */
  133. }
  134. /*
  135. * This is where you should define all your AutoGen AutoOpts option parsing.
  136. * Any user specified option should have it's bit turned on in the 'provides'
  137. * bit mask.
  138. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  139. */
  140. int
  141. dlt_en10mb_parse_opts(tcpeditdlt_t *ctx)
  142. {
  143. tcpeditdlt_plugin_t *plugin;
  144. en10mb_config_t *config;
  145. assert(ctx);
  146. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  147. config = (en10mb_config_t *)plugin->config;
  148. /* --dmac */
  149. if (HAVE_OPT(ENET_DMAC)) {
  150. int macparse;
  151. macparse = dualmac2hex(OPT_ARG(ENET_DMAC), config->intf1_dmac,
  152. config->intf2_dmac, strlen(OPT_ARG(ENET_DMAC)));
  153. switch (macparse) {
  154. case 1:
  155. config->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  156. break;
  157. case 2:
  158. config->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  159. break;
  160. case 3:
  161. config->mac_mask += TCPEDIT_MAC_MASK_DMAC1;
  162. config->mac_mask += TCPEDIT_MAC_MASK_DMAC2;
  163. break;
  164. case 0:
  165. /* nothing to do */
  166. break;
  167. default:
  168. tcpedit_seterr(ctx->tcpedit,
  169. "Unable to parse --enet-dmac=%s", OPT_ARG(ENET_DMAC));
  170. return TCPEDIT_ERROR;
  171. break;
  172. }
  173. plugin->requires -= PLUGIN_MASK_DSTADDR;
  174. }
  175. /* --smac */
  176. if (HAVE_OPT(ENET_SMAC)) {
  177. int macparse;
  178. macparse = dualmac2hex(OPT_ARG(ENET_SMAC), config->intf1_smac,
  179. config->intf2_smac, strlen(OPT_ARG(ENET_SMAC)));
  180. switch (macparse) {
  181. case 1:
  182. config->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  183. break;
  184. case 2:
  185. config->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  186. break;
  187. case 3:
  188. config->mac_mask += TCPEDIT_MAC_MASK_SMAC1;
  189. config->mac_mask += TCPEDIT_MAC_MASK_SMAC2;
  190. break;
  191. case 0:
  192. /* nothing to do */
  193. break;
  194. default:
  195. tcpedit_seterr(ctx->tcpedit,
  196. "Unable to parse --enet-smac=%s", OPT_ARG(ENET_SMAC));
  197. return TCPEDIT_ERROR;
  198. break;
  199. }
  200. plugin->requires -= PLUGIN_MASK_SRCADDR;
  201. }
  202. /*
  203. * Validate 802.1q vlan args and populate tcpedit->vlan_record
  204. */
  205. if (HAVE_OPT(ENET_VLAN)) {
  206. if (strcmp(OPT_ARG(ENET_VLAN), "add") == 0) { // add or change
  207. config->vlan = TCPEDIT_VLAN_ADD;
  208. } else if (strcmp(OPT_ARG(ENET_VLAN), "del") == 0) {
  209. config->vlan = TCPEDIT_VLAN_DEL;
  210. } else {
  211. tcpedit_seterr(ctx->tcpedit, "Invalid --enet-vlan=%s", OPT_ARG(ENET_VLAN));
  212. return -1;
  213. }
  214. if (config->vlan != TCPEDIT_VLAN_OFF) {
  215. if (config->vlan == TCPEDIT_VLAN_ADD) {
  216. if (! HAVE_OPT(ENET_VLAN_TAG)) {
  217. tcpedit_seterr(ctx->tcpedit, "%s",
  218. "Must specify a new 802.1 VLAN tag if vlan "
  219. "mode is add");
  220. return TCPEDIT_ERROR;
  221. }
  222. /*
  223. * fill out the 802.1q header
  224. */
  225. config->vlan_tag = OPT_VALUE_ENET_VLAN_TAG;
  226. dbgx(1, "We will %s 802.1q headers",
  227. config->vlan == TCPEDIT_VLAN_DEL ? "delete" : "add/modify");
  228. if (HAVE_OPT(ENET_VLAN_PRI))
  229. config->vlan_pri = OPT_VALUE_ENET_VLAN_PRI;
  230. if (HAVE_OPT(ENET_VLAN_CFI))
  231. config->vlan_cfi = OPT_VALUE_ENET_VLAN_CFI;
  232. }
  233. }
  234. }
  235. return TCPEDIT_OK; /* success */
  236. }
  237. /*
  238. * Function to decode the layer 2 header in the packet
  239. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  240. */
  241. int
  242. dlt_en10mb_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  243. {
  244. tcpeditdlt_plugin_t *plugin = NULL;
  245. struct tcpr_ethernet_hdr *eth = NULL;
  246. struct tcpr_802_1q_hdr *vlan = NULL;
  247. en10mb_extra_t *extra = NULL;
  248. en10mb_config_t *config = NULL;
  249. assert(ctx);
  250. assert(packet);
  251. assert(pktlen >= 14);
  252. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  253. config = plugin->config;
  254. /* get our src & dst address */
  255. eth = (struct tcpr_ethernet_hdr *)packet;
  256. memcpy(&(ctx->dstaddr.ethernet), eth, ETHER_ADDR_LEN);
  257. memcpy(&(ctx->srcaddr.ethernet), &(eth->ether_shost), ETHER_ADDR_LEN);
  258. extra = (en10mb_extra_t *)ctx->decoded_extra;
  259. extra->vlan = 0;
  260. /* get the L3 protocol type & L2 len*/
  261. switch (eth->ether_type) {
  262. case ETHERTYPE_VLAN:
  263. vlan = (struct tcpr_802_1q_hdr *)packet;
  264. ctx->proto = vlan->vlan_len;
  265. /* Get VLAN tag info */
  266. extra->vlan = 1;
  267. /* must use these mask values, rather then what's in the tcpr.h since it assumes you're shifting */
  268. extra->vlan_tag = vlan->vlan_priority_c_vid & 0x0FFF;
  269. extra->vlan_pri = vlan->vlan_priority_c_vid & 0xE000;
  270. extra->vlan_cfi = vlan->vlan_priority_c_vid & 0x1000;
  271. ctx->l2len = TCPR_802_1Q_H;
  272. break;
  273. /* we don't properly handle SNAP encoding */
  274. default:
  275. ctx->proto = eth->ether_type;
  276. ctx->l2len = TCPR_802_3_H;
  277. break;
  278. }
  279. return TCPEDIT_OK; /* success */
  280. }
  281. /*
  282. * Function to encode the layer 2 header back into the packet.
  283. * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN
  284. */
  285. int
  286. dlt_en10mb_encode(tcpeditdlt_t *ctx, u_char **packet_ex, int pktlen, tcpr_dir_t dir)
  287. {
  288. u_char *packet;
  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. u_char tmpbuff[MAXPACKET];
  296. assert(ctx);
  297. assert(packet_ex);
  298. assert(pktlen >= 14);
  299. packet = *packet_ex;
  300. assert(packet);
  301. plugin = tcpedit_dlt_getplugin(ctx, dlt_value);
  302. config = plugin->config;
  303. extra = (en10mb_extra_t *)ctx->decoded_extra;
  304. /* figure out the new layer2 length, first for the case: ethernet -> ethernet? */
  305. if (ctx->decoder->dlt == dlt_value) {
  306. if ((ctx->l2len == TCPR_802_1Q_H && config->vlan == TCPEDIT_VLAN_OFF) ||
  307. (config->vlan == TCPEDIT_VLAN_ADD)) {
  308. newl2len = TCPR_802_1Q_H;
  309. } else if ((ctx->l2len == TCPR_802_3_H && config->vlan == TCPEDIT_VLAN_OFF) ||
  310. (config->vlan == TCPEDIT_VLAN_DEL)) {
  311. newl2len = TCPR_802_3_H;
  312. }
  313. }
  314. /* newl2len for some other DLT -> ethernet */
  315. else {
  316. /* if add a vlan then 18, else 14 bytes */
  317. newl2len = config->vlan == TCPEDIT_VLAN_ADD ? TCPR_802_1Q_H : TCPR_802_3_H;
  318. }
  319. /* Make space for our new L2 header */
  320. if (newl2len > ctx->l2len) {
  321. memcpy(tmpbuff, packet, pktlen);
  322. memcpy(packet + newl2len, (tmpbuff + ctx->l2len), pktlen - ctx->l2len);
  323. } else if (newl2len < ctx->l2len) {
  324. memmove(packet + newl2len, packet + ctx->l2len, pktlen - ctx->l2len);
  325. } /* else same size, so do nothing */
  326. /* update the total packet length */
  327. pktlen += newl2len - ctx->l2len;
  328. /* always set the src & dst address as the first 12 bytes */
  329. eth = (struct tcpr_ethernet_hdr *)packet;
  330. if (dir == TCPR_DIR_C2S) {
  331. /* copy user supplied SRC MAC if provided or from original packet */
  332. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC1) {
  333. if ((ctx->addr_type == ETHERNET &&
  334. ((ctx->skip_broadcast &&
  335. is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  336. || ctx->addr_type != ETHERNET) {
  337. memcpy(eth->ether_shost, config->intf1_smac, ETHER_ADDR_LEN);
  338. } else {
  339. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  340. }
  341. } else if (ctx->addr_type == ETHERNET) {
  342. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  343. } else {
  344. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  345. return TCPEDIT_ERROR;
  346. }
  347. /* copy user supplied DMAC MAC if provided or from original packet */
  348. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC1) {
  349. if ((ctx->addr_type == ETHERNET &&
  350. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  351. || ctx->addr_type != ETHERNET) {
  352. memcpy(eth->ether_dhost, config->intf1_dmac, ETHER_ADDR_LEN);
  353. } else {
  354. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  355. }
  356. } else if (ctx->addr_type == ETHERNET) {
  357. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  358. } else {
  359. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  360. return TCPEDIT_ERROR;
  361. }
  362. } else if (dir == TCPR_DIR_S2C) {
  363. /* copy user supplied SRC MAC if provided or from original packet */
  364. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC2) {
  365. if ((ctx->addr_type == ETHERNET &&
  366. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  367. || ctx->addr_type != ETHERNET) {
  368. memcpy(eth->ether_shost, config->intf2_smac, ETHER_ADDR_LEN);
  369. } else {
  370. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  371. }
  372. } else if (ctx->addr_type == ETHERNET) {
  373. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  374. } else {
  375. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  376. return TCPEDIT_ERROR;
  377. }
  378. /* copy user supplied DMAC MAC if provided or from original packet */
  379. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC2) {
  380. if ((ctx->addr_type == ETHERNET &&
  381. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  382. || ctx->addr_type != ETHERNET) {
  383. memcpy(eth->ether_dhost, config->intf2_dmac, ETHER_ADDR_LEN);
  384. } else {
  385. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  386. }
  387. } else if (ctx->addr_type == ETHERNET) {
  388. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  389. } else {
  390. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  391. return TCPEDIT_ERROR;
  392. }
  393. } else {
  394. tcpedit_seterr(ctx->tcpedit, "%s", "Encoders only support C2S or C2S!");
  395. return TCPEDIT_ERROR;
  396. }
  397. if (newl2len == TCPR_802_3_H) {
  398. /* all we need for 802.3 is the proto */
  399. eth->ether_type = ctx->proto;
  400. } else if (newl2len == TCPR_802_1Q_H) {
  401. /* VLAN tags need a bit more */
  402. vlan = (struct tcpr_802_1q_hdr *)packet;
  403. vlan->vlan_len = ctx->proto;
  404. vlan->vlan_tpi = htons(ETHERTYPE_VLAN);
  405. /* are we changing VLAN info? */
  406. if (config->vlan_tag < 65535) {
  407. vlan->vlan_priority_c_vid =
  408. htons((u_int16_t)config->vlan_tag & TCPR_802_1Q_VIDMASK);
  409. } else if (extra->vlan) {
  410. vlan->vlan_priority_c_vid = extra->vlan_tag;
  411. } else {
  412. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-tag");
  413. return TCPEDIT_ERROR;
  414. }
  415. if (config->vlan_pri < 255) {
  416. vlan->vlan_priority_c_vid += htons((u_int16_t)config->vlan_pri << 13);
  417. } else if (extra->vlan) {
  418. vlan->vlan_priority_c_vid += extra->vlan_pri;
  419. } else {
  420. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-pri");
  421. return TCPEDIT_ERROR;
  422. }
  423. if (config->vlan_cfi < 255) {
  424. vlan->vlan_priority_c_vid += htons((u_int16_t)config->vlan_cfi << 12);
  425. } else if (extra->vlan) {
  426. vlan->vlan_priority_c_vid += extra->vlan_cfi;
  427. } else {
  428. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-cfi");
  429. return TCPEDIT_ERROR;
  430. }
  431. } else {
  432. tcpedit_seterr(ctx->tcpedit, "Unsupported new layer 2 length: %d", newl2len);
  433. return TCPEDIT_ERROR;
  434. }
  435. return pktlen;
  436. }
  437. /*
  438. * Function returns the Layer 3 protocol type of the given packet, or TCPEDIT_ERROR on error
  439. */
  440. int
  441. dlt_en10mb_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  442. {
  443. struct tcpr_ethernet_hdr *eth = NULL;
  444. struct tcpr_802_1q_hdr *vlan = NULL;
  445. assert(ctx);
  446. assert(packet);
  447. assert(pktlen);
  448. eth = (struct tcpr_ethernet_hdr *)packet;
  449. switch (eth->ether_type) {
  450. case ETHERTYPE_VLAN:
  451. vlan = (struct tcpr_802_1q_hdr *)packet;
  452. return ntohs(vlan->vlan_len);
  453. break;
  454. default:
  455. return ntohs(eth->ether_type);
  456. break;
  457. }
  458. return TCPEDIT_ERROR;
  459. }
  460. /*
  461. * Function returns a pointer to the layer 3 protocol header or NULL on error
  462. */
  463. u_char *
  464. dlt_en10mb_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen)
  465. {
  466. int l2len;
  467. assert(ctx);
  468. assert(packet);
  469. assert(pktlen);
  470. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  471. return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len);
  472. }
  473. /*
  474. * function merges the packet (containing L2 and old L3) with the l3data buffer
  475. * containing the new l3 data. Note, if L2 % 4 == 0, then they're pointing to the
  476. * same buffer, otherwise there was a memcpy involved on strictly aligned architectures
  477. * like SPARC
  478. */
  479. u_char *
  480. dlt_en10mb_merge_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen, u_char *l3data)
  481. {
  482. int l2len;
  483. assert(ctx);
  484. assert(packet);
  485. assert(l3data);
  486. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  487. assert(pktlen >= l2len);
  488. return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, l3data, l2len);
  489. }
  490. /*
  491. * return the length of the L2 header of the current packet
  492. */
  493. int
  494. dlt_en10mb_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  495. {
  496. struct tcpr_ethernet_hdr *eth = NULL;
  497. assert(ctx);
  498. assert(packet);
  499. assert(pktlen);
  500. eth = (struct tcpr_ethernet_hdr *)packet;
  501. switch (eth->ether_type) {
  502. case ETHERTYPE_VLAN:
  503. return 18;
  504. break;
  505. default:
  506. return 14;
  507. break;
  508. }
  509. tcpedit_seterr(ctx->tcpedit, "%s", "Whoops! Bug in my code!");
  510. return -1;
  511. }
  512. tcpeditdlt_l2addr_type_t
  513. dlt_en10mb_l2addr_type(void)
  514. {
  515. return ETHERNET;
  516. }