BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file
3 * DHCPv6 - RFC 3315
4 */
5  
6 /*
7 * Copyright (c) 2017 Simon Goldschmidt
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30 * OF SUCH DAMAGE.
31 *
32 * This file is part of the lwIP TCP/IP stack.
33 *
34 * Author: Simon Goldschmidt <goldsimon@gmx.de>
35 */
36  
37 #include "lwip/opt.h"
38  
39 #if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */
40  
41 #include "lwip/dhcp6.h"
42 #include "lwip/prot/dhcp6.h"
43 #include "lwip/def.h"
44 #include "lwip/udp.h"
45  
46 #include <string.h>
47  
48 #ifdef LWIP_HOOK_FILENAME
49 #include LWIP_HOOK_FILENAME
50 #endif
51 #ifndef LWIP_HOOK_DHCP6_APPEND_OPTIONS
52 #define LWIP_HOOK_DHCP6_APPEND_OPTIONS(netif, dhcp6, state, msg, msg_type)
53 #endif
54 #ifndef LWIP_HOOK_DHCP6_PARSE_OPTION
55 #define LWIP_HOOK_DHCP6_PARSE_OPTION(netif, dhcp6, state, msg, msg_type, option, len, pbuf, offset)
56 #endif
57  
58 const ip_addr_t dhcp6_All_DHCP_Relay_Agents_and_Servers = IPADDR6_INIT_HOST(0xFF020000, 0, 0, 0x00010002);
59 const ip_addr_t dhcp6_All_DHCP_Servers = IPADDR6_INIT_HOST(0xFF020000, 0, 0, 0x00010003);
60  
61 static struct udp_pcb *dhcp6_pcb;
62 static u8_t dhcp6_pcb_refcount;
63  
64  
65 /* receive, unfold, parse and free incoming messages */
66 static void dhcp6_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
67  
68 /** Ensure DHCP PCB is allocated and bound */
69 static err_t
70 dhcp6_inc_pcb_refcount(void)
71 {
72 if (dhcp6_pcb_refcount == 0) {
73 LWIP_ASSERT("dhcp6_inc_pcb_refcount(): memory leak", dhcp6_pcb == NULL);
74  
75 /* allocate UDP PCB */
76 dhcp6_pcb = udp_new();
77  
78 if (dhcp6_pcb == NULL) {
79 return ERR_MEM;
80 }
81  
82 ip_set_option(dhcp6_pcb, SOF_BROADCAST);
83  
84 /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */
85 udp_bind(dhcp6_pcb, IP6_ADDR_ANY, DHCP6_CLIENT_PORT);
86 udp_recv(dhcp6_pcb, dhcp6_recv, NULL);
87 }
88  
89 dhcp6_pcb_refcount++;
90  
91 return ERR_OK;
92 }
93  
94 /** Free DHCP PCB if the last netif stops using it */
95 static void
96 dhcp6_dec_pcb_refcount(void)
97 {
98 LWIP_ASSERT("dhcp6_pcb_refcount(): refcount error", (dhcp6_pcb_refcount > 0));
99 dhcp6_pcb_refcount--;
100  
101 if (dhcp6_pcb_refcount == 0) {
102 udp_remove(dhcp6_pcb);
103 dhcp6_pcb = NULL;
104 }
105 }
106  
107 /**
108 * @ingroup dhcp6
109 * Set a statically allocated struct dhcp6 to work with.
110 * Using this prevents dhcp6_start to allocate it using mem_malloc.
111 *
112 * @param netif the netif for which to set the struct dhcp
113 * @param dhcp6 (uninitialised) dhcp6 struct allocated by the application
114 */
115 void
116 dhcp6_set_struct(struct netif *netif, struct dhcp6 *dhcp6)
117 {
118 LWIP_ASSERT("netif != NULL", netif != NULL);
119 LWIP_ASSERT("dhcp6 != NULL", dhcp6 != NULL);
120 LWIP_ASSERT("netif already has a struct dhcp6 set", netif_dhcp6_data(netif) == NULL);
121  
122 /* clear data structure */
123 memset(dhcp6, 0, sizeof(struct dhcp6));
124 /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
125 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP6, dhcp6);
126 }
127  
128 /**
129 * @ingroup dhcp6
130 * Removes a struct dhcp6 from a netif.
131 *
132 * ATTENTION: Only use this when not using dhcp6_set_struct() to allocate the
133 * struct dhcp6 since the memory is passed back to the heap.
134 *
135 * @param netif the netif from which to remove the struct dhcp
136 */
137 void dhcp6_cleanup(struct netif *netif)
138 {
139 LWIP_ASSERT("netif != NULL", netif != NULL);
140  
141 if (netif_dhcp6_data(netif) != NULL) {
142 mem_free(netif_dhcp6_data(netif));
143 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP6, NULL);
144 }
145 }
146  
147 static struct dhcp6*
148 dhcp6_get_struct(struct netif *netif, const char *dbg_requester)
149 {
150 struct dhcp6 *dhcp6 = netif_dhcp6_data(netif);
151 if (dhcp6 == NULL) {
152 LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("%s: mallocing new DHCPv6 client\n", dbg_requester));
153 dhcp6 = (struct dhcp6 *)mem_malloc(sizeof(struct dhcp6));
154 if (dhcp6 == NULL) {
155 LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("%s: could not allocate dhcp6\n", dbg_requester));
156 return NULL;
157 }
158  
159 /* clear data structure, this implies DHCP6_STATE_OFF */
160 memset(dhcp6, 0, sizeof(struct dhcp6));
161 /* store this dhcp6 client in the netif */
162 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP6, dhcp6);
163 } else {
164 /* already has DHCP6 client attached */
165 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("%s: using existing DHCPv6 client\n", dbg_requester));
166 }
167  
168 if (!dhcp6->pcb_allocated) {
169 if (dhcp6_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP6 PCB is allocated */
170 mem_free(dhcp6);
171 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP6, NULL);
172 return NULL;
173 }
174 LWIP_DEBUGF(DHCP6_DEBUG | LWIP_DBG_TRACE, ("%s: allocated dhcp6", dbg_requester));
175 dhcp6->pcb_allocated = 1;
176 }
177 return dhcp6;
178 }
179  
180 static u32_t
181 dhcp6_create_next_xid(struct netif *netif, struct dhcp6 dhcp6)
182 {
183 LWIP_UNUSED_ARG(netif);
184 LWIP_UNUSED_ARG(dhcp6);
185 }
186  
187 #if LWIP_IPV6_DHCP6_STATELESS
188 static err_t
189 dhcp_information_request(struct netif *netif, struct dhcp6 *dhcp6)
190 {
191 struct dhcp *dhcp = netif_dhcp_data(netif);
192 err_t result = ERR_OK;
193 u16_t msecs;
194 u8_t i;
195 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
196 ip4_addr_set_any(&dhcp->offered_ip_addr);
197 dhcp_set_state(dhcp, DHCP_STATE_SELECTING);
198 /* create and initialize the DHCP message header */
199 result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER);
200 if (result == ERR_OK) {
201 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
202  
203 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
204 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
205  
206 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
207 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
208 dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
209 }
210 LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_SELECTING, dhcp->msg_out, DHCP_DISCOVER);
211 dhcp_option_trailer(dhcp);
212  
213 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
214 udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
215 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
216 dhcp_delete_msg(dhcp);
217 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
218 } else {
219 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
220 }
221 if (dhcp->tries < 255) {
222 dhcp->tries++;
223 }
224 #if LWIP_DHCP_AUTOIP_COOP
225 if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
226 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
227 autoip_start(netif);
228 }
229 #endif /* LWIP_DHCP_AUTOIP_COOP */
230 msecs = (u16_t)((dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000);
231 dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
232 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
233 return result;
234 }
235  
236 static err_t
237 dhcp6_request_config(struct netif *netif)
238 {
239 struct dhcp6 *dhcp6;
240  
241 LWIP_ASSERT("netif != NULL", netif != NULL);
242  
243 dhcp6 = dhcp6_get_struct(netif, "dhcp6_request_config()");
244 if (dhcp6 == NULL) {
245 return ERR_MEM;
246 }
247  
248 /* if state is not idle, set a flag to send an information-request later? */
249 if (dhcp6->state != DHCP6_STATE_OFF) {
250 dhcp6->request_config_pending = 1;
251 return ERR_OK;
252 }
253  
254 /* send Information-request and wait for answer; setup receive timeout */
255 dhcp_information_request(netif, dhcp6);
256  
257 return ERR_OK;
258 }
259 #endif /* LWIP_IPV6_DHCP6_STATELESS */
260  
261 void
262 dhcp6_nd6_ra_trigger(struct netif *netif, u8_t managed_addr_config, u8_t other_config)
263 {
264 LWIP_UNUSED_ARG(managed_addr_config);
265 LWIP_UNUSED_ARG(other_config);
266  
267 #if LWIP_IPV6_DHCP6_STATELESS
268 if (other_config) {
269 dhcp6_request_config(netif);
270 }
271 #endif /* LWIP_IPV6_DHCP6_STATELESS */
272 }
273  
274 static void
275 dhcp6_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
276 {
277 LWIP_UNUSED_ARG(arg);
278 LWIP_UNUSED_ARG(pcb);
279 LWIP_UNUSED_ARG(p);
280 LWIP_UNUSED_ARG(addr);
281 LWIP_UNUSED_ARG(port);
282  
283 }
284  
285 #endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */