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-2024 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
#endif
27
28
#include "
syshead.h
"
29
30
#include "
dhcp.h
"
31
#include "
socket.h
"
32
#include "
error.h
"
33
34
#include "
memdbg.h
"
35
36
static
int
37
get_dhcp_message_type
(
const
struct
dhcp
*
dhcp
,
const
int
optlen)
38
{
39
const
uint8_t *p = (uint8_t *) (
dhcp
+ 1);
40
int
i;
41
42
for
(i = 0; i < optlen; ++i)
43
{
44
const
uint8_t type = p[i];
45
const
int
room = optlen - i;
46
if
(type ==
DHCP_END
)
/* didn't find what we were looking for */
47
{
48
return
-1;
49
}
50
else
if
(type ==
DHCP_PAD
)
/* no-operation */
51
{
52
}
53
else
if
(type ==
DHCP_MSG_TYPE
)
/* what we are looking for */
54
{
55
if
(room >= 3)
56
{
57
if
(p[i+1] == 1)
/* option length should be 1 */
58
{
59
return
p[i+2];
/* return message type */
60
}
61
}
62
return
-1;
63
}
64
else
/* some other option */
65
{
66
if
(room >= 2)
67
{
68
const
int
len = p[i+1];
/* get option length */
69
i += (len + 1);
/* advance to next option */
70
}
71
}
72
}
73
return
-1;
74
}
75
76
static
in_addr_t
77
do_extract
(
struct
dhcp
*
dhcp
,
int
optlen)
78
{
79
uint8_t *p = (uint8_t *) (
dhcp
+ 1);
80
int
i;
81
in_addr_t ret = 0;
82
83
for
(i = 0; i < optlen; )
84
{
85
const
uint8_t type = p[i];
86
const
int
room = optlen - i;
87
if
(type ==
DHCP_END
)
88
{
89
break
;
90
}
91
else
if
(type ==
DHCP_PAD
)
92
{
93
++i;
94
}
95
else
if
(type ==
DHCP_ROUTER
)
96
{
97
if
(room >= 2)
98
{
99
const
int
len = p[i+1];
/* get option length */
100
if
(len <= (room-2))
101
{
102
/* get router IP address */
103
if
(!ret && len >= 4 && (len & 3) == 0)
104
{
105
memcpy(&ret, p+i+2, 4);
106
ret = ntohl(ret);
107
}
108
{
109
/* delete the router option */
110
uint8_t *dest = p + i;
111
const
int
owlen = len + 2;
/* len of data to overwrite */
112
uint8_t *src = dest + owlen;
113
uint8_t *end = p + optlen;
114
const
int
movlen = end - src;
115
if
(movlen > 0)
116
{
117
memmove(dest, src, movlen);
/* overwrite router option */
118
}
119
memset(end - owlen,
DHCP_PAD
, owlen);
/* pad tail */
120
}
121
}
122
else
123
{
124
break
;
125
}
126
}
127
else
128
{
129
break
;
130
}
131
}
132
else
/* some other option */
133
{
134
if
(room >= 2)
135
{
136
const
int
len = p[i+1];
/* get option length */
137
i += (len + 2);
/* advance to next option */
138
}
139
else
140
{
141
break
;
142
}
143
}
144
}
145
return
ret;
146
}
147
148
in_addr_t
149
dhcp_extract_router_msg
(
struct
buffer
*ipbuf)
150
{
151
struct
dhcp_full
*df = (
struct
dhcp_full
*)
BPTR
(ipbuf);
152
const
int
optlen =
BLEN
(ipbuf) - (
sizeof
(
struct
openvpn_iphdr
) + sizeof(struct
openvpn_udphdr
) + sizeof(struct
dhcp
));
153
154
if
(optlen >= 0
155
&& df->
ip
.
protocol
==
OPENVPN_IPPROTO_UDP
156
&& df->
udp
.
source
== htons(
BOOTPS_PORT
)
157
&& df->
udp
.
dest
== htons(
BOOTPC_PORT
)
158
&& df->
dhcp
.
op
==
BOOTREPLY
)
159
{
160
const
int
message_type =
get_dhcp_message_type
(&df->
dhcp
, optlen);
161
if
(message_type ==
DHCPACK
|| message_type ==
DHCPOFFER
)
162
{
163
/* get the router IP address while padding out all DHCP router options */
164
const
in_addr_t ret =
do_extract
(&df->
dhcp
, optlen);
165
166
/* recompute the UDP checksum */
167
df->
udp
.
check
= 0;
168
df->
udp
.
check
= htons(
ip_checksum
(AF_INET, (uint8_t *)&df->
udp
,
169
sizeof
(
struct
openvpn_udphdr
) +
sizeof
(
struct
dhcp
) + optlen,
170
(uint8_t *)&df->
ip
.
saddr
, (uint8_t *)&df->
ip
.
daddr
,
171
OPENVPN_IPPROTO_UDP
));
172
173
/* only return the extracted Router address if DHCPACK */
174
if
(message_type ==
DHCPACK
)
175
{
176
if
(ret)
177
{
178
struct
gc_arena
gc =
gc_new
();
179
msg
(
D_ROUTE
,
"Extracted DHCP router address: %s"
,
print_in_addr_t
(ret, 0, &gc));
180
gc_free
(&gc);
181
}
182
183
return
ret;
184
}
185
}
186
}
187
return
0;
188
}
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:1030
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
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:37
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:77
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:149
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:2904
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:1038
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:144
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:123
Generated by
1.8.17