ip_packet_t parses the header of IP packets
authorTobias Brunner <tobias@strongswan.org>
Fri, 13 Jul 2012 13:05:27 +0000 (15:05 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Aug 2012 13:41:03 +0000 (15:41 +0200)
src/libipsec/Android.mk
src/libipsec/Makefile.am
src/libipsec/ip_packet.c [new file with mode: 0644]
src/libipsec/ip_packet.h [new file with mode: 0644]

index 269f39b..698e12f 100644 (file)
@@ -6,6 +6,7 @@ LOCAL_SRC_FILES := \
 ipsec.c ipsec.h \
 esp_context.c esp_context.h \
 esp_packet.c esp_packet.h \
+ip_packet.c ip_packet.h \
 ipsec_event_listener.h \
 ipsec_event_relay.c ipsec_event_relay.h \
 ipsec_policy.c ipsec_policy.h \
index ec5745a..3dfa41f 100644 (file)
@@ -4,6 +4,7 @@ libipsec_la_SOURCES = \
 ipsec.c ipsec.h \
 esp_context.c esp_context.h \
 esp_packet.c esp_packet.h \
+ip_packet.c ip_packet.h \
 ipsec_event_listener.h \
 ipsec_event_relay.c ipsec_event_relay.h \
 ipsec_policy.c ipsec_policy.h \
diff --git a/src/libipsec/ip_packet.c b/src/libipsec/ip_packet.c
new file mode 100644 (file)
index 0000000..c78c238
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "ip_packet.h"
+
+#include <library.h>
+#include <debug.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+
+typedef struct private_ip_packet_t private_ip_packet_t;
+
+/**
+ * Private additions to ip_packet_t.
+ */
+struct private_ip_packet_t {
+
+       /**
+        * Public members
+        */
+       ip_packet_t public;
+
+       /**
+        * Source address
+        */
+       host_t *src;
+
+       /**
+        * Destination address
+        */
+       host_t *dst;
+
+       /**
+        * IP packet
+        */
+       chunk_t packet;
+
+       /**
+        * IP version
+        */
+       u_int8_t version;
+
+       /**
+        * Protocol|Next Header field
+        */
+       u_int8_t next_header;
+
+};
+
+METHOD(ip_packet_t, get_version, u_int8_t,
+       private_ip_packet_t *this)
+{
+       return this->version;
+}
+
+METHOD(ip_packet_t, get_source, host_t*,
+       private_ip_packet_t *this)
+{
+       return this->src;
+}
+
+METHOD(ip_packet_t, get_destination, host_t*,
+       private_ip_packet_t *this)
+{
+       return this->dst;
+}
+
+METHOD(ip_packet_t, get_encoding, chunk_t,
+       private_ip_packet_t *this)
+{
+       return this->packet;
+}
+
+METHOD(ip_packet_t, get_next_header, u_int8_t,
+       private_ip_packet_t *this)
+{
+       return this->next_header;
+}
+
+METHOD(ip_packet_t, clone, ip_packet_t*,
+       private_ip_packet_t *this)
+{
+       return ip_packet_create(this->packet);
+}
+
+METHOD(ip_packet_t, destroy, void,
+       private_ip_packet_t *this)
+{
+       this->src->destroy(this->src);
+       this->dst->destroy(this->dst);
+       chunk_free(&this->packet);
+       free(this);
+}
+
+/**
+ * Described in header.
+ */
+ip_packet_t *ip_packet_create(chunk_t packet)
+{
+       private_ip_packet_t *this;
+       u_int8_t version, next_header;
+       host_t *src, *dst;
+
+       if (packet.len < 1)
+       {
+               DBG1(DBG_ESP, "IP packet too short");
+               goto failed;
+       }
+
+       version = (packet.ptr[0] & 0xf0) >> 4;
+
+       switch (version)
+       {
+               case 4:
+               {
+                       struct iphdr *ip;
+
+                       if (packet.len < sizeof(struct iphdr))
+                       {
+                               DBG1(DBG_ESP, "IPv4 packet too short");
+                               goto failed;
+                       }
+                       ip = (struct iphdr*)packet.ptr;
+                       src = host_create_from_chunk(AF_INET,
+                                                                                chunk_from_thing(ip->saddr), 0);
+                       dst = host_create_from_chunk(AF_INET,
+                                                                                chunk_from_thing(ip->daddr), 0);
+                       next_header = ip->protocol;
+                       break;
+               }
+               case 6:
+               {
+                       struct ip6_hdr *ip;
+
+                       if (packet.len < sizeof(struct ip6_hdr))
+                       {
+                               DBG1(DBG_ESP, "IPv6 packet too short");
+                               goto failed;
+                       }
+                       ip = (struct ip6_hdr*)packet.ptr;
+                       src = host_create_from_chunk(AF_INET6,
+                                                                                chunk_from_thing(ip->ip6_src), 0);
+                       dst = host_create_from_chunk(AF_INET6,
+                                                                                chunk_from_thing(ip->ip6_dst), 0);
+                       next_header = ip->ip6_nxt;
+               }
+               default:
+                       DBG1(DBG_ESP, "unsupported IP version");
+                       goto failed;
+       }
+
+       INIT(this,
+               .public = {
+                       .get_version = _get_version,
+                       .get_source = _get_source,
+                       .get_destination = _get_destination,
+                       .get_next_header = _get_next_header,
+                       .get_encoding = _get_encoding,
+                       .clone = _clone,
+                       .destroy = _destroy,
+               },
+               .src = src,
+               .dst = dst,
+               .packet = packet,
+               .version = version,
+               .next_header = next_header,
+       );
+       return &this->public;
+
+failed:
+       chunk_free(&packet);
+       return NULL;
+}
diff --git a/src/libipsec/ip_packet.h b/src/libipsec/ip_packet.h
new file mode 100644 (file)
index 0000000..b4fc298
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ip_packet ip_packet
+ * @{ @ingroup libipsec
+ */
+
+#ifndef IP_PACKET_H_
+#define IP_PACKET_H_
+
+#include <library.h>
+#include <utils/host.h>
+#include <utils/packet.h>
+
+typedef struct ip_packet_t ip_packet_t;
+
+/**
+ *  IP packet
+ */
+struct ip_packet_t {
+
+       /**
+        * IP version of this packet
+        *
+        * @return                              ip version
+        */
+       u_int8_t (*get_version)(ip_packet_t *this);
+
+       /**
+        * Get the source address of this packet
+        *
+        * @return                              source host
+        */
+       host_t *(*get_source)(ip_packet_t *this);
+
+       /**
+        * Get the destination address of this packet
+        *
+        * @return                              destination host
+        */
+       host_t *(*get_destination)(ip_packet_t *this);
+
+       /**
+        * Get the protocol (IPv4) or next header (IPv6) field of this packet.
+        *
+        * @return                              protocol|next header field
+        */
+       u_int8_t (*get_next_header)(ip_packet_t *this);
+
+       /**
+        * Get the complete IP packet (including the header)
+        *
+        * @return                              IP packet (internal data)
+        */
+       chunk_t (*get_encoding)(ip_packet_t *this);
+
+       /**
+        * Clone the IP packet
+        *
+        * @return                              clone of the packet
+        */
+       ip_packet_t *(*clone)(ip_packet_t *this);
+
+       /**
+        * Destroy an ip_packet_t
+        */
+       void (*destroy)(ip_packet_t *this);
+
+};
+
+/**
+ * Create an IP packet out of data from the wire (or decapsulated from another
+ * packet).
+ *
+ * @note The raw IP packet gets either owned by the new object, or destroyed,
+ * if the data is invalid.
+ *
+ * @param packet               the IP packet (including header), gets owned
+ * @return                             ip_packet_t instance, or NULL if invalid
+ */
+ip_packet_t *ip_packet_create(chunk_t packet);
+
+#endif /** IP_PACKET_H_ @}*/