ip_packet: Apply transport protocol ports when encoding IP packet
authorTobias Brunner <tobias@strongswan.org>
Tue, 15 Jul 2014 15:19:48 +0000 (17:19 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 22 Jul 2014 09:10:35 +0000 (11:10 +0200)
src/libipsec/ip_packet.c
src/libipsec/ip_packet.h

index 4ef8fd5..7de4658 100644 (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,
-                                                                  chunk_t payload)
+static void fix_transport_header(host_t *src, host_t *dst, u_int8_t proto,
+                                                                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)
        {
@@ -335,6 +338,14 @@ static void fix_transport_checksum(host_t *src, host_t *dst, u_int8_t proto,
                                return;
                        }
                        udp = (struct udphdr*)payload.ptr;
+                       if (sport != 0)
+                       {
+                               udp->source = htons(sport);
+                       }
+                       if (dport != 0)
+                       {
+                               udp->dest = htons(dport);
+                       }
                        udp->check = 0;
                        sum = pseudo_header_checksum(src, dst, proto, payload);
                        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;
                        }
                        tcp = (struct tcphdr*)payload.ptr;
+                       if (sport != 0)
+                       {
+                               tcp->source = htons(sport);
+                       }
+                       if (dport != 0)
+                       {
+                               tcp->dest = htons(dport);
+                       }
                        tcp->check = 0;
                        sum = pseudo_header_checksum(src, dst, proto, payload);
                        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));
 
                        packet = chunk_cat("cc", chunk_from_thing(ip), data);
-                       fix_transport_checksum(src, dst, next_header,
-                                                                  chunk_skip(packet, 20));
+                       fix_transport_header(src, dst, next_header, chunk_skip(packet, 20));
                        return ip_packet_create(packet);
                }
 #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));
 
                        packet = chunk_cat("cc", chunk_from_thing(ip), data);
-                       fix_transport_checksum(src, dst, next_header,
-                                                                  chunk_skip(packet, 40));
+                       fix_transport_header(src, dst, next_header, chunk_skip(packet, 40));
                        return ip_packet_create(packet);
                }
 #endif /* HAVE_NETINET_IP6_H */
index 7f7c1a3..73721cf 100644 (file)
@@ -103,8 +103,11 @@ ip_packet_t *ip_packet_create(chunk_t packet);
 /**
  * Encode an IP packet from the given data.
  *
- * @param src                  source address (cloned)
- * @param dst                  destination address (cloned)
+ * If src and/or dst have ports set they are applied to UDP/TCP headers found
+ * 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 data                 complete data after basic IP header (cloned)
  * @return                             ip_packet_t instance, or NULL if invalid