add mangle functions for IPv4/TCP and IPv4/UDP
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 31 May 2012 08:52:46 +0000 (10:52 +0200)
committerr.kubiak <r.kubiak@samsung.com>
Mon, 16 Nov 2015 13:12:06 +0000 (14:12 +0100)
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/libnetfilter_queue/libnetfilter_queue_ipv4.h
include/libnetfilter_queue/libnetfilter_queue_tcp.h
include/libnetfilter_queue/libnetfilter_queue_udp.h
include/libnetfilter_queue/pktbuff.h
src/extra/checksum.c
src/extra/ipv4.c
src/extra/ipv6.c
src/extra/pktbuff.c
src/extra/tcp.c
src/extra/udp.c
src/internal.h

index d18924e..e707f1f 100644 (file)
@@ -7,6 +7,7 @@ struct iphdr;
 struct iphdr *nfq_ip_get_hdr(struct pkt_buff *pktb);
 int nfq_ip_set_transport_header(struct pkt_buff *pktb, struct iphdr *iph);
 void nfq_ip_set_checksum(struct iphdr *iph);
+int nfq_ip_mangle(struct pkt_buff *pkt, unsigned int dataoff, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
 int nfq_ip_snprintf(char *buf, size_t size, const struct iphdr *iph);
 
 #endif
index cc965f5..c66dfb6 100644 (file)
@@ -13,6 +13,8 @@ struct ip6_hdr;
 void nfq_tcp_compute_checksum_ipv4(struct tcphdr *tcph, struct iphdr *iph);
 void nfq_tcp_compute_checksum_ipv6(struct tcphdr *tcph, struct ip6_hdr *ip6h);
 
+int nfq_tcp_mangle_ipv4(struct pkt_buff *pkt, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
+
 int nfq_tcp_snprintf(char *buf, size_t size, const struct tcphdr *tcp);
 
 #endif
index e1aeb73..f4b6c49 100644 (file)
@@ -10,6 +10,8 @@ unsigned int nfq_udp_get_payload_len(struct udphdr *udph, struct pkt_buff *pktb)
 void nfq_udp_compute_checksum_ipv4(struct udphdr *udph, struct iphdr *iph);
 void nfq_udp_compute_checksum_ipv6(struct udphdr *udph, struct ip6_hdr *ip6h);
 
+int nfq_udp_mangle_ipv4(struct pkt_buff *pkt, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
+
 int nfq_udp_snprintf(char *buf, size_t size, const struct udphdr *udp);
 
 #endif
index a0e7abf..b15ee1e 100644 (file)
@@ -19,4 +19,8 @@ uint8_t *pktb_mac_header(struct pkt_buff *pktb);
 uint8_t *pktb_network_header(struct pkt_buff *pktb);
 uint8_t *pktb_transport_header(struct pkt_buff *pktb);
 
+int pktb_mangle(struct pkt_buff *pkt, unsigned int dataoff, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
+
+bool pktb_mangled(const struct pkt_buff *pktb);
+
 #endif
index d0c4167..6f07e71 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
index 200a20e..ce101ef 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 
@@ -90,6 +91,24 @@ void nfq_ip_set_checksum(struct iphdr *iph)
 }
 EXPORT_SYMBOL(nfq_ip_set_checksum);
 
+int nfq_ip_mangle(struct pkt_buff *pkt, unsigned int dataoff,
+                 unsigned int match_offset, unsigned int match_len,
+                 const char *rep_buffer, unsigned int rep_len)
+{
+       struct iphdr *iph = (struct iphdr *) pkt->network_header;
+
+       if (!pktb_mangle(pkt, dataoff, match_offset, match_len,
+                                               rep_buffer, rep_len))
+               return 0;
+
+       /* fix IP hdr checksum information */
+       iph->tot_len = htons(pkt->len);
+       nfq_ip_set_checksum(iph);
+
+       return 1;
+}
+EXPORT_SYMBOL(nfq_ip_mangle);
+
 /**
  * nfq_pkt_snprintf_ip - print IPv4 header into buffer in iptables LOG format
  * \param buf: pointer to buffer that will be used to print the header
index 0457016..7c5dc9b 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <stdio.h>
 #include <stddef.h>
+#include <stdbool.h>
 #include <arpa/inet.h>
 #include <netinet/ip6.h>
 
index 809953b..e9ca5da 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <stdlib.h>
 #include <string.h> /* for memcpy */
+#include <stdbool.h>
 
 #include <netinet/if_ether.h>
 #include <netinet/ip.h>
@@ -137,6 +138,67 @@ uint8_t *pktb_transport_header(struct pkt_buff *pktb)
        return pktb->transport_header;
 }
 
+static int pktb_expand_tail(struct pkt_buff *pkt, int extra)
+{
+       /* XXX: support reallocation case. */
+       pkt->len += extra;
+       pkt->tail = pkt->tail + extra;
+       return 0;
+}
+
+static int enlarge_pkt(struct pkt_buff *pkt, unsigned int extra)
+{
+       if (pkt->len + extra > 65535)
+               return 0;
+
+       if (pktb_expand_tail(pkt, extra - pktb_tailroom(pkt)))
+               return 0;
+
+       return 1;
+}
+
+int pktb_mangle(struct pkt_buff *pkt,
+                unsigned int dataoff,
+                unsigned int match_offset,
+                unsigned int match_len,
+                const char *rep_buffer,
+                unsigned int rep_len)
+{
+       unsigned char *data;
+
+       if (rep_len > match_len &&
+           rep_len - match_len > pktb_tailroom(pkt) &&
+           !enlarge_pkt(pkt, rep_len - match_len))
+               return 0;
+
+       data = pkt->network_header + dataoff;
+
+       /* move post-replacement */
+       memmove(data + match_offset + rep_len,
+               data + match_offset + match_len,
+               pkt->tail - (pkt->network_header + dataoff +
+                            match_offset + match_len));
+
+       /* insert data from buffer */
+       memcpy(data + match_offset, rep_buffer, rep_len);
+
+       /* update pkt info */
+       if (rep_len > match_len)
+               pktb_put(pkt, rep_len - match_len);
+       else
+               pktb_trim(pkt, pkt->len + rep_len - match_len);
+
+       pkt->mangled = true;
+       return 1;
+}
+EXPORT_SYMBOL(pktb_mangle);
+
+bool pktb_mangled(const struct pkt_buff *pkt)
+{
+       return pkt->mangled;
+}
+EXPORT_SYMBOL(pktb_mangled);
+
 /**
  * @}
  */
index 9de3748..2ea0d8a 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <stdio.h>
 #include <string.h> /* for memcpy */
+#include <stdbool.h>
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
@@ -18,6 +19,7 @@
 
 #include <libnetfilter_queue/libnetfilter_queue.h>
 #include <libnetfilter_queue/libnetfilter_queue_tcp.h>
+#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
 #include <libnetfilter_queue/pktbuff.h>
 
 #include "internal.h"
@@ -134,12 +136,12 @@ int nfq_tcp_snprintf(char *buf, size_t size, const struct tcphdr *tcph)
 #define TCP_RESERVED_BITS htonl(0x0F000000)
 
        ret = snprintf(buf, size, "SPT=%u DPT=%u SEQ=%u ACK=%u "
-                                  "WINDOW=%u RES=%0x%02x ",
+                                  "WINDOW=%u RES=0x%02x ",
                        ntohs(tcph->source), ntohs(tcph->dest),
                        ntohl(tcph->seq), ntohl(tcph->ack_seq),
                        ntohs(tcph->window),
-                       (uint8_t)(ntohl(tcp_flag_word(tcph) &
-                               TCP_RESERVED_BITS) >> 22));
+                       (uint8_t)
+                       (ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
        len += ret;
 
        if (tcph->urg) {
@@ -166,10 +168,33 @@ int nfq_tcp_snprintf(char *buf, size_t size, const struct tcphdr *tcph)
                ret = snprintf(buf+len, size-len, "FIN ");
                len += ret;
        }
-       /* Not TCP options implemented yet, sorry. */
+       /* XXX: Not TCP options implemented yet, sorry. */
+
+       return ret;
 }
 EXPORT_SYMBOL(nfq_tcp_snprintf);
 
+int
+nfq_tcp_mangle_ipv4(struct pkt_buff *pkt,
+                   unsigned int match_offset, unsigned int match_len,
+                   const char *rep_buffer, unsigned int rep_len)
+{
+       struct iphdr *iph;
+       struct tcphdr *tcph;
+
+       iph = (struct iphdr *)pkt->network_header;
+       tcph = (struct tcphdr *)(pkt->network_header + iph->ihl*4);
+
+       if (!nfq_ip_mangle(pkt, iph->ihl*4 + tcph->doff*4,
+                               match_offset, match_len, rep_buffer, rep_len))
+               return 0;
+
+       nfq_tcp_compute_checksum_ipv4(tcph, iph);
+
+       return 1;
+}
+EXPORT_SYMBOL(nfq_tcp_mangle_ipv4);
+
 /**
  * @}
  */
index c0b1b7d..5f7f9ec 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
@@ -17,6 +18,7 @@
 
 #include <libnetfilter_queue/libnetfilter_queue.h>
 #include <libnetfilter_queue/libnetfilter_queue_udp.h>
+#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
 #include <libnetfilter_queue/pktbuff.h>
 
 #include "internal.h"
@@ -112,6 +114,27 @@ nfq_udp_compute_checksum_ipv6(struct udphdr *udph, struct ip6_hdr *ip6h)
 }
 EXPORT_SYMBOL(nfq_udp_compute_checksum_ipv6);
 
+int
+nfq_udp_mangle_ipv4(struct pkt_buff *pkt,
+                   unsigned int match_offset, unsigned int match_len,
+                   const char *rep_buffer, unsigned int rep_len)
+{
+       struct iphdr *iph;
+       struct udphdr *udph;
+
+       iph = (struct iphdr *)pkt->network_header;
+       udph = (struct udphdr *)(pkt->network_header + iph->ihl*4);
+
+       if (!nfq_ip_mangle(pkt, iph->ihl*4 + sizeof(struct udphdr),
+                               match_offset, match_len, rep_buffer, rep_len))
+               return 0;
+
+       nfq_udp_compute_checksum_ipv4(udph, iph);
+
+       return 1;
+}
+EXPORT_SYMBOL(nfq_udp_mangle_ipv4);
+
 /**
  * nfq_pkt_snprintf_udp_hdr - print udp header into one buffer in a humnan
  * readable way
index 477dc70..37bf79e 100644 (file)
@@ -27,6 +27,8 @@ struct pkt_buff {
 
        uint32_t len;
        uint32_t data_len;
+
+       bool    mangled;
 };
 
 #endif