-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2013 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
uint16_t id;
uint32_t flow;
uint8_t class;
- struct in6_addr src6, dst6;
+ struct libnet_in6_addr src6, dst6;
uint32_t src4, dst4;
uint16_t sp, dp;
size_t len;
return 0;
}
+int RejectSendLibnet11L3IPv6TCP(ThreadVars *tv, Packet *p, void *data, int dir)
+{
+
+ Libnet11Packet lpacket;
+ libnet_t *c; /* libnet context */
+ char ebuf[LIBNET_ERRBUF_SIZE];
+ int result;
+ char *devname = NULL;
+
+ /* fill in struct defaults */
+ lpacket.ttl = 0;
+ lpacket.id = 0;
+ lpacket.flow = 0;
+ lpacket.class = 0;
+
+ if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode) && (p->livedev)) {
+ devname = p->livedev->dev;
+ }
+ if ((c = libnet_init(LIBNET_RAW6, devname, ebuf)) == NULL) {
+ SCLogError(SC_ERR_LIBNET_INIT,"libnet_init failed: %s", ebuf);
+ return 1;
+ }
+
+ if (p->tcph == NULL)
+ return 1;
+
+ /* save payload len */
+ lpacket.dsize = p->payload_len;
+
+ switch (dir) {
+ case REJECT_DIR_SRC:
+ SCLogDebug("sending a tcp reset to src");
+ /* We follow http://tools.ietf.org/html/rfc793#section-3.4 :
+ * If packet has no ACK, the seq number is 0 and the ACK is built
+ * the normal way. If packet has a ACK, the seq of the RST packet
+ * is equal to the ACK of incoming packet and the ACK is build
+ * using packet sequence number and size of the data. */
+ if (TCP_GET_ACK(p) == 0) {
+ lpacket.seq = 0;
+ lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize + 1;
+ } else {
+ lpacket.seq = TCP_GET_ACK(p);
+ lpacket.ack = TCP_GET_SEQ(p) + lpacket.dsize;
+ }
+
+ lpacket.sp = TCP_GET_DST_PORT(p);
+ lpacket.dp = TCP_GET_SRC_PORT(p);
+
+ memcpy(lpacket.src6.libnet_s6_addr, GET_IPV6_DST_ADDR(p), 16);
+ memcpy(lpacket.dst6.libnet_s6_addr, GET_IPV6_SRC_ADDR(p), 16);
+
+ break;
+ case REJECT_DIR_DST:
+ SCLogDebug("sending a tcp reset to dst");
+ lpacket.seq = TCP_GET_SEQ(p);
+ lpacket.ack = TCP_GET_ACK(p);
+
+ lpacket.sp = TCP_GET_SRC_PORT(p);
+ lpacket.dp = TCP_GET_DST_PORT(p);
+
+ memcpy(lpacket.src6.libnet_s6_addr, GET_IPV6_SRC_ADDR(p), 16);
+ memcpy(lpacket.dst6.libnet_s6_addr, GET_IPV6_DST_ADDR(p), 16);
+ break;
+ default:
+ SCLogError(SC_ERR_LIBNET_INVALID_DIR,
+ "reset not src or dst returning");
+ return 1;
+ }
+
+ lpacket.window = TCP_GET_WINDOW(p);
+ //lpacket.seq += lpacket.dsize;
+
+ /* TODO come up with ttl calc function */
+ lpacket.ttl = 64;
+
+ /* build the package */
+ if ((libnet_build_tcp(
+ lpacket.sp, /* source port */
+ lpacket.dp, /* dst port */
+ lpacket.seq, /* seq number */
+ lpacket.ack, /* ack number */
+ TH_RST|TH_ACK, /* flags */
+ lpacket.window, /* window size */
+ 0, /* checksum */
+ 0, /* urgent flag */
+ LIBNET_TCP_H, /* header length */
+ NULL, /* payload */
+ 0, /* payload length */
+ c, /* libnet context */
+ 0)) < 0) /* libnet ptag */
+ {
+ SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_tcp %s", libnet_geterror(c));
+ goto cleanup;
+ }
+
+ if ((libnet_build_ipv6(
+ lpacket.class, /* traffic class */
+ lpacket.flow, /* Flow label */
+ LIBNET_TCP_H, /* payload length */
+ IPPROTO_TCP, /* next header */
+ lpacket.ttl, /* TTL */
+ lpacket.src6, /* source address */
+ lpacket.dst6, /* destination address */
+ NULL, /* pointer to packet data (or NULL) */
+ 0, /* payload length */
+ c, /* libnet context pointer */
+ 0)) < 0) /* packet id */
+ {
+ SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv6 %s", libnet_geterror(c));
+ goto cleanup;
+ }
+
+ result = libnet_write(c);
+ if (result == -1) {
+ SCLogError(SC_ERR_LIBNET_WRITE_FAILED,"libnet_write failed: %s", libnet_geterror(c));
+ goto cleanup;
+ }
+
+cleanup:
+ libnet_destroy (c);
+ return 0;
+}
+
+#ifdef HAVE_LIBNET_ICMPV6_UNREACH
+int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
+{
+ Libnet11Packet lpacket;
+ libnet_t *c; /* libnet context */
+ char ebuf[LIBNET_ERRBUF_SIZE];
+ int result;
+ char *devname = NULL;
+
+ /* fill in struct defaults */
+ lpacket.ttl = 0;
+ lpacket.id = 0;
+ lpacket.flow = 0;
+ lpacket.class = 0;
+
+
+ lpacket.len = IPV6_GET_PLEN(p) + IPV6_HEADER_LEN;
+
+ if (IS_SURI_HOST_MODE_SNIFFER_ONLY(host_mode) && (p->livedev)) {
+ devname = p->livedev->dev;
+ }
+ if ((c = libnet_init(LIBNET_RAW6, devname, ebuf)) == NULL) {
+ SCLogError(SC_ERR_LIBNET_INIT,"libnet_inint failed: %s", ebuf);
+ return 1;
+ }
+
+ switch (dir) {
+ case REJECT_DIR_SRC:
+ memcpy(lpacket.src6.libnet_s6_addr, GET_IPV6_DST_ADDR(p), 16);
+ memcpy(lpacket.dst6.libnet_s6_addr, GET_IPV6_SRC_ADDR(p), 16);
+ break;
+ case REJECT_DIR_DST:
+ memcpy(lpacket.src6.libnet_s6_addr, GET_IPV6_SRC_ADDR(p), 16);
+ memcpy(lpacket.dst6.libnet_s6_addr, GET_IPV6_DST_ADDR(p), 16);
+ break;
+ default:
+ SCLogError(SC_ERR_LIBNET_INVALID_DIR,
+ "reset not src or dst returning");
+ return 1;
+ }
+
+ /* TODO come up with ttl calc function */
+ lpacket.ttl = 64;
+
+ /* build the package */
+ if ((libnet_build_icmpv6_unreach(
+ ICMP6_DST_UNREACH, /* type */
+ ICMP6_DST_UNREACH_ADMIN, /* code */
+ 0, /* checksum */
+ (uint8_t *)p->ip6h, /* payload */
+ lpacket.len, /* payload length */
+ c, /* libnet context */
+ 0)) < 0) /* libnet ptag */
+ {
+ SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_icmpv6_unreach %s", libnet_geterror(c));
+ goto cleanup;
+ }
+
+ if ((libnet_build_ipv6(
+ lpacket.class, /* traffic class */
+ lpacket.flow, /* Flow label */
+ LIBNET_ICMPV6_H + lpacket.len, /* IPv6 payload length */
+ IPPROTO_ICMPV6, /* next header */
+ lpacket.ttl, /* TTL */
+ lpacket.src6, /* source address */
+ lpacket.dst6, /* destination address */
+ NULL, /* pointer to packet data (or NULL) */
+ 0, /* payload length */
+ c, /* libnet context pointer */
+ 0)) < 0) /* packet id */
+ {
+ SCLogError(SC_ERR_LIBNET_BUILD_FAILED,"libnet_build_ipv6 %s", libnet_geterror(c));
+ goto cleanup;
+ }
+
+ result = libnet_write(c);
+ if (result == -1) {
+ SCLogError(SC_ERR_LIBNET_WRITE_FAILED,"libnet_write_raw_ipv6 failed: %s", libnet_geterror(c));
+ goto cleanup;
+ }
+
+cleanup:
+ libnet_destroy (c);
+ return 0;
+}
+#else /* HAVE_LIBNET_ICMPV6_UNREACH */
+
+int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
+{
+ SCLogError(SC_ERR_LIBNET_NOT_ENABLED, "Libnet ICMPv6 based rejects are disabled."
+ "Usually this means that you don't have a patched libnet installed,"
+ " or configure couldn't find it.");
+}
+#endif /* HAVE_LIBNET_ICMPV6_UNREACH */
+
+
#else
int RejectSendLibnet11L3IPv4TCP(ThreadVars *tv, Packet *p, void *data, int dir)
return 0;
}
+int RejectSendLibnet11L3IPv6TCP(ThreadVars *tv, Packet *p, void *data, int dir)
+{
+ SCLogError(SC_ERR_LIBNET_NOT_ENABLED, "Libnet based rejects are disabled."
+ "Usually this means that you don't have libnet installed,"
+ " or configure couldn't find it.");
+ return 0;
+}
+
+int RejectSendLibnet11L3IPv6ICMP(ThreadVars *tv, Packet *p, void *data, int dir)
+{
+ SCLogError(SC_ERR_LIBNET_NOT_ENABLED, "Libnet based rejects are disabled."
+ "Usually this means that you don't have libnet installed,"
+ " or configure couldn't find it.");
+ return 0;
+}
+
#endif /* HAVE_LIBNET11 */
return 0;
}
-/** \todo implement */
int RejectSendIPv6TCP(ThreadVars *tv, Packet *p, void *data) {
SCEnter();
- SCLogDebug("we would send a ipv6 tcp reset here");
+ if (PACKET_TEST_ACTION(p, ACTION_REJECT)) {
+ return RejectSendLibnet11L3IPv6TCP(tv, p, data, REJECT_DIR_SRC);
+ } else if (PACKET_TEST_ACTION(p, ACTION_REJECT_DST)) {
+ return RejectSendLibnet11L3IPv6TCP(tv, p, data, REJECT_DIR_DST);
+ } else if(PACKET_TEST_ACTION(p, ACTION_REJECT_BOTH)) {
+ if (RejectSendLibnet11L3IPv6TCP(tv, p, data, REJECT_DIR_SRC) == 0 &&
+ RejectSendLibnet11L3IPv6TCP(tv, p, data, REJECT_DIR_DST) == 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
SCReturnInt(0);
}
-/** \todo implement */
int RejectSendIPv6ICMP(ThreadVars *tv, Packet *p, void *data) {
SCEnter();
- SCLogDebug("we would send a ipv6 icmp reset here");
+ if (PACKET_TEST_ACTION(p, ACTION_REJECT)) {
+ return RejectSendLibnet11L3IPv6ICMP(tv, p, data, REJECT_DIR_SRC);
+ } else if (PACKET_TEST_ACTION(p, ACTION_REJECT_DST)) {
+ return RejectSendLibnet11L3IPv6ICMP(tv, p, data, REJECT_DIR_DST);
+ } else if(PACKET_TEST_ACTION(p, ACTION_REJECT_BOTH)) {
+ if (RejectSendLibnet11L3IPv6ICMP(tv, p, data, REJECT_DIR_SRC) == 0 &&
+ RejectSendLibnet11L3IPv6ICMP(tv, p, data, REJECT_DIR_DST) == 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
SCReturnInt(0);
}