dhcpv6_relay.c
Go to the documentation of this file.
1 /**
2  * @file dhcpv6_relay.c
3  * @brief DHCPv6 relay agent (Dynamic Host Configuration Protocol for IPv6)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2023 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * DHCPv6 Relay-Agents are deployed to forward DHCPv6 messages between clients
30  * and servers when they are not on the same IPv6 link and are often implemented
31  * alongside a routing function in a common node. Refer to RFC 3315
32  *
33  * @author Oryx Embedded SARL (www.oryx-embedded.com)
34  * @version 2.2.2
35  **/
36 
37 //Switch to the appropriate trace level
38 #define TRACE_LEVEL DHCPV6_TRACE_LEVEL
39 
40 //Dependencies
41 #include "core/net.h"
42 #include "dhcpv6_relay.h"
43 #include "dhcpv6/dhcpv6_common.h"
44 #include "dhcpv6/dhcpv6_debug.h"
45 #include "debug.h"
46 
47 //Check TCP/IP stack configuration
48 #if (IPV6_SUPPORT == ENABLED && DHCPV6_RELAY_SUPPORT == ENABLED)
49 
50 
51 /**
52  * @brief Start DHCPv6 relay agent
53  * @param[in] context Pointer to the DHCPv6 relay agent context
54  * @param[in] settings DHCPv6 relay agent specific settings
55  * @return Error code
56  **/
57 
59 {
60  error_t error;
61  uint_t i;
62 
63  //Debug message
64  TRACE_INFO("Starting DHCPv6 relay agent...\r\n");
65 
66  //Ensure the parameters are valid
67  if(!context || !settings)
69  //The pointer to the network-facing interface shall be valid
70  if(!settings->serverInterface)
72  //Check the number of client-facing interfaces
73  if(!settings->clientInterfaceCount)
77 
78  //Loop through the client-facing interfaces
79  for(i = 0; i < settings->clientInterfaceCount; i++)
80  {
81  //A valid pointer is required for each interface
82  if(!settings->clientInterface[i])
84  }
85 
86  //Check the address to be used when forwarding messages to the server
88  return ERROR_INVALID_ADDRESS;
89 
90  //Clear the DHCPv6 relay agent context
91  osMemset(context, 0, sizeof(Dhcpv6RelayContext));
92 
93  //Save the network-facing interface
94  context->serverInterface = settings->serverInterface;
95  //Save the number of client-facing interfaces
96  context->clientInterfaceCount = settings->clientInterfaceCount;
97 
98  //Save all the client-facing interfaces
99  for(i = 0; i < context->clientInterfaceCount; i++)
100  context->clientInterface[i] = settings->clientInterface[i];
101 
102  //Save the address to be used when relaying client messages to the server
103  context->serverAddress = settings->serverAddress;
104 
105  //Join the All_DHCP_Relay_Agents_and_Servers multicast group
106  //for each client-facing interface
107  error = dhcpv6RelayJoinMulticastGroup(context);
108  //Any error to report?
109  if(error)
110  return error;
111 
112  //Start of exception handling block
113  do
114  {
115  //Open a UDP socket to handle the network-facing interface
117  //Failed to open socket?
118  if(!context->serverSocket)
119  {
120  //Report an error
121  error = ERROR_OPEN_FAILED;
122  //Stop processing
123  break;
124  }
125 
126  //Explicitly associate the socket with the relevant interface
127  error = socketBindToInterface(context->serverSocket, context->serverInterface);
128  //Unable to bind the socket to the desired interface?
129  if(error)
130  break;
131 
132  //Relay agents listen for DHCPv6 messages on UDP port 547
134  //Unable to bind the socket to the desired port?
135  if(error)
136  break;
137 
138  //Only accept datagrams with source port number 547
140  //Any error to report?
141  if(error)
142  break;
143 
144  //If the relay agent relays messages to the All_DHCP_Servers address
145  //or other multicast addresses, it sets the Hop Limit field to 32
146 
147  //Loop through the client-facing interfaces
148  for(i = 0; i < context->clientInterfaceCount; i++)
149  {
150  //Open a UDP socket to handle the current interface
152  //Failed to open socket?
153  if(!context->clientSocket[i])
154  {
155  //Report an error
156  error = ERROR_OPEN_FAILED;
157  //Stop processing
158  break;
159  }
160 
161  //Explicitly associate the socket with the relevant interface
162  error = socketBindToInterface(context->clientSocket[i], context->clientInterface[i]);
163  //Unable to bind the socket to the desired interface?
164  if(error)
165  break;
166 
167  //Relay agents listen for DHCPv6 messages on UDP port 547
168  error = socketBind(context->clientSocket[i], &IP_ADDR_ANY, DHCPV6_SERVER_PORT);
169  //Unable to bind the socket to the desired port?
170  if(error)
171  break;
172 
173  //Only accept datagrams with source port number 546
175  //Any error to report?
176  if(error)
177  break;
178  }
179 
180  //Propagate exception if necessary
181  if(error)
182  break;
183 
184  //Initialize event object
185  if(!osCreateEvent(&context->event))
186  {
187  //Failed to create event
188  error = ERROR_OUT_OF_RESOURCES;
189  //Stop processing
190  break;
191  }
192 
193  //Initialize ACK event object
194  if(!osCreateEvent(&context->ackEvent))
195  {
196  //Failed to create event
197  error = ERROR_OUT_OF_RESOURCES;
198  //Stop processing
199  break;
200  }
201 
202  //The DHCPv6 relay agent is now running
203  context->running = TRUE;
204 
205 #if (OS_STATIC_TASK_SUPPORT == ENABLED)
206  //Create a task using statically allocated memory
207  context->taskId = osCreateStaticTask("DHCPv6 Relay",
208  (OsTaskCode) dhcpv6RelayTask, context, &context->taskTcb,
210 #else
211  //Create a task
212  context->taskId = osCreateTask("DHCPv6 Relay",
215 #endif
216 
217  //Failed to create task?
218  if(context->taskId == OS_INVALID_TASK_ID)
219  error = ERROR_OUT_OF_RESOURCES;
220 
221  //End of exception handling block
222  } while(0);
223 
224  //Did we encounter an error?
225  if(error)
226  {
227  //Close the socket associated with the network-facing interface
228  socketClose(context->serverSocket);
229 
230  //Close the socket associated with each client-facing interface
231  for(i = 0; i < context->clientInterfaceCount; i++)
232  {
233  socketClose(context->clientSocket[i]);
234  }
235 
236  //Leave the All_DHCP_Relay_Agents_and_Servers multicast group
237  //for each client-facing interface
239 
240  //Delete event objects
241  osDeleteEvent(&context->event);
242  osDeleteEvent(&context->ackEvent);
243  }
244 
245  //Return status code
246  return error;
247 }
248 
249 
250 /**
251  * @brief Stop DHCPv6 relay agent
252  * @param[in] context Pointer to the DHCPv6 relay agent context
253  * @return Error code
254  **/
255 
257 {
258  uint_t i;
259 
260  //Make sure the DHCPv6 relay agent context is valid
261  if(context == NULL)
263 
264  //Debug message
265  TRACE_INFO("Stopping DHCPv6 relay agent...\r\n");
266 
267  //Check DHCPv6 relay agent state
268  if(!context->running)
269  return ERROR_WRONG_STATE;
270 
271  //Reset ACK event before sending the kill signal
272  osResetEvent(&context->ackEvent);
273  //Stop the DHCPv6 relay agent task
274  context->stopRequest = TRUE;
275  //Send a signal to the task in order to abort any blocking operation
276  osSetEvent(&context->event);
277 
278  //Wait for the process to terminate...
280 
281  //Leave the All_DHCP_Relay_Agents_and_Servers multicast group
282  //for each client-facing interface
284 
285  //Close the socket that carries traffic towards the DHCPv6 server
286  socketClose(context->serverSocket);
287 
288  //Properly dispose the sockets that carry traffic towards the DHCPv6 clients
289  for(i = 0; i < context->clientInterfaceCount; i++)
290  {
291  socketClose(context->clientSocket[i]);
292  }
293 
294  //Delete event objects
295  osDeleteEvent(&context->event);
296  osDeleteEvent(&context->ackEvent);
297 
298  //Successful processing
299  return NO_ERROR;
300 }
301 
302 
303 /**
304  * @brief Join All_DHCP_Relay_Agents_and_Servers multicast group
305  * @param[in] context Pointer to the DHCPv6 relay agent context
306  **/
307 
309 {
310  uint_t i;
311  uint_t j;
312 
313  //Initialize status code
314  error_t error = NO_ERROR;
315 
316  //Loop through the client-facing interfaces
317  for(i = 0; i < context->clientInterfaceCount; i++)
318  {
319  //Join the All_DHCP_Relay_Agents_and_Servers multicast
320  //group for each interface
321  error = ipv6JoinMulticastGroup(context->clientInterface[i],
323  //Unable to join the specified multicast group?
324  if(error)
325  break;
326  }
327 
328  //Did we encounter an error?
329  if(error)
330  {
331  //Clean up side effects before returning...
332  for(j = 0; j < i; j++)
333  {
334  //Leave the multicast group for each interface
337  }
338  }
339 
340  //Return status code
341  return error;
342 }
343 
344 
345 /**
346  * @brief Leave All_DHCP_Relay_Agents_and_Servers multicast group
347  * @param[in] context Pointer to the DHCPv6 relay agent context
348  **/
349 
351 {
352  uint_t i;
353 
354  //Loop through the client-facing interfaces
355  for(i = 0; i < context->clientInterfaceCount; i++)
356  {
357  //Leave the All_DHCP_Relay_Agents_and_Servers multicast
358  //group for each interface
361  }
362 
363  //Successsful processing
364  return NO_ERROR;
365 }
366 
367 
368 /**
369  * @brief DHCPv6 relay agent task
370  * @param[in] param Pointer to the DHCPv6 relay agent context
371  **/
372 
373 void dhcpv6RelayTask(void *param)
374 {
375  error_t error;
376  uint_t i;
377  Dhcpv6RelayContext *context;
378 
379  //Task prologue
380  osEnterTask();
381 
382  //Point to the DHCPv6 relay agent context
383  context = (Dhcpv6RelayContext *) param;
384 
385  //Specify the events the application is interested in for
386  //each client-facing sockets
387  for(i = 0; i < context->clientInterfaceCount; i++)
388  {
389  context->eventDesc[i].socket = context->clientSocket[i];
391  }
392 
393  //Specify the events the application is interested in for
394  //the network-facing socket
395  context->eventDesc[i].socket = context->serverSocket;
397 
398  //Main loop
399  while(1)
400  {
401  //Wait for incoming packets on network-facing or client-facing interfaces
402  error = socketPoll(context->eventDesc, context->clientInterfaceCount + 1,
403  &context->event, INFINITE_DELAY);
404 
405  //Stop DHCPv6 relay agent?
406  if(context->stopRequest)
407  {
408  //The DHCPv6 relay agent is about to stop
409  context->stopRequest = FALSE;
410  context->running = FALSE;
411  //Acknowledge the reception of the user request
412  osSetEvent(&context->ackEvent);
413  //Task epilogue
414  osExitTask();
415  //Kill ourselves
417  }
418 
419  //Verify status code
420  if(error == NO_ERROR || error == ERROR_WAIT_CANCELED)
421  {
422  //Check the state of each client-facing socket
423  for(i = 0; i < context->clientInterfaceCount; i++)
424  {
425  //Relay client messages if applicable
426  if(context->eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY)
427  dhcpv6ForwardClientMessage(context, i);
428  }
429 
430  //Check the state of the network-facing socket
431  if(context->eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY)
432  {
433  //Forward Relay-Reply messages from the network
435  }
436  }
437  }
438 }
439 
440 
441 /**
442  * @brief Forward client message
443  * @param[in] context Pointer to the DHCPv6 relay agent context
444  * @param[in] index Index identifying the interface on which the message was received
445  * @return Error code
446  **/
447 
449 {
450  error_t error;
451  uint32_t interfaceId;
452  size_t inputMessageLen;
453  size_t outputMessageLen;
454  Dhcpv6RelayMessage *inputMessage;
455  Dhcpv6RelayMessage *outputMessage;
456  Dhcpv6Option *option;
457  IpAddr ipAddr;
458 
459  //Point to the buffer where to store the incoming DHCPv6 message
460  inputMessage = (Dhcpv6RelayMessage *) (context->buffer + DHCPV6_RELAY_FORW_OVERHEAD);
461  //Message that will be forwarded by the DHCPv6 relay agent
462  outputMessage = (Dhcpv6RelayMessage *) context->buffer;
463 
464  //Read incoming message
465  error = socketReceiveFrom(context->clientSocket[index], &ipAddr, NULL, inputMessage,
466  DHCPV6_MAX_MSG_SIZE - DHCPV6_RELAY_FORW_OVERHEAD, &inputMessageLen, 0);
467  //Any error to report?
468  if(error)
469  return error;
470 
471  //Debug message
472  TRACE_INFO("\r\nDHCPv6 message received on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
473  context->clientInterface[index]->name, inputMessageLen);
474 
475  //Dump the contents of the message for debugging purpose
476  dhcpv6DumpMessage(inputMessage, inputMessageLen);
477 
478  //The source address must be a valid IPv6 address
479  if(ipAddr.length != sizeof(Ipv6Addr))
480  return ERROR_INVALID_ADDRESS;
481  //Check the length of the DHCPv6 message
482  if(inputMessageLen < sizeof(Dhcpv6Message))
483  return ERROR_INVALID_MESSAGE;
484 
485  //When the relay agent receives a valid message to be relayed,
486  //it constructs a new Relay-Forward message
487  outputMessage->msgType = DHCPV6_MSG_TYPE_RELAY_FORW;
488 
489  //Inspect the message type
490  switch(inputMessage->msgType)
491  {
492  //Message received from a client?
501  //If the relay agent received the message to be relayed from a client
502  //the hop-count in the Relay-Forward message is set to 0
503  outputMessage->hopCount = 0;
504  //Continue processing
505  break;
506 
507  //Message received from another relay agent?
509  //If the message received by the relay agent is a Relay-Forward message
510  //and the hop-count in the message is greater than or equal to 32, the
511  //relay agent discards the received message
512  if(inputMessage->hopCount >= DHCPV6_HOP_COUNT_LIMIT)
513  return ERROR_INVALID_MESSAGE;
514  //Set the hop-count field to the value of the hop-count field in
515  //the received message incremented by 1
516  outputMessage->hopCount = inputMessage->hopCount + 1;
517  //Continue processing
518  break;
519 
520  //Message received from a server?
521  default:
522  //Discard ADVERTISE, REPLY, RECONFIGURE and RELAY-REPL messages
523  return ERROR_INVALID_MESSAGE;
524  }
525 
526  //Set the link-address field to the unspecified address
527  outputMessage->linkAddress = IPV6_UNSPECIFIED_ADDR;
528  //Copy the source address from the header of the IP datagram in
529  //which the message was received to the peer-address field
530  outputMessage->peerAddress = ipAddr.ipv6Addr;
531  //Size of the Relay-Forward message
532  outputMessageLen = sizeof(Dhcpv6RelayMessage);
533 
534  //Get the interface identifier
535  interfaceId = context->clientInterface[index]->id;
536  //Convert the 32-bit integer to network byte order
538 
539  //If the relay agent cannot use the address in the link-address field
540  //to identify the interface through which the response to the client
541  //will be relayed, the relay agent must include an Interface ID option
542  dhcpv6AddOption(outputMessage, &outputMessageLen,
544 
545  //Copy the received DHCPv6 message into a Relay Message option
546  option = dhcpv6AddOption(outputMessage, &outputMessageLen,
547  DHCPV6_OPT_RELAY_MSG, NULL, 0);
548 
549  //Set the appropriate length of the option
550  option->length = htons(inputMessageLen);
551  //Adjust the length of the Relay-Forward message
552  outputMessageLen += inputMessageLen;
553 
554  //Debug message
555  TRACE_INFO("Forwarding DHCPv6 message on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
556  context->serverInterface->name, outputMessageLen);
557 
558  //Dump the contents of the message for debugging purpose
559  dhcpv6DumpMessage(outputMessage, outputMessageLen);
560 
561  //Destination address to be used when relaying the client message
562  ipAddr.length = sizeof(Ipv6Addr);
563  ipAddr.ipv6Addr = context->serverAddress;
564 
565  //Relay the client message to the server
566  return socketSendTo(context->serverSocket, &ipAddr,
567  DHCPV6_SERVER_PORT, outputMessage, outputMessageLen, NULL, 0);
568 }
569 
570 
571 /**
572  * @brief Forward Relay-Reply message
573  * @param[in] context Pointer to the DHCPv6 relay agent context
574  * @return Error code
575  **/
576 
578 {
579  error_t error;
580  uint_t i;
581  uint32_t interfaceId;
582  size_t inputMessageLen;
583  size_t outputMessageLen;
584  Dhcpv6RelayMessage *inputMessage;
585  Dhcpv6Message *outputMessage;
586  Dhcpv6Option *option;
587  IpAddr ipAddr;
588  uint16_t port;
589 
590  //Point to the buffer where to store the incoming DHCPv6 message
591  inputMessage = (Dhcpv6RelayMessage *) context->buffer;
592 
593  //Read incoming message
594  error = socketReceiveFrom(context->serverSocket, &ipAddr, &port,
595  inputMessage, DHCPV6_MAX_MSG_SIZE, &inputMessageLen, 0);
596  //Any error to report?
597  if(error)
598  return error;
599 
600  //Debug message
601  TRACE_INFO("\r\nDHCPv6 message received on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
602  context->serverInterface->name, inputMessageLen);
603 
604  //Dump the contents of the message for debugging purpose
605  dhcpv6DumpMessage(inputMessage, inputMessageLen);
606 
607  //Check the length of the DHCPv6 message
608  if(inputMessageLen < sizeof(Dhcpv6RelayMessage))
609  return ERROR_INVALID_MESSAGE;
610 
611  //Inspect the message type and only forward Relay-Reply messages.
612  //Other DHCPv6 message types must be silently discarded
613  if(inputMessage->msgType != DHCPV6_MSG_TYPE_RELAY_REPL)
614  return ERROR_INVALID_MESSAGE;
615 
616  //Get the length of the Options field
617  inputMessageLen -= sizeof(Dhcpv6Message);
618 
619  //Check whether an Interface ID option is included in the Relay-Reply
620  option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPT_INTERFACE_ID);
621  //Failed to retrieve specified option?
622  if(option == NULL || ntohs(option->length) != sizeof(interfaceId))
623  return ERROR_INVALID_MESSAGE;
624 
625  //Read the Interface ID option contents
626  osMemcpy(&interfaceId, option->value, sizeof(interfaceId));
627  //Convert the 32-bit integer from network byte order
629 
630  //The Relay-Reply message must include a Relay Message option
631  option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPT_RELAY_MSG);
632  //Failed to retrieve specified option?
633  if(option == NULL || ntohs(option->length) < sizeof(Dhcpv6Message))
634  return ERROR_INVALID_MESSAGE;
635 
636  //Extract the message from the Relay Message option
637  outputMessage = (Dhcpv6Message *) option->value;
638  //Save the length of the message
639  outputMessageLen = ntohs(option->length);
640 
641  //Loop through client-facing interfaces
642  for(i = 0; i < context->clientInterfaceCount; i++)
643  {
644  //Check whether the current interface matches the Interface ID option
645  if(context->clientInterface[i]->id == interfaceId)
646  {
647  //Debug message
648  TRACE_INFO("Forwarding DHCPv6 message on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n",
649  context->clientInterface[i]->name, outputMessageLen);
650 
651  //Dump the contents of the message for debugging purpose
652  dhcpv6DumpMessage(outputMessage, outputMessageLen);
653 
654  //Copy the peer-address into the destination IP address
655  ipAddr.length = sizeof(Ipv6Addr);
656  ipAddr.ipv6Addr = inputMessage->peerAddress;
657 
658  //Select the relevant port number to use
659  if(outputMessage->msgType == DHCPV6_MSG_TYPE_RELAY_REPL)
661  else
663 
664  //Relay the DHCPv6 message to the client on the link
665  //identified by the Interface ID option
666  return socketSendTo(context->clientSocket[i], &ipAddr,
667  port, outputMessage, outputMessageLen, NULL, 0);
668  }
669  }
670 
671  //Unknown interface identifier...
672  return ERROR_INVALID_OPTION;
673 }
674 
675 #endif
bool_t running
DHCPv6 relay agent is currently running or not?
Definition: dhcpv6_relay.h:99
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a task.
#define htons(value)
Definition: cpu_endian.h:413
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:94
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:596
@ DHCPV6_MSG_TYPE_DECLINE
Definition: dhcpv6_common.h:98
__start_packed struct @3 Dhcpv6Message
DHCPv6 message.
#define osExitTask()
DHCPv6 relay agent (Dynamic Host Configuration Protocol for IPv6)
@ DHCPV6_MSG_TYPE_SOLICIT
Definition: dhcpv6_common.h:90
IP network address.
Definition: ip.h:79
@ ERROR_INVALID_INTERFACE
Invalid interface.
Definition: error.h:53
#define DHCPV6_CLIENT_PORT
Definition: dhcpv6_common.h:40
error_t dhcpv6ForwardRelayReplyMessage(Dhcpv6RelayContext *context)
Forward Relay-Reply message.
Definition: dhcpv6_relay.c:577
uint_t clientInterfaceCount
Number of client-facing interfaces.
Definition: dhcpv6_relay.h:81
#define TRUE
Definition: os_port.h:50
Definitions common to DHCPv6 client, server and relay agent.
#define OS_INVALID_TASK_ID
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:1331
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ DHCPV6_MSG_TYPE_REBIND
Definition: dhcpv6_common.h:95
@ DHCPV6_MSG_TYPE_RELAY_FORW
@ SOCKET_TYPE_DGRAM
Definition: socket.h:79
OsStackType taskStack[DHCPV6_RELAY_STACK_SIZE]
Task stack.
Definition: dhcpv6_relay.h:106
const Ipv6Addr DHCPV6_ALL_RELAY_AGENTS_AND_SERVERS_ADDR
Definition: dhcpv6_common.c:51
void dhcpv6RelayTask(void *param)
DHCPv6 relay agent task.
Definition: dhcpv6_relay.c:373
error_t dhcpv6RelayStop(Dhcpv6RelayContext *context)
Stop DHCPv6 relay agent.
Definition: dhcpv6_relay.c:256
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:121
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
Ipv6Addr serverAddress
Address to be used when relaying messages to the server.
Definition: dhcpv6_relay.h:95
Dhcpv6Option * dhcpv6GetOption(const uint8_t *options, size_t optionsLength, uint16_t optionCode)
Search a DHCPv6 message for a given option.
SocketEventDesc eventDesc[DHCPV6_RELAY_MAX_CLIENT_IF]
The events the application is interested in.
Definition: dhcpv6_relay.h:98
Socket * clientSocket[DHCPV6_RELAY_MAX_CLIENT_IF]
Sockets that handle client-facing interfaces.
Definition: dhcpv6_relay.h:97
error_t dhcpv6RelayLeaveMulticastGroup(Dhcpv6RelayContext *context)
Leave All_DHCP_Relay_Agents_and_Servers multicast group.
Definition: dhcpv6_relay.c:350
#define OS_SELF_TASK_ID
#define DHCPV6_RELAY_PRIORITY
Definition: dhcpv6_relay.h:54
error_t dhcpv6RelayStart(Dhcpv6RelayContext *context, const Dhcpv6RelaySettings *settings)
Start DHCPv6 relay agent.
Definition: dhcpv6_relay.c:58
@ ERROR_WRONG_STATE
Definition: error.h:209
@ ERROR_OPEN_FAILED
Definition: error.h:75
NetInterface * serverInterface
Network-facing interface.
Definition: dhcpv6_relay.h:79
const IpAddr IP_ADDR_ANY
Definition: ip.c:45
void osDeleteTask(OsTaskId taskId)
Delete a task.
#define FALSE
Definition: os_port.h:46
NetInterface * serverInterface
Network-facing interface.
Definition: dhcpv6_relay.h:92
OsEvent ackEvent
Event object use to acknowledge user requests.
Definition: dhcpv6_relay.h:101
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
#define DHCPV6_MAX_MSG_SIZE
Definition: dhcpv6_common.h:44
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
#define osMemcpy(dest, src, length)
Definition: os_port.h:137
OsEvent event
Event object used to poll the sockets.
Definition: dhcpv6_relay.h:102
error_t
Error codes.
Definition: error.h:43
OsTaskId osCreateStaticTask(const char_t *name, OsTaskCode taskCode, void *param, OsTaskTcb *tcb, OsStackType *stack, size_t stackSize, int_t priority)
Create a task with statically allocated memory.
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ DHCPV6_MSG_TYPE_RELEASE
Definition: dhcpv6_common.h:97
void osDeleteEvent(OsEvent *event)
Delete an event object.
error_t dhcpv6RelayJoinMulticastGroup(Dhcpv6RelayContext *context)
Join All_DHCP_Relay_Agents_and_Servers multicast group.
Definition: dhcpv6_relay.c:308
error_t socketReceiveFrom(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram from a connectionless socket.
Definition: socket.c:988
Ipv6Addr serverAddress
Address to be used when relaying messages to the server.
Definition: dhcpv6_relay.h:82
@ DHCPV6_OPT_INTERFACE_ID
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:625
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:66
error_t ipv6LeaveMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Leave an IPv6 multicast group.
Definition: ipv6.c:2111
@ DHCPV6_MSG_TYPE_RENEW
Definition: dhcpv6_common.h:94
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
Definition: ipv6.c:2001
Eui64 interfaceId
Definition: ipv6cp.h:69
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t buffer[DHCPV6_MAX_MSG_SIZE]
Scratch buffer to store DHCPv6 messages.
Definition: dhcpv6_relay.h:108
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:122
#define osEnterTask()
uint_t eventFlags
Returned events.
Definition: socket.h:368
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:1391
#define DHCPV6_RELAY_MAX_CLIENT_IF
Definition: dhcpv6_relay.h:59
#define socketBindToInterface
Definition: net_legacy.h:193
@ DHCPV6_MSG_TYPE_INFO_REQUEST
DHCPv6 relay agent settings.
Definition: dhcpv6_relay.h:78
@ DHCPV6_MSG_TYPE_RELAY_REPL
uint16_t port
Definition: dns_common.h:251
#define ntohs(value)
Definition: cpu_endian.h:421
__start_packed struct @5 Dhcpv6Option
DHCPv6 option.
#define DHCPV6_SERVER_PORT
Definition: dhcpv6_common.h:41
NetInterface * clientInterface[DHCPV6_RELAY_MAX_CLIENT_IF]
Client-facing interfaces.
Definition: dhcpv6_relay.h:93
#define DHCPV6_RELAY_FORW_OVERHEAD
Definition: dhcpv6_relay.h:65
@ SOCKET_EVENT_RX_READY
Definition: socket.h:162
void(* OsTaskCode)(void *param)
Task routine.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
@ DHCPV6_OPT_RELAY_MSG
DHCPv6 relay agent context.
Definition: dhcpv6_relay.h:91
error_t dhcpv6DumpMessage(const void *message, size_t length)
Dump DHCPv6 message for debugging purpose.
Definition: dhcpv6_debug.c:123
NetInterface * clientInterface[DHCPV6_RELAY_MAX_CLIENT_IF]
Client-facing interfaces.
Definition: dhcpv6_relay.h:80
error_t dhcpv6ForwardClientMessage(Dhcpv6RelayContext *context, uint_t index)
Forward client message.
Definition: dhcpv6_relay.c:448
Dhcpv6Option * dhcpv6AddOption(void *message, size_t *messageLen, uint16_t optionCode, const void *optionValue, size_t optionLen)
Add an option to a DHCPv6 message.
@ ERROR_WAIT_CANCELED
Definition: error.h:73
bool_t osCreateEvent(OsEvent *event)
Create an event object.
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:781
@ DHCPV6_MSG_TYPE_CONFIRM
Definition: dhcpv6_common.h:93
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
@ ERROR_INVALID_OPTION
Definition: error.h:98
#define DHCPV6_HOP_COUNT_LIMIT
Definition: dhcpv6_common.h:49
uint_t clientInterfaceCount
Number of client-facing interfaces.
Definition: dhcpv6_relay.h:94
Socket * socket
Handle to a socket to monitor.
Definition: socket.h:366
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:131
TCP/IP stack core.
__start_packed struct @4 Dhcpv6RelayMessage
DHCPv6 relay agent message.
bool_t stopRequest
Stop request.
Definition: dhcpv6_relay.h:100
OsTaskTcb taskTcb
Task control block.
Definition: dhcpv6_relay.h:105
__start_packed struct @0 Ipv6Addr
IPv6 network address.
#define DHCPV6_RELAY_STACK_SIZE
Definition: dhcpv6_relay.h:47
uint8_t ipAddr[4]
Definition: mib_common.h:187
#define ntohl(value)
Definition: cpu_endian.h:422
uint_t eventMask
Requested events.
Definition: socket.h:367
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
Socket * serverSocket
Socket that handles the network-facing interface.
Definition: dhcpv6_relay.h:96
Data logging functions for debugging purpose (DHCPv6)
#define INFINITE_DELAY
Definition: os_port.h:74
@ DHCPV6_MSG_TYPE_REQUEST
Definition: dhcpv6_common.h:92
OsTaskId taskId
Task identifier.
Definition: dhcpv6_relay.h:103