2 * Copyright (C) 2012-2014 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "ip_packet.h"
20 #include <utils/debug.h>
22 #include <sys/types.h>
23 #include <netinet/in.h>
24 #include <netinet/ip.h>
25 #include <netinet/udp.h>
26 #include <netinet/tcp.h>
27 #ifdef HAVE_NETINET_IP6_H
28 #include <netinet/ip6.h>
31 typedef struct private_ip_packet_t private_ip_packet_t
;
34 * Private additions to ip_packet_t.
36 struct private_ip_packet_t
{
64 * Protocol|Next Header field
70 METHOD(ip_packet_t
, get_version
, u_int8_t
,
71 private_ip_packet_t
*this)
76 METHOD(ip_packet_t
, get_source
, host_t
*,
77 private_ip_packet_t
*this)
82 METHOD(ip_packet_t
, get_destination
, host_t
*,
83 private_ip_packet_t
*this)
88 METHOD(ip_packet_t
, get_encoding
, chunk_t
,
89 private_ip_packet_t
*this)
94 METHOD(ip_packet_t
, get_next_header
, u_int8_t
,
95 private_ip_packet_t
*this)
97 return this->next_header
;
100 METHOD(ip_packet_t
, clone_
, ip_packet_t
*,
101 private_ip_packet_t
*this)
103 return ip_packet_create(chunk_clone(this->packet
));
106 METHOD(ip_packet_t
, destroy
, void,
107 private_ip_packet_t
*this)
109 this->src
->destroy(this->src
);
110 this->dst
->destroy(this->dst
);
111 chunk_free(&this->packet
);
116 * Parse transport protocol header
118 static bool parse_transport_header(chunk_t packet
, u_int8_t proto
,
119 u_int16_t
*sport
, u_int16_t
*dport
)
127 if (packet
.len
< sizeof(*udp
))
129 DBG1(DBG_ESP
, "UDP packet too short");
132 udp
= (struct udphdr
*)packet
.ptr
;
133 *sport
= ntohs(udp
->source
);
134 *dport
= ntohs(udp
->dest
);
141 if (packet
.len
< sizeof(*tcp
))
143 DBG1(DBG_ESP
, "TCP packet too short");
146 tcp
= (struct tcphdr
*)packet
.ptr
;
147 *sport
= ntohs(tcp
->source
);
148 *dport
= ntohs(tcp
->dest
);
158 * Described in header.
160 ip_packet_t
*ip_packet_create(chunk_t packet
)
162 private_ip_packet_t
*this;
163 u_int8_t version
, next_header
;
164 u_int16_t sport
= 0, dport
= 0;
169 DBG1(DBG_ESP
, "IP packet too short");
173 version
= (packet
.ptr
[0] & 0xf0) >> 4;
181 if (packet
.len
< sizeof(struct ip
))
183 DBG1(DBG_ESP
, "IPv4 packet too short");
186 ip
= (struct ip
*)packet
.ptr
;
187 /* remove any RFC 4303 TFC extra padding */
188 packet
.len
= min(packet
.len
, untoh16(&ip
->ip_len
));
190 if (!parse_transport_header(chunk_skip(packet
, ip
->ip_hl
* 4),
191 ip
->ip_p
, &sport
, &dport
))
195 src
= host_create_from_chunk(AF_INET
,
196 chunk_from_thing(ip
->ip_src
), sport
);
197 dst
= host_create_from_chunk(AF_INET
,
198 chunk_from_thing(ip
->ip_dst
), dport
);
199 next_header
= ip
->ip_p
;
202 #ifdef HAVE_NETINET_IP6_H
207 if (packet
.len
< sizeof(*ip
))
209 DBG1(DBG_ESP
, "IPv6 packet too short");
212 ip
= (struct ip6_hdr
*)packet
.ptr
;
213 /* remove any RFC 4303 TFC extra padding */
214 packet
.len
= min(packet
.len
, untoh16(&ip
->ip6_plen
));
215 /* we only handle packets without extension headers, just skip the
216 * basic IPv6 header */
217 if (!parse_transport_header(chunk_skip(packet
, 40), ip
->ip6_nxt
,
222 src
= host_create_from_chunk(AF_INET6
,
223 chunk_from_thing(ip
->ip6_src
), sport
);
224 dst
= host_create_from_chunk(AF_INET6
,
225 chunk_from_thing(ip
->ip6_dst
), dport
);
226 next_header
= ip
->ip6_nxt
;
229 #endif /* HAVE_NETINET_IP6_H */
231 DBG1(DBG_ESP
, "unsupported IP version");
237 .get_version
= _get_version
,
238 .get_source
= _get_source
,
239 .get_destination
= _get_destination
,
240 .get_next_header
= _get_next_header
,
241 .get_encoding
= _get_encoding
,
249 .next_header
= next_header
,
251 return &this->public;