-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathdhcp_common.c
178 lines (149 loc) · 5.06 KB
/
dhcp_common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* @file dhcp_common.c
* @brief Definitions common to DHCP client and server
*
* @section License
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
*
* This file is part of CycloneTCP Open.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @author Oryx Embedded SARL (www.oryx-embedded.com)
* @version 2.5.0
**/
//Switch to the appropriate trace level
#define TRACE_LEVEL DHCP_TRACE_LEVEL
//Dependencies
#include "core/net.h"
#include "dhcp/dhcp_client.h"
#include "dhcp/dhcp_server.h"
#include "dhcp/dhcp_common.h"
#include "debug.h"
//Check TCP/IP stack configuration
#if (IPV4_SUPPORT == ENABLED && (DHCP_CLIENT_SUPPORT == ENABLED || \
DHCP_SERVER_SUPPORT == ENABLED))
/**
* @brief Append an option to a DHCP message
* @param[in] message Pointer to the DHCP message
* @param[in,out] messageLen Actual length of the DHCP message
* @param[in] optionCode Option code
* @param[in] optionValue Option value
* @param[in] optionLen Length of the option value
* @return Error code
**/
error_t dhcpAddOption(DhcpMessage *message, size_t *messageLen,
uint8_t optionCode, const void *optionValue, size_t optionLen)
{
size_t n;
DhcpOption *option;
//Check parameters
if(message == NULL || messageLen == NULL)
return ERROR_INVALID_PARAMETER;
//Check the length of the DHCP message
if(*messageLen < (sizeof(DhcpMessage) + sizeof(uint8_t)))
return ERROR_INVALID_LENGTH;
//Check the length of the option
if(optionLen > 0 && optionValue == NULL)
return ERROR_INVALID_PARAMETER;
if(optionLen > UINT8_MAX)
return ERROR_INVALID_LENGTH;
//Ensure that the length of the resulting message will not exceed the
//maximum DHCP message size
if((*messageLen + sizeof(DhcpOption) + optionLen) > DHCP_MAX_MSG_SIZE)
return ERROR_BUFFER_OVERFLOW;
//Retrieve the total length of the options field, excluding the end option
n = *messageLen - sizeof(DhcpMessage) - sizeof(uint8_t);
//Point to the buffer where to format the option
option = (DhcpOption *) (message->options + n);
//Set option code
option->code = optionCode;
//Set option length
option->length = (uint8_t) optionLen;
//Copy option value
osMemcpy(option->value, optionValue, optionLen);
//Determine the length of the options field
n += sizeof(DhcpOption) + option->length;
//Always terminate the options field with 255
message->options[n++] = DHCP_OPT_END;
//Update the length of the DHCPv6 message
*messageLen = sizeof(DhcpMessage) + n;
//Successful processing
return NO_ERROR;
}
/**
* @brief Search a DHCP message for a given option
* @param[in] message Pointer to the DHCP message
* @param[in] length Length of the message
* @param[in] optionCode Code of the option to find
* @return If the specified option is found, a pointer to the corresponding
* option is returned. Otherwise NULL pointer is returned
**/
DhcpOption *dhcpGetOption(const DhcpMessage *message, size_t length,
uint8_t optionCode)
{
size_t i;
DhcpOption *option;
//Make sure the DHCP header is valid
if(length >= sizeof(DhcpMessage))
{
//Get the length of the options field
length -= sizeof(DhcpMessage);
//Loop through the list of options
for(i = 0; i < length; i++)
{
//Point to the current option
option = (DhcpOption *) (message->options + i);
//Check option code
if(option->code == DHCP_OPT_PAD)
{
//The pad option can be used to cause subsequent fields to align
//on word boundaries
}
else if(option->code == DHCP_OPT_END)
{
//The end option marks the end of valid information in the vendor
//field
break;
}
else
{
//The option code is followed by a one-byte length field
if((i + 1) >= length)
{
break;
}
//Check the length of the option
if((i + sizeof(DhcpOption) + option->length) > length)
{
break;
}
//Matching option code?
if(option->code == optionCode)
{
return option;
}
//Jump to the next option
i += option->length + 1;
}
}
}
//The specified option code was not found
return NULL;
}
#endif