rewrite_l2.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /* $Id: rewrite_l2.c 1503 2006-07-17 02:33:45Z aturner $ */
  2. /*
  3. * Copyright (c) 2005 Aaron Turner.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include "defines.h"
  33. #include "common.h"
  34. /*
  35. * rewrite_l2.c can be compiled for tcprewrite or tcpbridge
  36. * in both cases, it requires a number of variables to be
  37. * available in the global options structure
  38. */
  39. #include "tcpedit.h"
  40. #include "../common.h"
  41. #include "lib/sll.h"
  42. #include "dlt.h"
  43. #include "rewrite_l2.h"
  44. extern int maxpacket;
  45. static int check_pkt_len(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  46. int oldl2len, int newl2len);
  47. /*
  48. * Do all the layer 2 rewriting. Change ethernet header or even
  49. * rewrite mac addresses
  50. * return layer 2 length on success or 0 on don't send packet
  51. * or -1 on critical failure
  52. */
  53. int
  54. rewrite_l2(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr,
  55. u_char **pktdata, int direction)
  56. {
  57. u_char *l2data = NULL; /* ptr to the user specified layer2 data if any */
  58. int newl2len = 0;
  59. pcap_t *pcap;
  60. /* do we need a ptr for l2data ? */
  61. if (tcpedit->l2.dlt == DLT_USER) {
  62. if (direction == CACHE_SECONDARY) {
  63. l2data = tcpedit->l2.data2;
  64. } else {
  65. l2data = tcpedit->l2.data1;
  66. }
  67. }
  68. pcap = direction == CACHE_PRIMARY ? tcpedit->runtime.pcap1 :
  69. tcpedit->runtime.pcap2;
  70. /*
  71. * figure out what the CURRENT packet encapsulation is and we'll call
  72. * the appropriate function to:
  73. * 1) resize the L2 header
  74. * 2) copy over existing L2 header info (protocol, MAC's) to a new
  75. * standard 802.3 ethernet header where applicable
  76. * We do NOT apply any src/dst mac rewriting, as that is common
  77. * to all conversions, so that happens at the bottom of this function
  78. */
  79. switch (pcap_datalink(pcap)) {
  80. case DLT_EN10MB: /* Standard 802.3 Ethernet */
  81. newl2len = rewrite_en10mb(tcpedit, pktdata, pkthdr, l2data);
  82. break;
  83. case DLT_LINUX_SLL: /* Linux Cooked sockets */
  84. newl2len = rewrite_linux_sll(tcpedit, pktdata, pkthdr, l2data);
  85. break;
  86. case DLT_RAW: /* No ethernet header, raw IP */
  87. newl2len = rewrite_raw(tcpedit, pktdata, pkthdr, l2data);
  88. break;
  89. case DLT_C_HDLC: /* Cisco HDLC */
  90. newl2len = rewrite_c_hdlc(tcpedit, pktdata, pkthdr, l2data);
  91. break;
  92. default:
  93. tcpedit_seterr(tcpedit, "Unsupported DLT type: %d",
  94. pcap_datalink(pcap));
  95. return -1;
  96. } /* switch (dlt) */
  97. /* if newl2len == 0, then return zero so we don't send the packet */
  98. if (! newl2len)
  99. return 0;
  100. /*
  101. * Okay... we've got our new layer 2 header
  102. * if required. The next question, is do we have to
  103. * replace the src/dst MAC??
  104. */
  105. if (direction == CACHE_SECONDARY) {
  106. if (tcpedit->mac_mask & TCPEDIT_MAC_MASK_SMAC2) {
  107. memcpy(*pktdata + ETHER_ADDR_LEN, tcpedit->intf2_smac, ETHER_ADDR_LEN);
  108. }
  109. if (tcpedit->mac_mask & TCPEDIT_MAC_MASK_DMAC2) {
  110. memcpy(*pktdata, tcpedit->intf2_dmac, ETHER_ADDR_LEN);
  111. }
  112. } else {
  113. if (tcpedit->mac_mask & TCPEDIT_MAC_MASK_SMAC1) {
  114. memcpy(*pktdata + ETHER_ADDR_LEN, tcpedit->intf1_smac, ETHER_ADDR_LEN);
  115. }
  116. if (tcpedit->mac_mask & TCPEDIT_MAC_MASK_DMAC1) {
  117. memcpy(*pktdata, tcpedit->intf1_dmac, ETHER_ADDR_LEN);
  118. }
  119. }
  120. /* return the updated layer 2 len */
  121. return (newl2len);
  122. }
  123. /*
  124. * All of these functions return the NEW layer two length and update the
  125. * total packet length in (*pkthdr)->caplen
  126. */
  127. /*
  128. * logic to rewrite packets using DLT_EN10MB
  129. * returns -1 on error
  130. * returns 0 un unable to rewrite
  131. * returns length of new layer 2 header on success
  132. */
  133. int
  134. rewrite_en10mb(tcpedit_t *tcpedit, u_char **pktdata,
  135. struct pcap_pkthdr **pkthdr, u_char *l2data)
  136. {
  137. eth_hdr_t *eth_hdr = NULL;
  138. vlan_hdr_t *vlan_hdr = NULL;
  139. int oldl2len = 0, newl2len = 0, lendiff;
  140. u_char tmpbuff[MAXPACKET];
  141. /*
  142. * is the header ethernet or 802.1q?
  143. */
  144. eth_hdr = (eth_hdr_t *)(*pktdata);
  145. if (eth_hdr->ether_type == ETHERTYPE_VLAN) {
  146. newl2len = oldl2len = LIBNET_802_1Q_H;
  147. } else {
  148. newl2len = oldl2len = LIBNET_ETH_H;
  149. }
  150. switch (tcpedit->l2.dlt) {
  151. case DLT_USER:
  152. /* track the new L2 len */
  153. newl2len = tcpedit->l2.len;
  154. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  155. return 0; /* unable to send packet */
  156. /*
  157. * remove the old header and copy our header back
  158. */
  159. dbg(3, "Rewriting packet via --dlink...");
  160. /* do we need a temp buff? */
  161. if (newl2len > oldl2len) {
  162. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  163. memcpy(*pktdata, l2data, tcpedit->l2.len);
  164. memcpy(*pktdata + newl2len, (tmpbuff + oldl2len),
  165. (*pkthdr)->caplen);
  166. } else if (newl2len < oldl2len) {
  167. memcpy(*pktdata, l2data, newl2len);
  168. memmove(*pktdata + newl2len, *pktdata + oldl2len,
  169. (*pkthdr)->caplen);
  170. } else { // same size
  171. memcpy(*pktdata, l2data, newl2len);
  172. }
  173. break;
  174. case DLT_VLAN:
  175. /* are we adding/modifying a VLAN header? */
  176. if (tcpedit->vlan == TCPEDIT_VLAN_ADD) {
  177. newl2len = LIBNET_802_1Q_H;
  178. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  179. return 0; /* unable to send packet */
  180. vlan_hdr = (vlan_hdr_t *)*pktdata;
  181. /* do we modify the VLAN header? */
  182. if (oldl2len == newl2len) {
  183. /* user must always specify a tag */
  184. vlan_hdr->vlan_priority_c_vid |=
  185. htons((u_int16_t)tcpedit->l2.vlan_tag & LIBNET_802_1Q_VIDMASK);
  186. /* these are optional */
  187. if (tcpedit->l2.vlan_pri)
  188. vlan_hdr->vlan_priority_c_vid |=
  189. htons((u_int16_t)tcpedit->l2.vlan_pri) << 13;
  190. if (tcpedit->l2.vlan_cfi)
  191. vlan_hdr->vlan_priority_c_vid |=
  192. htons((u_int16_t)tcpedit->l2.vlan_cfi) << 12;
  193. }
  194. /* else we are adding a VLAN header */
  195. else if (oldl2len == LIBNET_ETH_H) {
  196. /* zero out our L2 header */
  197. memset(tmpbuff, 0, newl2len);
  198. /* copy the dst/src MAC's over to our temp buffer */
  199. memcpy(tmpbuff, *pktdata, ETHER_ADDR_LEN * 2);
  200. vlan_hdr = (vlan_hdr_t *)tmpbuff;
  201. eth_hdr = (eth_hdr_t *)*pktdata;
  202. /* these fields are always set this way */
  203. vlan_hdr->vlan_tpi = htons(ETHERTYPE_VLAN);
  204. vlan_hdr->vlan_len = eth_hdr->ether_type;
  205. /* user must always specify a tag */
  206. vlan_hdr->vlan_priority_c_vid |=
  207. htons((u_int16_t)tcpedit->l2.vlan_tag & LIBNET_802_1Q_VIDMASK);
  208. /* other things are optional */
  209. if (tcpedit->l2.vlan_pri)
  210. vlan_hdr->vlan_priority_c_vid |=
  211. htons((u_int16_t)tcpedit->l2.vlan_pri) << 13;
  212. if (tcpedit->l2.vlan_cfi)
  213. vlan_hdr->vlan_priority_c_vid |=
  214. htons((u_int16_t)tcpedit->l2.vlan_cfi) << 12;
  215. /* move around our buffers */
  216. memcpy(&tmpbuff[newl2len], (*pktdata + oldl2len), ((*pkthdr)->caplen - oldl2len));
  217. memcpy(*pktdata, tmpbuff, ((*pkthdr)->caplen + newl2len - oldl2len));
  218. } else {
  219. err(1, "Uh, how are we supposed to rewrite the header when the oldl2len != LIBNET_ETH_H?");
  220. }
  221. }
  222. else {
  223. /* remove VLAN header */
  224. newl2len = LIBNET_ETH_H;
  225. /* we still verify packet len incase MTU has shrunk */
  226. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  227. return 0; /* unable to send packet */
  228. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  229. eth_hdr = (eth_hdr_t *)*pktdata;
  230. vlan_hdr = (vlan_hdr_t *)tmpbuff;
  231. eth_hdr->ether_type = vlan_hdr->vlan_len;
  232. memcpy(*pktdata + LIBNET_ETH_H, (tmpbuff + LIBNET_802_1Q_H), (*pkthdr)->caplen - oldl2len);
  233. }
  234. break;
  235. case DLT_EN10MB:
  236. /* nothing to do here since we're already ethernet! */
  237. break;
  238. default:
  239. tcpedit_seterr(tcpedit, "Invalid tcpedit->l2.dlt value: 0x%04x", tcpedit->l2.dlt);
  240. return -1;
  241. break;
  242. }
  243. /* new packet len */
  244. lendiff = newl2len - oldl2len;
  245. (*pkthdr)->caplen += lendiff;
  246. (*pkthdr)->len += lendiff;
  247. return newl2len;
  248. }
  249. /*
  250. * logic to rewrite packets using DLT_RAW
  251. * returns -1 on error
  252. * returns 0 un unable to rewrite
  253. * returns length of new layer 2 header on success
  254. */
  255. int
  256. rewrite_raw(tcpedit_t *tcpedit, u_char **pktdata,
  257. struct pcap_pkthdr **pkthdr, u_char *l2data)
  258. {
  259. int oldl2len = 0, newl2len = 0, lendiff;
  260. u_char tmpbuff[MAXPACKET];
  261. vlan_hdr_t *vlan_hdr = NULL;
  262. eth_hdr_t *eth_hdr = NULL;
  263. /* we have no ethernet header, but we know we're IP */
  264. switch (tcpedit->l2.dlt) {
  265. case DLT_USER:
  266. newl2len = tcpedit->l2.len;
  267. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  268. return 0; /* unable to send packet */
  269. /*
  270. * add our user specified header
  271. */
  272. dbg(3, "Rewriting packet via --dlink...");
  273. /* backup the old packet */
  274. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  275. memcpy(*pktdata, l2data, newl2len);
  276. memcpy(*pktdata + newl2len, tmpbuff, (*pkthdr)->caplen);
  277. break;
  278. case DLT_VLAN:
  279. newl2len = LIBNET_802_1Q_H;
  280. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  281. return 0; /* unable to send packet */
  282. /* prep a 802.1q tagged frame */
  283. /* make space for the header */
  284. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  285. memcpy(*pktdata + LIBNET_802_1Q_H, tmpbuff, (*pkthdr)->caplen);
  286. vlan_hdr = (vlan_hdr_t *)*pktdata;
  287. /* these fields are always set this way */
  288. vlan_hdr->vlan_tpi = ETHERTYPE_VLAN;
  289. vlan_hdr->vlan_len = tcpedit->l2proto;
  290. /* user must always specify a tag */
  291. vlan_hdr->vlan_priority_c_vid |=
  292. htons((u_int16_t)tcpedit->l2.vlan_tag & LIBNET_802_1Q_VIDMASK);
  293. /* other things are optional */
  294. if (tcpedit->l2.vlan_pri)
  295. vlan_hdr->vlan_priority_c_vid |=
  296. htons((u_int16_t)tcpedit->l2.vlan_pri) << 13;
  297. if (tcpedit->l2.vlan_cfi)
  298. vlan_hdr->vlan_priority_c_vid |=
  299. htons((u_int16_t)tcpedit->l2.vlan_cfi) << 12;
  300. /* new packet len */
  301. newl2len = LIBNET_802_1Q_H;
  302. break;
  303. case DLT_EN10MB:
  304. newl2len = LIBNET_ETH_H;
  305. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  306. return 0; /* unable to send packet */
  307. /* make room for L2 header */
  308. memmove(*pktdata + LIBNET_ETH_H, *pktdata, (*pkthdr)->caplen);
  309. /* these fields are always set this way */
  310. eth_hdr = (eth_hdr_t *)*pktdata;
  311. eth_hdr->ether_type = tcpedit->l2proto;
  312. break;
  313. default:
  314. tcpedit_seterr(tcpedit, "Invalid tcpedit->l2.dlt value: 0x%x", tcpedit->l2.dlt);
  315. return -1;
  316. break;
  317. }
  318. /* new packet len */
  319. lendiff = newl2len - oldl2len;
  320. (*pkthdr)->caplen += lendiff;
  321. (*pkthdr)->len += lendiff;
  322. return newl2len;
  323. }
  324. /*
  325. * logic to rewrite packets using DLT_LINUX_SLL
  326. * returns -1 on error
  327. * returns 0 un unable to rewrite
  328. * returns length of new layer 2 header on success
  329. */
  330. int
  331. rewrite_linux_sll(tcpedit_t *tcpedit, u_char **pktdata,
  332. struct pcap_pkthdr **pkthdr, u_char *l2data)
  333. {
  334. int oldl2len = 0, newl2len = 0, lendiff;
  335. u_char tmpbuff[MAXPACKET];
  336. vlan_hdr_t *vlan_hdr = NULL;
  337. eth_hdr_t *eth_hdr = NULL;
  338. sll_hdr_t *sll_hdr = NULL;
  339. newl2len = oldl2len = SLL_HDR_LEN;
  340. switch (tcpedit->l2.dlt) {
  341. case DLT_USER:
  342. newl2len = tcpedit->l2.len;
  343. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  344. return 0; /* unable to send packet */
  345. /*
  346. * add our user specified header
  347. */
  348. dbg(3, "Rewriting packet via --dlink...");
  349. /* backup the old packet */
  350. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  351. memcpy(*pktdata, l2data, newl2len);
  352. memcpy(*pktdata + newl2len, tmpbuff, (*pkthdr)->caplen);
  353. break;
  354. case DLT_VLAN:
  355. /* prep a 802.1q tagged frame */
  356. newl2len = LIBNET_802_1Q_H;
  357. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  358. return 0; /* unable to send packet */
  359. /* make space for the header */
  360. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  361. memcpy(*pktdata + LIBNET_802_1Q_H, tmpbuff, (*pkthdr)->caplen - oldl2len);
  362. vlan_hdr = (vlan_hdr_t *)*pktdata;
  363. sll_hdr = (sll_hdr_t *)tmpbuff;
  364. /* these fields are always set this way */
  365. vlan_hdr->vlan_tpi = ETHERTYPE_VLAN;
  366. vlan_hdr->vlan_len = sll_hdr->sll_protocol;
  367. /* the sll header might have a src mac */
  368. if (sll_hdr->sll_halen == ETHER_ADDR_LEN)
  369. memcpy(vlan_hdr->vlan_shost, sll_hdr->sll_addr, ETHER_ADDR_LEN);
  370. /* user must always specify a tag */
  371. vlan_hdr->vlan_priority_c_vid |=
  372. htons((u_int16_t)(tcpedit->l2.vlan_tag & LIBNET_802_1Q_VIDMASK));
  373. /* other things are optional */
  374. if (tcpedit->l2.vlan_pri)
  375. vlan_hdr->vlan_priority_c_vid |=
  376. htons((u_int16_t)tcpedit->l2.vlan_pri) << 13;
  377. if (tcpedit->l2.vlan_cfi)
  378. vlan_hdr->vlan_priority_c_vid |=
  379. htons((u_int16_t)tcpedit->l2.vlan_cfi) << 12;
  380. break;
  381. case DLT_EN10MB:
  382. newl2len = LIBNET_ETH_H;
  383. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  384. return 0; /* unable to send packet */
  385. /* make room for L2 header */
  386. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  387. memcpy(*pktdata + LIBNET_ETH_H, (tmpbuff + oldl2len), (*pkthdr)->caplen - oldl2len);
  388. /* these fields are always set this way */
  389. sll_hdr = (sll_hdr_t *)tmpbuff;
  390. eth_hdr = (eth_hdr_t *)*pktdata;
  391. eth_hdr->ether_type = sll_hdr->sll_protocol;
  392. /* the sll header might have a src mac */
  393. if (sll_hdr->sll_halen == ETHER_ADDR_LEN)
  394. memcpy(eth_hdr->ether_shost, sll_hdr->sll_addr, ETHER_ADDR_LEN);
  395. break;
  396. default:
  397. tcpedit_seterr(tcpedit, "Invalid tcpedit->l2.dlt value: 0x%x", tcpedit->l2.dlt);
  398. return -1;
  399. break;
  400. }
  401. /* new packet len */
  402. lendiff = newl2len - oldl2len;
  403. (*pkthdr)->caplen += lendiff;
  404. (*pkthdr)->len += lendiff;
  405. return newl2len;
  406. }
  407. /*
  408. * logic to rewrite packets using DLT_C_HDLC
  409. * returns -1 on error or 0 on unable to send packet. Returns length of new
  410. * layer 2 header
  411. */
  412. int
  413. rewrite_c_hdlc(tcpedit_t *tcpedit, u_char **pktdata,
  414. struct pcap_pkthdr **pkthdr, u_char *l2data)
  415. {
  416. int oldl2len = 0, newl2len = 0, lendiff;
  417. u_char tmpbuff[MAXPACKET];
  418. hdlc_hdr_t *hdlc_hdr = NULL;
  419. eth_hdr_t *eth_hdr = NULL;
  420. vlan_hdr_t *vlan_hdr = NULL;
  421. newl2len = oldl2len = dlt2layer2len(tcpedit, DLT_C_HDLC);
  422. switch (tcpedit->l2.dlt) {
  423. case DLT_USER:
  424. /* track the new L2 len */
  425. newl2len = dlt2layer2len(tcpedit, DLT_USER);
  426. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  427. return 0; /* unable to send packet */
  428. /*
  429. * add our user specified header
  430. */
  431. dbg(3, "Rewriting packet via --dlink...");
  432. /* backup the old packet */
  433. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  434. memcpy(*pktdata, l2data, tcpedit->l2.len);
  435. memcpy(*pktdata + tcpedit->l2.len, (tmpbuff + oldl2len), (*pkthdr)->caplen - oldl2len);
  436. break;
  437. case DLT_VLAN:
  438. /* new l2 len */
  439. newl2len = dlt2layer2len(tcpedit, DLT_VLAN);
  440. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  441. return 0; /* unable to send packet */
  442. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  443. hdlc_hdr = (hdlc_hdr_t *)tmpbuff;
  444. vlan_hdr = (vlan_hdr_t *)*pktdata;
  445. memcpy(*pktdata + LIBNET_802_1Q_H, tmpbuff + oldl2len, (*pkthdr)->caplen - oldl2len);
  446. vlan_hdr->vlan_tpi = ETHERTYPE_VLAN;
  447. vlan_hdr->vlan_len = hdlc_hdr->protocol;
  448. /* user must always specify a tag */
  449. vlan_hdr->vlan_priority_c_vid |=
  450. htons((u_int16_t)tcpedit->l2.vlan_tag & LIBNET_802_1Q_VIDMASK);
  451. /* other things are optional */
  452. if (tcpedit->l2.vlan_pri)
  453. vlan_hdr->vlan_priority_c_vid |=
  454. htons((u_int16_t)tcpedit->l2.vlan_pri) << 13;
  455. if (tcpedit->l2.vlan_cfi)
  456. vlan_hdr->vlan_priority_c_vid |=
  457. htons((u_int16_t)tcpedit->l2.vlan_cfi) << 12;
  458. break;
  459. case DLT_EN10MB:
  460. newl2len = dlt2layer2len(tcpedit, DLT_EN10MB);
  461. if (! check_pkt_len(tcpedit, *pkthdr, oldl2len, newl2len))
  462. return 0; /* unable to send packet */
  463. memcpy(tmpbuff, *pktdata, (*pkthdr)->caplen);
  464. hdlc_hdr = (hdlc_hdr_t *)tmpbuff;
  465. eth_hdr = (eth_hdr_t *)*pktdata;
  466. memcpy(*pktdata + LIBNET_ETH_H, tmpbuff + oldl2len, (*pkthdr)->caplen - oldl2len);
  467. eth_hdr->ether_type = hdlc_hdr->protocol;
  468. break;
  469. default:
  470. tcpedit_seterr(tcpedit, "Invalid tcpedit->l2.dlt value: 0x%x", tcpedit->l2.dlt);
  471. return -1;
  472. break;
  473. }
  474. /* new packet len */
  475. lendiff = newl2len - oldl2len;
  476. (*pkthdr)->caplen += lendiff;
  477. (*pkthdr)->len += lendiff;
  478. return newl2len;
  479. }
  480. /*
  481. * will the new packet be too big?
  482. * If so, we have to change the (*pkthdr)->caplen to be artifically lower
  483. * so we don't go beyond tcpedit->maxpacket
  484. */
  485. static int
  486. check_pkt_len(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
  487. int oldl2len, int newl2len)
  488. {
  489. /*
  490. * is new packet too big?
  491. */
  492. if ((pkthdr->caplen - oldl2len + newl2len) > (u_int)tcpedit->maxpacket) {
  493. if (tcpedit->fixlen) {
  494. warnx("Packet length (%u) is greater then MTU (%u); "
  495. "truncating packet.",
  496. (pkthdr->caplen - oldl2len + newl2len), tcpedit->maxpacket);
  497. /* set our packet length to the max packet size */
  498. pkthdr->caplen = tcpedit->maxpacket;
  499. }
  500. else {
  501. warnx("Packet length (%u) is greater then MTU (%u); "
  502. "skipping packet.",
  503. (pkthdr->caplen - oldl2len + newl2len), tcpedit->maxpacket);
  504. return (0);
  505. }
  506. }
  507. /* all is fine */
  508. return 1;
  509. }
  510. /*
  511. Local Variables:
  512. mode:c
  513. indent-tabs-mode:nil
  514. c-basic-offset:4
  515. End:
  516. */