dhcp_common.c
Go to the documentation of this file.
1 /**
2  * @file dhcp_common.c
3  * @brief Definitions common to DHCP client and server
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL DHCP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "dhcp/dhcp_client.h"
37 #include "dhcp/dhcp_server.h"
38 #include "dhcp/dhcp_common.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (IPV4_SUPPORT == ENABLED && (DHCP_CLIENT_SUPPORT == ENABLED || \
43  DHCP_SERVER_SUPPORT == ENABLED))
44 
45 
46 /**
47  * @brief Append an option to a DHCP message
48  * @param[in] message Pointer to the DHCP message
49  * @param[in,out] messageLen Actual length of the DHCP message
50  * @param[in] optionCode Option code
51  * @param[in] optionValue Option value
52  * @param[in] optionLen Length of the option value
53  * @return Error code
54  **/
55 
57  uint8_t optionCode, const void *optionValue, size_t optionLen)
58 {
59  size_t n;
60  DhcpOption *option;
61 
62  //Check parameters
63  if(message == NULL || messageLen == NULL)
65 
66  //Check the length of the DHCP message
67  if(*messageLen < (sizeof(DhcpMessage) + sizeof(uint8_t)))
68  return ERROR_INVALID_LENGTH;
69 
70  //Check the length of the option
71  if(optionLen > 0 && optionValue == NULL)
73 
74  if(optionLen > UINT8_MAX)
75  return ERROR_INVALID_LENGTH;
76 
77  //Ensure that the length of the resulting message will not exceed the
78  //maximum DHCP message size
79  if((*messageLen + sizeof(DhcpOption) + optionLen) > DHCP_MAX_MSG_SIZE)
80  return ERROR_BUFFER_OVERFLOW;
81 
82  //Retrieve the total length of the options field, excluding the end option
83  n = *messageLen - sizeof(DhcpMessage) - sizeof(uint8_t);
84 
85  //Point to the buffer where to format the option
86  option = (DhcpOption *) (message->options + n);
87 
88  //Set option code
89  option->code = optionCode;
90  //Set option length
91  option->length = (uint8_t) optionLen;
92  //Copy option value
93  osMemcpy(option->value, optionValue, optionLen);
94 
95  //Determine the length of the options field
96  n += sizeof(DhcpOption) + option->length;
97 
98  //Always terminate the options field with 255
99  message->options[n++] = DHCP_OPT_END;
100 
101  //Update the length of the DHCPv6 message
102  *messageLen = sizeof(DhcpMessage) + n;
103 
104  //Successful processing
105  return NO_ERROR;
106 }
107 
108 
109 /**
110  * @brief Search a DHCP message for a given option
111  * @param[in] message Pointer to the DHCP message
112  * @param[in] length Length of the message
113  * @param[in] optionCode Code of the option to find
114  * @return If the specified option is found, a pointer to the corresponding
115  * option is returned. Otherwise NULL pointer is returned
116  **/
117 
119  uint8_t optionCode)
120 {
121  size_t i;
122  DhcpOption *option;
123 
124  //Make sure the DHCP header is valid
125  if(length >= sizeof(DhcpMessage))
126  {
127  //Get the length of the options field
128  length -= sizeof(DhcpMessage);
129 
130  //Loop through the list of options
131  for(i = 0; i < length; i++)
132  {
133  //Point to the current option
134  option = (DhcpOption *) (message->options + i);
135 
136  //Check option code
137  if(option->code == DHCP_OPT_PAD)
138  {
139  //The pad option can be used to cause subsequent fields to align
140  //on word boundaries
141  }
142  else if(option->code == DHCP_OPT_END)
143  {
144  //The end option marks the end of valid information in the vendor
145  //field
146  break;
147  }
148  else
149  {
150  //The option code is followed by a one-byte length field
151  if((i + 1) >= length)
152  {
153  break;
154  }
155 
156  //Check the length of the option
157  if((i + sizeof(DhcpOption) + option->length) > length)
158  {
159  break;
160  }
161 
162  //Matching option code?
163  if(option->code == optionCode)
164  {
165  return option;
166  }
167 
168  //Jump to the next option
169  i += option->length + 1;
170  }
171  }
172  }
173 
174  //The specified option code was not found
175  return NULL;
176 }
177 
178 #endif
DHCP client (Dynamic Host Configuration Protocol)
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
uint8_t message[]
Definition: chap.h:154
#define DHCP_MAX_MSG_SIZE
Definition: dhcp_common.h:46
@ DHCP_OPT_END
Definition: dhcp_common.h:191
error_t dhcpAddOption(DhcpMessage *message, size_t *messageLen, uint8_t optionCode, const void *optionValue, size_t optionLen)
Append an option to a DHCP message.
Definition: dhcp_common.c:56
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
@ DHCP_OPT_PAD
Definition: dhcp_common.h:106
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_LENGTH
Definition: error.h:111
DhcpMessage
Definition: dhcp_common.h:226
Definitions common to DHCP client and server.
uint8_t length
Definition: tcp.h:368
uint8_t n
DhcpOption
Definition: dhcp_common.h:238
TCP/IP stack core.
DHCP server (Dynamic Host Configuration Protocol)
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
DhcpOption * dhcpGetOption(const DhcpMessage *message, size_t length, uint8_t optionCode)
Search a DHCP message for a given option.
Definition: dhcp_common.c:118