en10mb.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /* $Id: en10mb.c 1921 2007-10-25 18:18:50Z 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_ex, int pktlen, tcpr_dir_t dir)
  288. {
  289. u_char *packet;
  290. tcpeditdlt_plugin_t *plugin = NULL;
  291. struct tcpr_ethernet_hdr *eth = NULL;
  292. struct tcpr_802_1q_hdr *vlan = NULL;
  293. en10mb_config_t *config = NULL;
  294. en10mb_extra_t *extra = NULL;
  295. int newl2len = 0;
  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. memmove(packet + newl2len, packet + ctx->l2len, pktlen - ctx->l2len);
  322. /* update the total packet length */
  323. pktlen += newl2len - ctx->l2len;
  324. /* always set the src & dst address as the first 12 bytes */
  325. eth = (struct tcpr_ethernet_hdr *)packet;
  326. if (dir == TCPR_DIR_C2S) {
  327. /* copy user supplied SRC MAC if provided or from original packet */
  328. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC1) {
  329. if ((ctx->addr_type == ETHERNET &&
  330. ((ctx->skip_broadcast &&
  331. is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  332. || ctx->addr_type != ETHERNET) {
  333. memcpy(eth->ether_shost, config->intf1_smac, ETHER_ADDR_LEN);
  334. } else {
  335. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  336. }
  337. } else if (ctx->addr_type == ETHERNET) {
  338. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  339. } else {
  340. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  341. return TCPEDIT_ERROR;
  342. }
  343. /* copy user supplied DMAC MAC if provided or from original packet */
  344. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC1) {
  345. if ((ctx->addr_type == ETHERNET &&
  346. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  347. || ctx->addr_type != ETHERNET) {
  348. memcpy(eth->ether_dhost, config->intf1_dmac, ETHER_ADDR_LEN);
  349. } else {
  350. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  351. }
  352. } else if (ctx->addr_type == ETHERNET) {
  353. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  354. } else {
  355. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  356. return TCPEDIT_ERROR;
  357. }
  358. } else if (dir == TCPR_DIR_S2C) {
  359. /* copy user supplied SRC MAC if provided or from original packet */
  360. if (config->mac_mask & TCPEDIT_MAC_MASK_SMAC2) {
  361. if ((ctx->addr_type == ETHERNET &&
  362. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->srcaddr.ethernet)) || !ctx->skip_broadcast))
  363. || ctx->addr_type != ETHERNET) {
  364. memcpy(eth->ether_shost, config->intf2_smac, ETHER_ADDR_LEN);
  365. } else {
  366. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  367. }
  368. } else if (ctx->addr_type == ETHERNET) {
  369. memcpy(eth->ether_shost, ctx->srcaddr.ethernet, ETHER_ADDR_LEN);
  370. } else {
  371. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a source address");
  372. return TCPEDIT_ERROR;
  373. }
  374. /* copy user supplied DMAC MAC if provided or from original packet */
  375. if (config->mac_mask & TCPEDIT_MAC_MASK_DMAC2) {
  376. if ((ctx->addr_type == ETHERNET &&
  377. ((ctx->skip_broadcast && is_unicast_ethernet(ctx, ctx->dstaddr.ethernet)) || !ctx->skip_broadcast))
  378. || ctx->addr_type != ETHERNET) {
  379. memcpy(eth->ether_dhost, config->intf2_dmac, ETHER_ADDR_LEN);
  380. } else {
  381. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  382. }
  383. } else if (ctx->addr_type == ETHERNET) {
  384. memcpy(eth->ether_dhost, ctx->dstaddr.ethernet, ETHER_ADDR_LEN);
  385. } else {
  386. tcpedit_seterr(ctx->tcpedit, "%s", "Please provide a destination address");
  387. return TCPEDIT_ERROR;
  388. }
  389. } else {
  390. tcpedit_seterr(ctx->tcpedit, "%s", "Encoders only support C2S or C2S!");
  391. return TCPEDIT_ERROR;
  392. }
  393. if (newl2len == TCPR_802_3_H) {
  394. /* all we need for 802.3 is the proto */
  395. eth->ether_type = ctx->proto;
  396. } else if (newl2len == TCPR_802_1Q_H) {
  397. /* VLAN tags need a bit more */
  398. vlan = (struct tcpr_802_1q_hdr *)packet;
  399. vlan->vlan_len = ctx->proto;
  400. vlan->vlan_tpi = htons(ETHERTYPE_VLAN);
  401. /* are we changing VLAN info? */
  402. if (config->vlan_tag < 65535) {
  403. vlan->vlan_priority_c_vid =
  404. htons((u_int16_t)config->vlan_tag & TCPR_802_1Q_VIDMASK);
  405. } else if (extra->vlan) {
  406. vlan->vlan_priority_c_vid = extra->vlan_tag;
  407. } else {
  408. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-tag");
  409. return TCPEDIT_ERROR;
  410. }
  411. if (config->vlan_pri < 255) {
  412. vlan->vlan_priority_c_vid += htons((u_int16_t)config->vlan_pri << 13);
  413. } else if (extra->vlan) {
  414. vlan->vlan_priority_c_vid += extra->vlan_pri;
  415. } else {
  416. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-pri");
  417. return TCPEDIT_ERROR;
  418. }
  419. if (config->vlan_cfi < 255) {
  420. vlan->vlan_priority_c_vid += htons((u_int16_t)config->vlan_cfi << 12);
  421. } else if (extra->vlan) {
  422. vlan->vlan_priority_c_vid += extra->vlan_cfi;
  423. } else {
  424. tcpedit_seterr(ctx->tcpedit, "%s", "Non-VLAN tagged packet requires --enet-vlan-cfi");
  425. return TCPEDIT_ERROR;
  426. }
  427. } else {
  428. tcpedit_seterr(ctx->tcpedit, "Unsupported new layer 2 length: %d", newl2len);
  429. return TCPEDIT_ERROR;
  430. }
  431. return pktlen;
  432. }
  433. /*
  434. * Function returns the Layer 3 protocol type of the given packet, or TCPEDIT_ERROR on error
  435. */
  436. int
  437. dlt_en10mb_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  438. {
  439. struct tcpr_ethernet_hdr *eth = NULL;
  440. struct tcpr_802_1q_hdr *vlan = NULL;
  441. assert(ctx);
  442. assert(packet);
  443. assert(pktlen);
  444. eth = (struct tcpr_ethernet_hdr *)packet;
  445. switch (ntohs(eth->ether_type)) {
  446. case ETHERTYPE_VLAN:
  447. vlan = (struct tcpr_802_1q_hdr *)packet;
  448. return vlan->vlan_len;
  449. break;
  450. default:
  451. return eth->ether_type;
  452. break;
  453. }
  454. return TCPEDIT_ERROR;
  455. }
  456. /*
  457. * Function returns a pointer to the layer 3 protocol header or NULL on error
  458. */
  459. u_char *
  460. dlt_en10mb_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen)
  461. {
  462. int l2len;
  463. assert(ctx);
  464. assert(packet);
  465. assert(pktlen);
  466. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  467. return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len);
  468. }
  469. /*
  470. * function merges the packet (containing L2 and old L3) with the l3data buffer
  471. * containing the new l3 data. Note, if L2 % 4 == 0, then they're pointing to the
  472. * same buffer, otherwise there was a memcpy involved on strictly aligned architectures
  473. * like SPARC
  474. */
  475. u_char *
  476. dlt_en10mb_merge_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen, u_char *l3data)
  477. {
  478. int l2len;
  479. assert(ctx);
  480. assert(packet);
  481. assert(l3data);
  482. l2len = dlt_en10mb_l2len(ctx, packet, pktlen);
  483. assert(pktlen >= l2len);
  484. return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, l3data, l2len);
  485. }
  486. /*
  487. * return a static pointer to the source/destination MAC address
  488. * return NULL on error/address doesn't exist
  489. */
  490. u_char *
  491. dlt_en10mb_get_mac(tcpeditdlt_t *ctx, tcpeditdlt_mac_type_t mac, const u_char *packet, const int pktlen)
  492. {
  493. assert(ctx);
  494. assert(packet);
  495. assert(pktlen);
  496. /* FIXME: return a ptr to the source or dest mac address. */
  497. switch(mac) {
  498. case SRC_MAC:
  499. memcpy(ctx->srcmac, &packet[6], ETHER_ADDR_LEN);
  500. return(ctx->srcmac);
  501. break;
  502. case DST_MAC:
  503. memcpy(ctx->dstmac, packet, ETHER_ADDR_LEN);
  504. return(ctx->dstmac);
  505. break;
  506. default:
  507. errx(1, "Invalid tcpeditdlt_mac_type_t: %d", mac);
  508. }
  509. return(NULL);
  510. }
  511. /*
  512. * return the length of the L2 header of the current packet
  513. */
  514. int
  515. dlt_en10mb_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen)
  516. {
  517. struct tcpr_ethernet_hdr *eth = NULL;
  518. assert(ctx);
  519. assert(packet);
  520. assert(pktlen);
  521. eth = (struct tcpr_ethernet_hdr *)packet;
  522. switch (ntohs(eth->ether_type)) {
  523. case ETHERTYPE_VLAN:
  524. return 18;
  525. break;
  526. default:
  527. return 14;
  528. break;
  529. }
  530. tcpedit_seterr(ctx->tcpedit, "%s", "Whoops! Bug in my code!");
  531. return -1;
  532. }
  533. tcpeditdlt_l2addr_type_t
  534. dlt_en10mb_l2addr_type(void)
  535. {
  536. return ETHERNET;
  537. }