ip_packet: Apply transport protocol ports when encoding IP packet

This commit is contained in:
Tobias Brunner
2014-07-22 11:10:35 +02:00
parent 46bb36980b
commit 108a67893f
2 changed files with 30 additions and 10 deletions
+25 -8
View File
@@ -317,12 +317,15 @@ static u_int16_t pseudo_header_checksum(host_t *src, host_t *dst,
} }
/** /**
* Calculate transport header checksums * Apply transport ports and calculate header checksums
*/ */
static void fix_transport_checksum(host_t *src, host_t *dst, u_int8_t proto, static void fix_transport_header(host_t *src, host_t *dst, u_int8_t proto,
chunk_t payload) chunk_t payload)
{ {
u_int16_t sum = 0; u_int16_t sum = 0, sport, dport;
sport = src->get_port(src);
dport = dst->get_port(dst);
switch (proto) switch (proto)
{ {
@@ -335,6 +338,14 @@ static void fix_transport_checksum(host_t *src, host_t *dst, u_int8_t proto,
return; return;
} }
udp = (struct udphdr*)payload.ptr; udp = (struct udphdr*)payload.ptr;
if (sport != 0)
{
udp->source = htons(sport);
}
if (dport != 0)
{
udp->dest = htons(dport);
}
udp->check = 0; udp->check = 0;
sum = pseudo_header_checksum(src, dst, proto, payload); sum = pseudo_header_checksum(src, dst, proto, payload);
udp->check = chunk_internet_checksum_inc(payload, sum); udp->check = chunk_internet_checksum_inc(payload, sum);
@@ -349,6 +360,14 @@ static void fix_transport_checksum(host_t *src, host_t *dst, u_int8_t proto,
return; return;
} }
tcp = (struct tcphdr*)payload.ptr; tcp = (struct tcphdr*)payload.ptr;
if (sport != 0)
{
tcp->source = htons(sport);
}
if (dport != 0)
{
tcp->dest = htons(dport);
}
tcp->check = 0; tcp->check = 0;
sum = pseudo_header_checksum(src, dst, proto, payload); sum = pseudo_header_checksum(src, dst, proto, payload);
tcp->check = chunk_internet_checksum_inc(payload, sum); tcp->check = chunk_internet_checksum_inc(payload, sum);
@@ -391,8 +410,7 @@ ip_packet_t *ip_packet_create_from_data(host_t *src, host_t *dst,
ip.ip_sum = chunk_internet_checksum(chunk_from_thing(ip)); ip.ip_sum = chunk_internet_checksum(chunk_from_thing(ip));
packet = chunk_cat("cc", chunk_from_thing(ip), data); packet = chunk_cat("cc", chunk_from_thing(ip), data);
fix_transport_checksum(src, dst, next_header, fix_transport_header(src, dst, next_header, chunk_skip(packet, 20));
chunk_skip(packet, 20));
return ip_packet_create(packet); return ip_packet_create(packet);
} }
#ifdef HAVE_NETINET_IP6_H #ifdef HAVE_NETINET_IP6_H
@@ -408,8 +426,7 @@ ip_packet_t *ip_packet_create_from_data(host_t *src, host_t *dst,
memcpy(&ip.ip6_dst, dst->get_address(dst).ptr, sizeof(ip.ip6_dst)); memcpy(&ip.ip6_dst, dst->get_address(dst).ptr, sizeof(ip.ip6_dst));
packet = chunk_cat("cc", chunk_from_thing(ip), data); packet = chunk_cat("cc", chunk_from_thing(ip), data);
fix_transport_checksum(src, dst, next_header, fix_transport_header(src, dst, next_header, chunk_skip(packet, 40));
chunk_skip(packet, 40));
return ip_packet_create(packet); return ip_packet_create(packet);
} }
#endif /* HAVE_NETINET_IP6_H */ #endif /* HAVE_NETINET_IP6_H */
+5 -2
View File
@@ -103,8 +103,11 @@ ip_packet_t *ip_packet_create(chunk_t packet);
/** /**
* Encode an IP packet from the given data. * Encode an IP packet from the given data.
* *
* @param src source address (cloned) * If src and/or dst have ports set they are applied to UDP/TCP headers found
* @param dst destination address (cloned) * in the packet.
*
* @param src source address and optional port (cloned)
* @param dst destination address and optional port (cloned)
* @param next_header the protocol (IPv4) or next header (IPv6) * @param next_header the protocol (IPv4) or next header (IPv6)
* @param data complete data after basic IP header (cloned) * @param data complete data after basic IP header (cloned)
* @return ip_packet_t instance, or NULL if invalid * @return ip_packet_t instance, or NULL if invalid