summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dhcp.c79
-rw-r--r--forward.c2
2 files changed, 52 insertions, 29 deletions
diff --git a/dhcp.c b/dhcp.c
index 3474a17..280a4af 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -66,20 +66,20 @@ get_dhcp_message_type (const struct dhcp *dhcp, const int optlen)
}
static in_addr_t
-do_extract (struct dhcp *dhcp, const int optlen)
+do_extract (struct dhcp *dhcp, int optlen)
{
uint8_t *p = (uint8_t *) (dhcp + 1);
int i;
in_addr_t ret = 0;
- for (i = 0; i < optlen; ++i)
+ for (i = 0; i < optlen; )
{
const uint8_t type = p[i];
const int room = optlen - i;
if (type == DHCP_END)
break;
else if (type == DHCP_PAD)
- ;
+ ++i;
else if (type == DHCP_ROUTER)
{
if (room >= 2)
@@ -87,23 +87,39 @@ do_extract (struct dhcp *dhcp, const int optlen)
const int len = p[i+1]; /* get option length */
if (len <= (room-2))
{
+ /* get router IP address */
if (!ret && len >= 4 && (len & 3) == 0)
{
- memcpy (&ret, p+i+2, 4); /* get router IP address */
+ memcpy (&ret, p+i+2, 4);
ret = ntohl (ret);
}
- memset (p+i, DHCP_PAD, len+2); /* delete the router option by padding it out */
+ {
+ /* delete the router option */
+ uint8_t *dest = p + i;
+ const int owlen = len + 2; /* len of data to overwrite */
+ uint8_t *src = dest + owlen;
+ uint8_t *end = p + optlen;
+ const int movlen = end - src;
+ if (movlen > 0)
+ memmove(dest, src, movlen); /* overwrite router option */
+ memset(end - owlen, DHCP_PAD, owlen); /* pad tail */
+ }
}
- i += (len + 1); /* advance to next option */
+ else
+ break;
}
+ else
+ break;
}
- else /* some other option */
+ else /* some other option */
{
if (room >= 2)
{
- const int len = p[i+1]; /* get option length */
- i += (len + 1); /* advance to next option */
+ const int len = p[i+1]; /* get option length */
+ i += (len + 2); /* advance to next option */
}
+ else
+ break;
}
}
return ret;
@@ -157,27 +173,34 @@ dhcp_extract_router_msg (struct buffer *ipbuf)
&& df->ip.protocol == OPENVPN_IPPROTO_UDP
&& df->udp.source == htons (BOOTPS_PORT)
&& df->udp.dest == htons (BOOTPC_PORT)
- && df->dhcp.op == BOOTREPLY
- && get_dhcp_message_type (&df->dhcp, optlen) == DHCPACK)
+ && df->dhcp.op == BOOTREPLY)
{
- /* get the router IP address while padding out all DHCP router options */
- const in_addr_t ret = do_extract (&df->dhcp, optlen);
-
- /* recompute the UDP checksum */
- df->udp.check = htons (udp_checksum ((uint8_t *) &df->udp,
- sizeof (struct openvpn_udphdr) + sizeof (struct dhcp) + optlen,
- (uint8_t *)&df->ip.saddr,
- (uint8_t *)&df->ip.daddr));
-
- if (ret)
+ const int message_type = get_dhcp_message_type (&df->dhcp, optlen);
+ if (message_type == DHCPACK || message_type == DHCPOFFER)
{
- struct gc_arena gc = gc_new ();
- msg (D_ROUTE, "Extracted DHCP router address: %s", print_in_addr_t (ret, 0, &gc));
- gc_free (&gc);
- }
+ /* get the router IP address while padding out all DHCP router options */
+ const in_addr_t ret = do_extract (&df->dhcp, optlen);
+
+ /* recompute the UDP checksum */
+ df->udp.check = 0;
+ df->udp.check = htons (udp_checksum ((uint8_t *) &df->udp,
+ sizeof (struct openvpn_udphdr) + sizeof (struct dhcp) + optlen,
+ (uint8_t *)&df->ip.saddr,
+ (uint8_t *)&df->ip.daddr));
+
+ /* only return the extracted Router address if DHCPACK */
+ if (message_type == DHCPACK)
+ {
+ if (ret)
+ {
+ struct gc_arena gc = gc_new ();
+ msg (D_ROUTE, "Extracted DHCP router address: %s", print_in_addr_t (ret, 0, &gc));
+ gc_free (&gc);
+ }
- return ret;
+ return ret;
+ }
+ }
}
- else
- return 0;
+ return 0;
}
diff --git a/forward.c b/forward.c
index c66031f..dfef4ef 100644
--- a/forward.c
+++ b/forward.c
@@ -1011,7 +1011,7 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
if (!c->options.passtos)
flags &= ~PIPV4_PASSTOS;
#endif
- if (!c->options.route_gateway_via_dhcp || !route_list_vpn_gateway_needed (c->c1.route_list))
+ if (!c->options.route_gateway_via_dhcp)
flags &= ~PIPV4_EXTRACT_DHCP_ROUTER;
if (buf->len > 0)