Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dhcpv6_relay.c
00001 /** 00002 * @file dhcpv6_relay.c 00003 * @brief DHCPv6 relay agent (Dynamic Host Configuration Protocol for IPv6) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @section Description 00026 * 00027 * DHCPv6 Relay-Agents are deployed to forward DHCPv6 messages between clients 00028 * and servers when they are not on the same IPv6 link and are often implemented 00029 * alongside a routing function in a common node. Refer to RFC 3315 00030 * 00031 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00032 * @version 1.7.6 00033 **/ 00034 00035 //Switch to the appropriate trace level 00036 #define TRACE_LEVEL DHCPV6_TRACE_LEVEL 00037 00038 //Dependencies 00039 #include "core/net.h" 00040 #include "dhcpv6_relay.h" 00041 #include "dhcpv6/dhcpv6_common.h" 00042 #include "dhcpv6/dhcpv6_debug.h" 00043 #include "debug.h" 00044 00045 //Check TCP/IP stack configuration 00046 #if (IPV6_SUPPORT == ENABLED && DHCPV6_RELAY_SUPPORT == ENABLED) 00047 00048 00049 /** 00050 * @brief Start DHCPv6 relay agent 00051 * @param[in] context Pointer to the DHCPv6 relay agent context 00052 * @param[in] settings DHCPv6 relay agent specific settings 00053 * @return Error code 00054 **/ 00055 00056 error_t dhcpv6RelayStart(Dhcpv6RelayContext *context, const Dhcpv6RelaySettings *settings) 00057 { 00058 error_t error; 00059 uint_t i; 00060 OsTask *task; 00061 00062 //Debug message 00063 TRACE_INFO("Starting DHCPv6 relay agent...\r\n"); 00064 00065 //Ensure the parameters are valid 00066 if(!context || !settings) 00067 return ERROR_INVALID_PARAMETER; 00068 //The pointer to the network-facing interface shall be valid 00069 if(!settings->serverInterface) 00070 return ERROR_INVALID_INTERFACE; 00071 //Check the number of client-facing interfaces 00072 if(!settings->clientInterfaceCount) 00073 return ERROR_INVALID_PARAMETER; 00074 if(settings->clientInterfaceCount >= DHCPV6_RELAY_MAX_CLIENT_IF) 00075 return ERROR_INVALID_PARAMETER; 00076 00077 //Loop through the client-facing interfaces 00078 for(i = 0; i < settings->clientInterfaceCount; i++) 00079 { 00080 //A valid pointer is required for each interface 00081 if(!settings->clientInterface[i]) 00082 return ERROR_INVALID_INTERFACE; 00083 } 00084 00085 //Check the address to be used when forwarding messages to the server 00086 if(ipv6CompAddr(&settings->serverAddress, &IPV6_UNSPECIFIED_ADDR)) 00087 return ERROR_INVALID_ADDRESS; 00088 00089 //Clear the DHCPv6 relay agent context 00090 memset(context, 0, sizeof(Dhcpv6RelayContext)); 00091 00092 //Save the network-facing interface 00093 context->serverInterface = settings->serverInterface; 00094 //Save the number of client-facing interfaces 00095 context->clientInterfaceCount = settings->clientInterfaceCount; 00096 00097 //Save all the client-facing interfaces 00098 for(i = 0; i < context->clientInterfaceCount; i++) 00099 context->clientInterface[i] = settings->clientInterface[i]; 00100 00101 //Save the address to be used when relaying client messages to the server 00102 context->serverAddress = settings->serverAddress; 00103 00104 //Join the All_DHCP_Relay_Agents_and_Servers multicast group 00105 //for each client-facing interface 00106 error = dhcpv6RelayJoinMulticastGroup(context); 00107 //Any error to report? 00108 if(error) 00109 return error; 00110 00111 //Start of exception handling block 00112 do 00113 { 00114 //Open a UDP socket to handle the network-facing interface 00115 context->serverSocket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP); 00116 //Failed to open socket? 00117 if(!context->serverSocket) 00118 { 00119 //Report an error 00120 error = ERROR_OPEN_FAILED; 00121 //Stop processing 00122 break; 00123 } 00124 00125 //Explicitly associate the socket with the relevant interface 00126 error = socketBindToInterface(context->serverSocket, context->serverInterface); 00127 //Unable to bind the socket to the desired interface? 00128 if(error) 00129 break; 00130 00131 //Relay agents listen for DHCPv6 messages on UDP port 547 00132 error = socketBind(context->serverSocket, &IP_ADDR_ANY, DHCPV6_SERVER_PORT); 00133 //Unable to bind the socket to the desired port? 00134 if(error) 00135 break; 00136 00137 //Only accept datagrams with source port number 547 00138 error = socketConnect(context->serverSocket, &IP_ADDR_ANY, DHCPV6_SERVER_PORT); 00139 //Any error to report? 00140 if(error) 00141 break; 00142 00143 //If the relay agent relays messages to the All_DHCP_Servers address 00144 //or other multicast addresses, it sets the Hop Limit field to 32 00145 00146 //Loop through the client-facing interfaces 00147 for(i = 0; i < context->clientInterfaceCount; i++) 00148 { 00149 //Open a UDP socket to handle the current interface 00150 context->clientSocket[i] = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP); 00151 //Failed to open socket? 00152 if(!context->clientSocket[i]) 00153 { 00154 //Report an error 00155 error = ERROR_OPEN_FAILED; 00156 //Stop processing 00157 break; 00158 } 00159 00160 //Explicitly associate the socket with the relevant interface 00161 error = socketBindToInterface(context->clientSocket[i], context->clientInterface[i]); 00162 //Unable to bind the socket to the desired interface? 00163 if(error) 00164 break; 00165 00166 //Relay agents listen for DHCPv6 messages on UDP port 547 00167 error = socketBind(context->clientSocket[i], &IP_ADDR_ANY, DHCPV6_SERVER_PORT); 00168 //Unable to bind the socket to the desired port? 00169 if(error) 00170 break; 00171 00172 //Only accept datagrams with source port number 546 00173 error = socketConnect(context->clientSocket[i], &IP_ADDR_ANY, DHCPV6_CLIENT_PORT); 00174 //Any error to report? 00175 if(error) 00176 break; 00177 } 00178 00179 //Propagate exception if necessary... 00180 if(error) 00181 break; 00182 00183 //Initialize event object 00184 if(!osCreateEvent(&context->event)) 00185 { 00186 //Failed to create event 00187 error = ERROR_OUT_OF_RESOURCES; 00188 //Stop processing 00189 break; 00190 } 00191 00192 //Initialize ACK event object 00193 if(!osCreateEvent(&context->ackEvent)) 00194 { 00195 //Failed to create event 00196 error = ERROR_OUT_OF_RESOURCES; 00197 //Stop processing 00198 break; 00199 } 00200 00201 //The DHCPv6 relay agent is now running 00202 context->running = TRUE; 00203 00204 //Start the DHCPv6 relay agent service 00205 task = osCreateTask("DHCPv6 Relay", dhcpv6RelayTask, 00206 context, DHCPV6_RELAY_STACK_SIZE, DHCPV6_RELAY_PRIORITY); 00207 00208 //Unable to create the task? 00209 if(task == OS_INVALID_HANDLE) 00210 error = ERROR_OUT_OF_RESOURCES; 00211 00212 //End of exception handling block 00213 } while(0); 00214 00215 //Did we encounter an error? 00216 if(error) 00217 { 00218 //Close the socket associated with the network-facing interface 00219 socketClose(context->serverSocket); 00220 00221 //Close the socket associated with each client-facing interface 00222 for(i = 0; i < context->clientInterfaceCount; i++) 00223 socketClose(context->clientSocket[i]); 00224 00225 //Leave the All_DHCP_Relay_Agents_and_Servers multicast group 00226 //for each client-facing interface 00227 dhcpv6RelayLeaveMulticastGroup(context); 00228 00229 //Delete event objects 00230 osDeleteEvent(&context->event); 00231 osDeleteEvent(&context->ackEvent); 00232 } 00233 00234 //Return status code 00235 return error; 00236 } 00237 00238 00239 /** 00240 * @brief Stop DHCPv6 relay agent 00241 * @param[in] context Pointer to the DHCPv6 relay agent context 00242 * @return Error code 00243 **/ 00244 00245 error_t dhcpv6RelayStop(Dhcpv6RelayContext *context) 00246 { 00247 uint_t i; 00248 00249 //Debug message 00250 TRACE_INFO("Stopping DHCPv6 relay agent...\r\n"); 00251 00252 //Ensure the specified pointer is valid 00253 if(context == NULL) 00254 return ERROR_INVALID_PARAMETER; 00255 //Check DHCPv6 relay agent state 00256 if(!context->running) 00257 return ERROR_WRONG_STATE; 00258 00259 //Reset ACK event before sending the kill signal 00260 osResetEvent(&context->ackEvent); 00261 //Stop the DHCPv6 relay agent task 00262 context->stopRequest = TRUE; 00263 //Send a signal to the task in order to abort any blocking operation 00264 osSetEvent(&context->event); 00265 00266 //Wait for the process to terminate... 00267 osWaitForEvent(&context->ackEvent, INFINITE_DELAY); 00268 00269 //Leave the All_DHCP_Relay_Agents_and_Servers multicast group 00270 //for each client-facing interface 00271 dhcpv6RelayLeaveMulticastGroup(context); 00272 00273 //Close the socket that carries traffic towards the DHCPv6 server 00274 socketClose(context->serverSocket); 00275 00276 //Properly dispose the sockets that carry traffic towards the DHCPv6 clients 00277 for(i = 0; i < context->clientInterfaceCount; i++) 00278 socketClose(context->clientSocket[i]); 00279 00280 //Delete event objects 00281 osDeleteEvent(&context->event); 00282 osDeleteEvent(&context->ackEvent); 00283 00284 //Successful processing 00285 return NO_ERROR; 00286 } 00287 00288 00289 /** 00290 * @brief Join All_DHCP_Relay_Agents_and_Servers multicast group 00291 * @param[in] context Pointer to the DHCPv6 relay agent context 00292 **/ 00293 00294 error_t dhcpv6RelayJoinMulticastGroup(Dhcpv6RelayContext *context) 00295 { 00296 uint_t i; 00297 uint_t j; 00298 00299 //Initialize status code 00300 error_t error = NO_ERROR; 00301 00302 //Loop through the client-facing interfaces 00303 for(i = 0; i < context->clientInterfaceCount; i++) 00304 { 00305 //Join the All_DHCP_Relay_Agents_and_Servers multicast 00306 //group for each interface 00307 error = ipv6JoinMulticastGroup(context->clientInterface[i], 00308 &DHCPV6_ALL_RELAY_AGENTS_AND_SERVERS_ADDR); 00309 //Unable to join the specified multicast group? 00310 if(error) 00311 break; 00312 } 00313 00314 //Did we encounter an error? 00315 if(error) 00316 { 00317 //Clean up side effects before returning... 00318 for(j = 0; j < i; j++) 00319 { 00320 //Leave the multicast group for each interface 00321 ipv6LeaveMulticastGroup(context->clientInterface[j], 00322 &DHCPV6_ALL_RELAY_AGENTS_AND_SERVERS_ADDR); 00323 } 00324 } 00325 00326 //Return status code 00327 return error; 00328 } 00329 00330 00331 /** 00332 * @brief Leave All_DHCP_Relay_Agents_and_Servers multicast group 00333 * @param[in] context Pointer to the DHCPv6 relay agent context 00334 **/ 00335 00336 error_t dhcpv6RelayLeaveMulticastGroup(Dhcpv6RelayContext *context) 00337 { 00338 uint_t i; 00339 00340 //Loop through the client-facing interfaces 00341 for(i = 0; i < context->clientInterfaceCount; i++) 00342 { 00343 //Leave the All_DHCP_Relay_Agents_and_Servers multicast 00344 //group for each interface 00345 ipv6LeaveMulticastGroup(context->clientInterface[i], 00346 &DHCPV6_ALL_RELAY_AGENTS_AND_SERVERS_ADDR); 00347 } 00348 00349 //Successsful processing 00350 return NO_ERROR; 00351 } 00352 00353 00354 /** 00355 * @brief DHCPv6 relay agent task 00356 * @param[in] param Pointer to the DHCPv6 relay agent context 00357 **/ 00358 00359 void dhcpv6RelayTask(void *param) 00360 { 00361 error_t error; 00362 uint_t i; 00363 00364 //Point to the DHCPv6 relay agent context 00365 Dhcpv6RelayContext *context = (Dhcpv6RelayContext *) param; 00366 00367 //Specify the events the application is interested in for 00368 //each client-facing sockets 00369 for(i = 0; i < context->clientInterfaceCount; i++) 00370 { 00371 context->eventDesc[i].socket = context->clientSocket[i]; 00372 context->eventDesc[i].eventMask = SOCKET_EVENT_RX_READY; 00373 } 00374 00375 //Specify the events the application is interested in for 00376 //the network-facing socket 00377 context->eventDesc[i].socket = context->serverSocket; 00378 context->eventDesc[i].eventMask = SOCKET_EVENT_RX_READY; 00379 00380 //Main loop 00381 while(1) 00382 { 00383 //Wait for incoming packets on network-facing or client-facing interfaces 00384 error = socketPoll(context->eventDesc, context->clientInterfaceCount + 1, 00385 &context->event, INFINITE_DELAY); 00386 00387 //Stop DHCPv6 relay agent? 00388 if(context->stopRequest) 00389 { 00390 //The DHCPv6 relay agent is about to stop 00391 context->stopRequest = FALSE; 00392 context->running = FALSE; 00393 //Acknowledge the reception of the user request 00394 osSetEvent(&context->ackEvent); 00395 //Kill ourselves 00396 osDeleteTask(NULL); 00397 } 00398 00399 //Verify status code 00400 if(!error) 00401 { 00402 //Check the state of each client-facing socket 00403 for(i = 0; i < context->clientInterfaceCount; i++) 00404 { 00405 //Relay client messages if applicable 00406 if(context->eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY) 00407 dhcpv6ForwardClientMessage(context, i); 00408 } 00409 00410 //Check the state of the network-facing socket 00411 if(context->eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY) 00412 { 00413 //Forward Relay-Reply messages from the network 00414 dhcpv6ForwardRelayReplyMessage(context); 00415 } 00416 } 00417 } 00418 } 00419 00420 00421 /** 00422 * @brief Forward client message 00423 * @param[in] context Pointer to the DHCPv6 relay agent context 00424 * @param[in] index Index identifying the interface on which the message was received 00425 * @return Error code 00426 **/ 00427 00428 error_t dhcpv6ForwardClientMessage(Dhcpv6RelayContext *context, uint_t index) 00429 { 00430 error_t error; 00431 uint32_t interfaceId; 00432 size_t inputMessageLen; 00433 size_t outputMessageLen; 00434 Dhcpv6RelayMessage *inputMessage; 00435 Dhcpv6RelayMessage *outputMessage; 00436 Dhcpv6Option *option; 00437 IpAddr ipAddr; 00438 00439 //Point to the buffer where to store the incoming DHCPv6 message 00440 inputMessage = (Dhcpv6RelayMessage *) (context->buffer + DHCPV6_RELAY_FORW_OVERHEAD); 00441 //Message that will be forwarded by the DHCPv6 relay agent 00442 outputMessage = (Dhcpv6RelayMessage *) context->buffer; 00443 00444 //Read incoming message 00445 error = socketReceiveFrom(context->clientSocket[index], &ipAddr, NULL, inputMessage, 00446 DHCPV6_MAX_MSG_SIZE - DHCPV6_RELAY_FORW_OVERHEAD, &inputMessageLen, 0); 00447 //Any error to report? 00448 if(error) 00449 return error; 00450 00451 //Debug message 00452 TRACE_INFO("\r\nDHCPv6 message received on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n", 00453 context->clientInterface[index]->name, inputMessageLen); 00454 00455 //Dump the contents of the message for debugging purpose 00456 dhcpv6DumpMessage(inputMessage, inputMessageLen); 00457 00458 //The source address must be a valid IPv6 address 00459 if(ipAddr.length != sizeof(Ipv6Addr)) 00460 return ERROR_INVALID_ADDRESS; 00461 //Check the length of the DHCPv6 message 00462 if(inputMessageLen < sizeof(Dhcpv6Message)) 00463 return ERROR_INVALID_MESSAGE; 00464 00465 //When the relay agent receives a valid message to be relayed, 00466 //it constructs a new Relay-Forward message 00467 outputMessage->msgType = DHCPV6_MSG_TYPE_RELAY_FORW; 00468 00469 //Inspect the message type 00470 switch(inputMessage->msgType) 00471 { 00472 //Message received from a client? 00473 case DHCPV6_MSG_TYPE_SOLICIT: 00474 case DHCPV6_MSG_TYPE_REQUEST: 00475 case DHCPV6_MSG_TYPE_CONFIRM: 00476 case DHCPV6_MSG_TYPE_RENEW: 00477 case DHCPV6_MSG_TYPE_REBIND: 00478 case DHCPV6_MSG_TYPE_RELEASE: 00479 case DHCPV6_MSG_TYPE_DECLINE: 00480 case DHCPV6_MSG_TYPE_INFO_REQUEST: 00481 //If the relay agent received the message to be relayed from a client 00482 //the hop-count in the Relay-Forward message is set to 0 00483 outputMessage->hopCount = 0; 00484 //Continue processing 00485 break; 00486 00487 //Message received from another relay agent? 00488 case DHCPV6_MSG_TYPE_RELAY_FORW: 00489 //If the message received by the relay agent is a Relay-Forward message 00490 //and the hop-count in the message is greater than or equal to 32, the 00491 //relay agent discards the received message 00492 if(inputMessage->hopCount >= DHCPV6_HOP_COUNT_LIMIT) 00493 return ERROR_INVALID_MESSAGE; 00494 //Set the hop-count field to the value of the hop-count field in 00495 //the received message incremented by 1 00496 outputMessage->hopCount = inputMessage->hopCount + 1; 00497 //Continue processing 00498 break; 00499 00500 //Message received from a server? 00501 default: 00502 //Discard ADVERTISE, REPLY, RECONFIGURE and RELAY-REPL messages 00503 return ERROR_INVALID_MESSAGE; 00504 } 00505 00506 //Set the link-address field to the unspecified address 00507 outputMessage->linkAddress = IPV6_UNSPECIFIED_ADDR; 00508 //Copy the source address from the header of the IP datagram in 00509 //which the message was received to the peer-address field 00510 outputMessage->peerAddress = ipAddr.ipv6Addr; 00511 //Size of the Relay-Forward message 00512 outputMessageLen = sizeof(Dhcpv6RelayMessage); 00513 00514 //Get the interface identifier 00515 interfaceId = context->clientInterface[index]->id; 00516 //Convert the 32-bit integer to network byte order 00517 interfaceId = htonl(interfaceId); 00518 00519 //If the relay agent cannot use the address in the link-address field 00520 //to identify the interface through which the response to the client 00521 //will be relayed, the relay agent must include an Interface ID option 00522 dhcpv6AddOption(outputMessage, &outputMessageLen, 00523 DHCPV6_OPTION_INTERFACE_ID, &interfaceId, sizeof(interfaceId)); 00524 00525 //Copy the received DHCPv6 message into a Relay Message option 00526 option = dhcpv6AddOption(outputMessage, &outputMessageLen, 00527 DHCPV6_OPTION_RELAY_MSG, NULL, 0); 00528 00529 //Set the appropriate length of the option 00530 option->length = htons(inputMessageLen); 00531 //Adjust the length of the Relay-Forward message 00532 outputMessageLen += inputMessageLen; 00533 00534 //Debug message 00535 TRACE_INFO("Forwarding DHCPv6 message on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n", 00536 context->serverInterface->name, outputMessageLen); 00537 00538 //Dump the contents of the message for debugging purpose 00539 dhcpv6DumpMessage(outputMessage, outputMessageLen); 00540 00541 //Destination address to be used when relaying the client message 00542 ipAddr.length = sizeof(Ipv6Addr); 00543 ipAddr.ipv6Addr = context->serverAddress; 00544 00545 //Relay the client message to the server 00546 return socketSendTo(context->serverSocket, &ipAddr, 00547 DHCPV6_SERVER_PORT, outputMessage, outputMessageLen, NULL, 0); 00548 } 00549 00550 00551 /** 00552 * @brief Forward Relay-Reply message 00553 * @param[in] context Pointer to the DHCPv6 relay agent context 00554 * @return Error code 00555 **/ 00556 00557 error_t dhcpv6ForwardRelayReplyMessage(Dhcpv6RelayContext *context) 00558 { 00559 error_t error; 00560 uint_t i; 00561 uint32_t interfaceId; 00562 size_t inputMessageLen; 00563 size_t outputMessageLen; 00564 Dhcpv6RelayMessage *inputMessage; 00565 Dhcpv6Message *outputMessage; 00566 Dhcpv6Option *option; 00567 IpAddr ipAddr; 00568 uint16_t port; 00569 00570 //Point to the buffer where to store the incoming DHCPv6 message 00571 inputMessage = (Dhcpv6RelayMessage *) context->buffer; 00572 00573 //Read incoming message 00574 error = socketReceiveFrom(context->serverSocket, &ipAddr, &port, 00575 inputMessage, DHCPV6_MAX_MSG_SIZE, &inputMessageLen, 0); 00576 //Any error to report? 00577 if(error) 00578 return error; 00579 00580 //Debug message 00581 TRACE_INFO("\r\nDHCPv6 message received on network-facing interface %s (%" PRIuSIZE " bytes)...\r\n", 00582 context->serverInterface->name, inputMessageLen); 00583 00584 //Dump the contents of the message for debugging purpose 00585 dhcpv6DumpMessage(inputMessage, inputMessageLen); 00586 00587 //Check the length of the DHCPv6 message 00588 if(inputMessageLen < sizeof(Dhcpv6RelayMessage)) 00589 return ERROR_INVALID_MESSAGE; 00590 00591 //Inspect the message type and only forward Relay-Reply messages. 00592 //Other DHCPv6 message types must be silently discarded 00593 if(inputMessage->msgType != DHCPV6_MSG_TYPE_RELAY_REPL) 00594 return ERROR_INVALID_MESSAGE; 00595 00596 //Get the length of the Options field 00597 inputMessageLen -= sizeof(Dhcpv6Message); 00598 00599 //Check whether an Interface ID option is included in the Relay-Reply 00600 option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPTION_INTERFACE_ID); 00601 //Failed to retrieve specified option? 00602 if(option == NULL || ntohs(option->length) != sizeof(interfaceId)) 00603 return ERROR_INVALID_MESSAGE; 00604 00605 //Read the Interface ID option contents 00606 memcpy(&interfaceId, option->value, sizeof(interfaceId)); 00607 //Convert the 32-bit integer from network byte order 00608 interfaceId = ntohl(interfaceId); 00609 00610 //The Relay-Reply message must include a Relay Message option 00611 option = dhcpv6GetOption(inputMessage->options, inputMessageLen, DHCPV6_OPTION_RELAY_MSG); 00612 //Failed to retrieve specified option? 00613 if(option == NULL || ntohs(option->length) < sizeof(Dhcpv6Message)) 00614 return ERROR_INVALID_MESSAGE; 00615 00616 //Extract the message from the Relay Message option 00617 outputMessage = (Dhcpv6Message *) option->value; 00618 //Save the length of the message 00619 outputMessageLen = ntohs(option->length); 00620 00621 //Loop through client-facing interfaces 00622 for(i = 0; i < context->clientInterfaceCount; i++) 00623 { 00624 //Check whether the current interface matches the Interface ID option 00625 if(context->clientInterface[i]->id == interfaceId) 00626 { 00627 //Debug message 00628 TRACE_INFO("Forwarding DHCPv6 message on client-facing interface %s (%" PRIuSIZE " bytes)...\r\n", 00629 context->clientInterface[i]->name, outputMessageLen); 00630 00631 //Dump the contents of the message for debugging purpose 00632 dhcpv6DumpMessage(outputMessage, outputMessageLen); 00633 00634 //Copy the peer-address into the destination IP address 00635 ipAddr.length = sizeof(Ipv6Addr); 00636 ipAddr.ipv6Addr = inputMessage->peerAddress; 00637 00638 //Select the relevant port number to use 00639 if(outputMessage->msgType == DHCPV6_MSG_TYPE_RELAY_REPL) 00640 port = DHCPV6_SERVER_PORT; 00641 else 00642 port = DHCPV6_CLIENT_PORT; 00643 00644 //Relay the DHCPv6 message to the client on the link 00645 //identified by the Interface ID option 00646 return socketSendTo(context->clientSocket[i], &ipAddr, 00647 port, outputMessage, outputMessageLen, NULL, 0); 00648 } 00649 } 00650 00651 //Unknown interface identifier... 00652 return ERROR_INVALID_OPTION; 00653 } 00654 00655 #endif 00656
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2