OpenVPN
src
openvpn
dhcp.c
Go to the documentation of this file.
1
/*
2
* OpenVPN -- An application to securely tunnel IP networks
3
* over a single TCP/UDP port, with support for SSL/TLS-based
4
* session authentication and key exchange,
5
* packet encryption, packet authentication, and
6
* packet compression.
7
*
8
* Copyright (C) 2002-2023 OpenVPN Inc <sales@openvpn.net>
9
*
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License version 2
12
* as published by the Free Software Foundation.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License along
20
* with this program; if not, write to the Free Software Foundation, Inc.,
21
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
*/
23
24
#ifdef HAVE_CONFIG_H
25
#include "
config.h
"
26
#elif defined(_MSC_VER)
27
#include "
config-msvc.h
"
28
#endif
29
30
#include "
syshead.h
"
31
32
#include "
dhcp.h
"
33
#include "
socket.h
"
34
#include "
error.h
"
35
36
#include "
memdbg.h
"
37
38
static
int
39
get_dhcp_message_type
(
const
struct
dhcp
*
dhcp
,
const
int
optlen)
40
{
41
const
uint8_t *p = (uint8_t *) (
dhcp
+ 1);
42
int
i;
43
44
for
(i = 0; i < optlen; ++i)
45
{
46
const
uint8_t type = p[i];
47
const
int
room = optlen - i;
48
if
(type ==
DHCP_END
)
/* didn't find what we were looking for */
49
{
50
return
-1;
51
}
52
else
if
(type ==
DHCP_PAD
)
/* no-operation */
53
{
54
}
55
else
if
(type ==
DHCP_MSG_TYPE
)
/* what we are looking for */
56
{
57
if
(room >= 3)
58
{
59
if
(p[i+1] == 1)
/* option length should be 1 */
60
{
61
return
p[i+2];
/* return message type */
62
}
63
}
64
return
-1;
65
}
66
else
/* some other option */
67
{
68
if
(room >= 2)
69
{
70
const
int
len = p[i+1];
/* get option length */
71
i += (len + 1);
/* advance to next option */
72
}
73
}
74
}
75
return
-1;
76
}
77
78
static
in_addr_t
79
do_extract
(
struct
dhcp
*
dhcp
,
int
optlen)
80
{
81
uint8_t *p = (uint8_t *) (
dhcp
+ 1);
82
int
i;
83
in_addr_t
ret = 0;
84
85
for
(i = 0; i < optlen; )
86
{
87
const
uint8_t type = p[i];
88
const
int
room = optlen - i;
89
if
(type ==
DHCP_END
)
90
{
91
break
;
92
}
93
else
if
(type ==
DHCP_PAD
)
94
{
95
++i;
96
}
97
else
if
(type ==
DHCP_ROUTER
)
98
{
99
if
(room >= 2)
100
{
101
const
int
len = p[i+1];
/* get option length */
102
if
(len <= (room-2))
103
{
104
/* get router IP address */
105
if
(!ret && len >= 4 && (len & 3) == 0)
106
{
107
memcpy(&ret, p+i+2, 4);
108
ret = ntohl(ret);
109
}
110
{
111
/* delete the router option */
112
uint8_t *dest = p + i;
113
const
int
owlen = len + 2;
/* len of data to overwrite */
114
uint8_t *src = dest + owlen;
115
uint8_t *end = p + optlen;
116
const
int
movlen = end - src;
117
if
(movlen > 0)
118
{
119
memmove(dest, src, movlen);
/* overwrite router option */
120
}
121
memset(end - owlen,
DHCP_PAD
, owlen);
/* pad tail */
122
}
123
}
124
else
125
{
126
break
;
127
}
128
}
129
else
130
{
131
break
;
132
}
133
}
134
else
/* some other option */
135
{
136
if
(room >= 2)
137
{
138
const
int
len = p[i+1];
/* get option length */
139
i += (len + 2);
/* advance to next option */
140
}
141
else
142
{
143
break
;
144
}
145
}
146
}
147
return
ret;
148
}
149
150
in_addr_t
151
dhcp_extract_router_msg
(
struct
buffer
*ipbuf)
152
{
153
struct
dhcp_full
*df = (
struct
dhcp_full
*)
BPTR
(ipbuf);
154
const
int
optlen =
BLEN
(ipbuf) - (
sizeof
(
struct
openvpn_iphdr
) + sizeof(struct
openvpn_udphdr
) + sizeof(struct
dhcp
));
155
156
if
(optlen >= 0
157
&& df->
ip
.
protocol
==
OPENVPN_IPPROTO_UDP
158
&& df->
udp
.
source
== htons(
BOOTPS_PORT
)
159
&& df->
udp
.
dest
== htons(
BOOTPC_PORT
)
160
&& df->
dhcp
.
op
==
BOOTREPLY
)
161
{
162
const
int
message_type =
get_dhcp_message_type
(&df->
dhcp
, optlen);
163
if
(message_type ==
DHCPACK
|| message_type ==
DHCPOFFER
)
164
{
165
/* get the router IP address while padding out all DHCP router options */
166
const
in_addr_t
ret =
do_extract
(&df->
dhcp
, optlen);
167
168
/* recompute the UDP checksum */
169
df->
udp
.
check
= 0;
170
df->
udp
.
check
= htons(
ip_checksum
(AF_INET, (uint8_t *)&df->
udp
,
171
sizeof
(
struct
openvpn_udphdr
) +
sizeof
(
struct
dhcp
) + optlen,
172
(uint8_t *)&df->
ip
.
saddr
, (uint8_t *)&df->
ip
.
daddr
,
173
OPENVPN_IPPROTO_UDP
));
174
175
/* only return the extracted Router address if DHCPACK */
176
if
(message_type ==
DHCPACK
)
177
{
178
if
(ret)
179
{
180
struct
gc_arena
gc =
gc_new
();
181
msg
(
D_ROUTE
,
"Extracted DHCP router address: %s"
,
print_in_addr_t
(ret, 0, &gc));
182
gc_free
(&gc);
183
}
184
185
return
ret;
186
}
187
}
188
}
189
return
0;
190
}
dhcp_full::ip
struct openvpn_iphdr ip
Definition:
dhcp.h:75
openvpn_udphdr::source
uint16_t source
Definition:
proto.h:169
error.h
gc_new
static struct gc_arena gc_new(void)
Definition:
buffer.h:1011
in_addr_t
#define in_addr_t
Definition:
config-msvc.h:67
D_ROUTE
#define D_ROUTE
Definition:
errlevel.h:80
OPENVPN_IPPROTO_UDP
#define OPENVPN_IPPROTO_UDP
Definition:
proto.h:122
BOOTREPLY
#define BOOTREPLY
Definition:
dhcp.h:55
config-msvc.h
dhcp_full::udp
struct openvpn_udphdr udp
Definition:
dhcp.h:76
get_dhcp_message_type
static int get_dhcp_message_type(const struct dhcp *dhcp, const int optlen)
Definition:
dhcp.c:39
DHCP_MSG_TYPE
#define DHCP_MSG_TYPE
Definition:
dhcp.h:36
do_extract
static in_addr_t do_extract(struct dhcp *dhcp, int optlen)
Definition:
dhcp.c:79
DHCP_PAD
#define DHCP_PAD
Definition:
dhcp.h:34
openvpn_udphdr
Definition:
proto.h:168
openvpn_iphdr::daddr
uint32_t daddr
Definition:
proto.h:128
openvpn_iphdr::protocol
uint8_t protocol
Definition:
proto.h:124
openvpn_iphdr::saddr
uint32_t saddr
Definition:
proto.h:127
BLEN
#define BLEN(buf)
Definition:
buffer.h:127
DHCP_ROUTER
#define DHCP_ROUTER
Definition:
dhcp.h:35
dhcp_extract_router_msg
in_addr_t dhcp_extract_router_msg(struct buffer *ipbuf)
Definition:
dhcp.c:151
openvpn_udphdr::check
uint16_t check
Definition:
proto.h:172
dhcp::op
uint8_t op
Definition:
dhcp.h:56
buffer
Wrapper structure for dynamically allocated memory.
Definition:
buffer.h:60
DHCPOFFER
#define DHCPOFFER
Definition:
dhcp.h:41
BOOTPC_PORT
#define BOOTPC_PORT
Definition:
dhcp.h:51
print_in_addr_t
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
Definition:
socket.c:2905
syshead.h
BPTR
#define BPTR(buf)
Definition:
buffer.h:124
dhcp.h
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition:
buffer.h:116
DHCP_END
#define DHCP_END
Definition:
dhcp.h:37
DHCPACK
#define DHCPACK
Definition:
dhcp.h:44
BOOTPS_PORT
#define BOOTPS_PORT
Definition:
dhcp.h:50
gc_free
static void gc_free(struct gc_arena *a)
Definition:
buffer.h:1019
socket.h
config.h
dhcp_full::dhcp
struct dhcp dhcp
Definition:
dhcp.h:77
openvpn_udphdr::dest
uint16_t dest
Definition:
proto.h:170
openvpn_iphdr
Definition:
proto.h:106
memdbg.h
msg
#define msg(flags,...)
Definition:
error.h:150
dhcp_full
Definition:
dhcp.h:74
dhcp
Definition:
dhcp.h:53
ip_checksum
uint16_t ip_checksum(const sa_family_t af, const uint8_t *payload, const int len_payload, const uint8_t *src_addr, const uint8_t *dest_addr, const int proto)
Calculates an IP or IPv6 checksum with a pseudo header as required by TCP, UDP and ICMPv6.
Definition:
proto.c:125
Generated by
1.8.17