summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-06-07 21:34:35 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2013-06-07 21:35:23 +0200
commit140bde424c1381353f37ebc3395305f2acfcf546 (patch)
tree86ffb8d6f9a1503869a1966f2eda36d360636498
parentad9c4a919976a49246d74f751afe5da567328b54 (diff)
cthelper: add IPv6 support
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/cthelper.c70
1 files changed, 46 insertions, 24 deletions
diff --git a/src/cthelper.c b/src/cthelper.c
index 307be96..f333625 100644
--- a/src/cthelper.c
+++ b/src/cthelper.c
@@ -30,6 +30,7 @@
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <net/ethernet.h>
@@ -77,6 +78,8 @@ nfq_hdr_put(char *buf, int type, uint32_t queue_num)
static int
pkt_get(void *pkt, uint32_t pktlen, uint16_t proto, uint32_t *protoff)
{
+ uint8_t protocol;
+
switch(proto) {
case ETHERTYPE_IP: {
struct iphdr *ip = (struct iphdr *) pkt;
@@ -94,41 +97,60 @@ pkt_get(void *pkt, uint32_t pktlen, uint16_t proto, uint32_t *protoff)
}
*protoff = 4 * ip->ihl;
+ protocol = ip->protocol;
+ break;
+ }
+ case ETHERTYPE_IPV6: {
+ struct iphdr *ip = (struct iphdr *) pkt;
+ struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
- switch (ip->protocol) {
- case IPPROTO_TCP: {
- struct tcphdr *tcph =
- (struct tcphdr *) ((char *)pkt + *protoff);
-
- /* No room for IPv4 header plus TCP header. */
- if (pktlen < *protoff + sizeof(struct tcphdr)
- || pktlen < *protoff + tcph->doff * 4) {
- dlog(LOG_ERR, "no room for IPv4 + TCP header, skip");
- return -1;
- }
- return 0;
+ /* No room for IPv6 header. */
+ if (pktlen < sizeof(struct ip6_hdr)) {
+ dlog(LOG_ERR, "no room for IPv6 header");
+ return -1;
}
- case IPPROTO_UDP:
- /* No room for IPv4 header plus UDP header. */
- if (pktlen < *protoff + sizeof(struct udphdr)) {
- dlog(LOG_ERR, "no room for IPv4 + UDP header, skip");
- return -1;
- }
- return 0;
- default:
- dlog(LOG_ERR, "not TCP/UDP, skipping");
+
+ /* this is not IPv6, skip. */
+ if (ip->version != 6) {
+ dlog(LOG_ERR, "not IPv6, skipping");
return -1;
}
+
+ *protoff = sizeof(struct ip6_hdr);
+ protocol = ip6->ip6_nxt;
break;
}
- case ETHERTYPE_IPV6:
- dlog(LOG_ERR, "no IPv6 support sorry");
- return 0;
default:
/* Unknown layer 3 protocol. */
dlog(LOG_ERR, "unknown layer 3 protocol (%d), skipping", proto);
return -1;
}
+
+ switch (protocol) {
+ case IPPROTO_TCP: {
+ struct tcphdr *tcph =
+ (struct tcphdr *) ((char *)pkt + *protoff);
+
+ /* No room for IPv4 header plus TCP header. */
+ if (pktlen < *protoff + sizeof(struct tcphdr) ||
+ pktlen < *protoff + tcph->doff * 4) {
+ dlog(LOG_ERR, "no room for IPv4 + TCP header, skip");
+ return -1;
+ }
+ return 0;
+ }
+ case IPPROTO_UDP:
+ /* No room for IPv4 header plus UDP header. */
+ if (pktlen < *protoff + sizeof(struct udphdr)) {
+ dlog(LOG_ERR, "no room for IPv4 + UDP header, skip");
+ return -1;
+ }
+ return 0;
+ default:
+ dlog(LOG_ERR, "not TCP/UDP, skipping");
+ return -1;
+ }
+
return 0;
}