ppp_misc.c
Go to the documentation of this file.
1 /**
2  * @file ppp_misc.c
3  * @brief PPP miscellaneous functions
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 PPP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "ppp/ppp_misc.h"
37 #include "ppp/ppp_debug.h"
38 #include "ppp/lcp.h"
39 #include "ppp/ipcp.h"
40 #include "ppp/ipv6cp.h"
41 #include "debug.h"
42 
43 //Check TCP/IP stack configuration
44 #if (PPP_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Send Configure-Ack, Nak or Reject packet
49  * @param[in] context PPP context
50  * @param[in] configureReqPacket Pointer to the incoming Configure-Request
51  * @param[in] protocol Protocol field
52  * @param[in] code Code field
53  * @return Error code
54  **/
55 
57  const PppConfigurePacket *configureReqPacket, PppProtocol protocol, PppCode code)
58 {
59  error_t error;
60  size_t length;
61  size_t offset;
62  NetBuffer *buffer;
63  PppConfigurePacket *configureAckNakPacket;
64  PppOption *option;
65 
66  //Initialize status code
67  error = NO_ERROR;
68  //Retrieve the length of the Configure-Request packet
69  length = ntohs(configureReqPacket->length);
70 
71  //Allocate a buffer memory to hold the Configure-Ack, Nak or Reject packet
72  buffer = pppAllocBuffer(length, &offset);
73  //Failed to allocate memory?
74  if(buffer == NULL)
75  return ERROR_OUT_OF_MEMORY;
76 
77  //Point to the beginning of the packet
78  configureAckNakPacket = netBufferAt(buffer, offset, 0);
79 
80  //Format packet header
81  configureAckNakPacket->code = code;
82  configureAckNakPacket->identifier = configureReqPacket->identifier;
83  configureAckNakPacket->length = sizeof(PppConfigurePacket);
84 
85  //Retrieve the length of the option list
86  length -= sizeof(PppConfigurePacket);
87  //Point to the first option
88  option = (PppOption *) configureReqPacket->options;
89 
90  //Parse configuration options
91  while(length > 0)
92  {
93  //LCP protocol?
95  {
96  //Parse LCP option
97  lcpParseOption(context, option, length, configureAckNakPacket);
98  }
99 #if (IPV4_SUPPORT == ENABLED)
100  //IPCP protocol?
101  else if(protocol == PPP_PROTOCOL_IPCP)
102  {
103  //Parse IPCP option
104  ipcpParseOption(context, option, length, configureAckNakPacket);
105  }
106 #endif
107 #if (IPV6_SUPPORT == ENABLED)
108  //IPV6CP protocol?
109  else if(protocol == PPP_PROTOCOL_IPV6CP)
110  {
111  //Parse IPV6CP option
112  ipv6cpParseOption(context, option, length, configureAckNakPacket);
113  }
114 #endif
115 
116  //Remaining bytes to process
117  length -= option->length;
118  //Jump to the next option
119  option = (PppOption *) ((uint8_t *) option + option->length);
120  }
121 
122  //Adjust the length of the multi-part buffer
123  netBufferSetLength(buffer, offset + configureAckNakPacket->length);
124  //Convert length field to network byte order
125  configureAckNakPacket->length = htons(configureAckNakPacket->length);
126 
127  //Debug message
129  {
130  TRACE_INFO("Sending Configure-Ack packet (%" PRIuSIZE " bytes)...\r\n",
131  ntohs(configureAckNakPacket->length));
132  }
133  else if(code == PPP_CODE_CONFIGURE_NAK)
134  {
135  TRACE_INFO("Sending Configure-Nak packet (%" PRIuSIZE " bytes)...\r\n",
136  ntohs(configureAckNakPacket->length));
137  }
138  else if(code == PPP_CODE_CONFIGURE_REJ)
139  {
140  TRACE_INFO("Sending Configure-Reject packet (%" PRIuSIZE " bytes)...\r\n",
141  ntohs(configureAckNakPacket->length));
142  }
143 
144  //Dump packet contents for debugging purpose
145  pppDumpPacket((PppPacket *) configureAckNakPacket,
146  ntohs(configureAckNakPacket->length), protocol);
147 
148  //Send PPP frame
149  error = pppSendFrame(context->interface, buffer, offset, protocol);
150 
151  //Free previously allocated memory block
152  netBufferFree(buffer);
153 
154  //Return status code
155  return error;
156 }
157 
158 
159 /**
160  * @brief Send Terminate-Request packet
161  * @param[in] context PPP context
162  * @param[in] identifier Identifier field
163  * @param[in] protocol Protocol field
164  * @return Error code
165  **/
166 
169 {
170  error_t error;
171  size_t length;
172  size_t offset;
173  NetBuffer *buffer;
174  PppTerminatePacket *terminateReqPacket;
175 
176  //Length of the Terminate-Request packet
177  length = sizeof(PppTerminatePacket);
178 
179  //Allocate a buffer memory to hold the Terminate-Request packet
180  buffer = pppAllocBuffer(length, &offset);
181  //Failed to allocate memory?
182  if(buffer == NULL)
183  return ERROR_OUT_OF_MEMORY;
184 
185  //Point to the Terminate-Request packet
186  terminateReqPacket = netBufferAt(buffer, offset, 0);
187 
188  //Format packet header
189  terminateReqPacket->code = PPP_CODE_TERMINATE_REQ;
190  terminateReqPacket->identifier = identifier;
191  terminateReqPacket->length = htons(length);
192 
193  //Debug message
194  TRACE_INFO("Sending Terminate-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
195  //Dump packet contents for debugging purpose
196  pppDumpPacket((PppPacket *) terminateReqPacket, length, protocol);
197 
198  //Send PPP frame
199  error = pppSendFrame(context->interface, buffer, offset, protocol);
200 
201  //Free previously allocated memory block
202  netBufferFree(buffer);
203 
204  //Return status code
205  return error;
206 }
207 
208 
209 /**
210  * @brief Send Terminate-Ack packet
211  * @param[in] context PPP context
212  * @param[in] identifier Identifier field
213  * @param[in] protocol Protocol field
214  * @return Error code
215  **/
216 
219 {
220  error_t error;
221  size_t length;
222  size_t offset;
223  NetBuffer *buffer;
224  PppTerminatePacket *terminateAckPacket;
225 
226  //Length of the Terminate-Ack packet
227  length = sizeof(PppTerminatePacket);
228 
229  //Allocate a buffer memory to hold the Terminate-Ack packet
230  buffer = pppAllocBuffer(length, &offset);
231  //Failed to allocate memory?
232  if(buffer == NULL)
233  return ERROR_OUT_OF_MEMORY;
234 
235  //Point to the Terminate-Ack packet
236  terminateAckPacket = netBufferAt(buffer, offset, 0);
237 
238  //Format packet header
239  terminateAckPacket->code = PPP_CODE_TERMINATE_ACK;
240  terminateAckPacket->identifier = identifier;
241  terminateAckPacket->length = htons(length);
242 
243  //Debug message
244  TRACE_INFO("Sending Terminate-Ack packet (%" PRIuSIZE " bytes)...\r\n", length);
245  //Dump packet contents for debugging purpose
246  pppDumpPacket((PppPacket *) terminateAckPacket, length, protocol);
247 
248  //Send PPP frame
249  error = pppSendFrame(context->interface, buffer, offset, protocol);
250 
251  //Free previously allocated memory block
252  netBufferFree(buffer);
253 
254  //Return status code
255  return error;
256 }
257 
258 
259 /**
260  * @brief Send Code-Reject packet
261  * @param[in] context PPP context
262  * @param[in] packet Un-interpretable packet received from the peer
263  * @param[in] identifier Identifier field
264  * @param[in] protocol Protocol field
265  * @return Error code
266  **/
267 
268 error_t pppSendCodeRej(PppContext *context, const PppPacket *packet,
270 {
271  error_t error;
272  size_t length;
273  size_t offset;
274  NetBuffer *buffer;
275  PppCodeRejPacket *codeRejPacket;
276 
277  //Calculate the length of the Code-Reject packet
278  length = ntohs(packet->length) + sizeof(PppCodeRejPacket);
279 
280  //The rejected packet must be truncated to comply with
281  //the peer's established MRU
282  length = MIN(length, context->peerConfig.mru);
283 
284  //Allocate a buffer memory to hold the Code-Reject packet
285  buffer = pppAllocBuffer(sizeof(PppCodeRejPacket), &offset);
286  //Failed to allocate memory?
287  if(buffer == NULL)
288  return ERROR_OUT_OF_MEMORY;
289 
290  //Point to the Code-Reject packet
291  codeRejPacket = netBufferAt(buffer, offset, 0);
292 
293  //Format packet header
294  codeRejPacket->code = PPP_CODE_CODE_REJ;
295  codeRejPacket->identifier = identifier;
296  codeRejPacket->length = htons(length);
297 
298  //The Rejected-Packet field contains a copy of the packet which is being rejected
299  error = netBufferAppend(buffer, packet, length - sizeof(PppCodeRejPacket));
300 
301  //Check status code
302  if(!error)
303  {
304  //Debug message
305  TRACE_INFO("Sending Code-Reject packet (%" PRIuSIZE " bytes)...\r\n", length);
306 
307  //Send PPP frame
308  error = pppSendFrame(context->interface, buffer, offset, protocol);
309  }
310 
311  //Free previously allocated memory block
312  netBufferFree(buffer);
313 
314  //Return status code
315  return error;
316 }
317 
318 
319 /**
320  * @brief Send Protocol-Reject packet
321  * @param[in] context PPP context
322  * @param[in] identifier Identifier field
323  * @param[in] protocol Rejected protocol
324  * @param[in] information Rejected information
325  * @param[in] length Length of the rejected information
326  * @return Error code
327  **/
328 
330  uint16_t protocol, const uint8_t *information, size_t length)
331 {
332  error_t error;
333  size_t offset;
334  NetBuffer *buffer;
335  PppProtocolRejPacket *protocolRejPacket;
336 
337  //Calculate the length of the Protocol-Reject packet
338  length += sizeof(PppProtocolRejPacket);
339 
340  //The Rejected-Information must be truncated to comply with
341  //the peer's established MRU
342  length = MIN(length, context->peerConfig.mru);
343 
344  //Allocate a buffer memory to hold the Protocol-Reject packet
345  buffer = pppAllocBuffer(sizeof(PppProtocolRejPacket), &offset);
346  //Failed to allocate memory?
347  if(buffer == NULL)
348  return ERROR_OUT_OF_MEMORY;
349 
350  //Point to the Protocol-Reject packet
351  protocolRejPacket = netBufferAt(buffer, offset, 0);
352 
353  //Format packet header
354  protocolRejPacket->code = PPP_CODE_PROTOCOL_REJ;
355  protocolRejPacket->identifier = identifier;
356  protocolRejPacket->length = htons(length);
357  protocolRejPacket->rejectedProtocol = htons(protocol);
358 
359  //The Rejected-Information field contains a copy of the
360  //packet which is being rejected
361  error = netBufferAppend(buffer, information,
362  length - sizeof(PppProtocolRejPacket));
363 
364  //Check status code
365  if(!error)
366  {
367  //Debug message
368  TRACE_INFO("Sending Protocol-Reject packet (%" PRIuSIZE " bytes)...\r\n", length);
369 
370  //Send PPP frame
371  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);
372  }
373 
374  //Free previously allocated memory block
375  netBufferFree(buffer);
376 
377  //Return status code
378  return error;
379 }
380 
381 
382 /**
383  * @brief Send Echo-Reply packet
384  * @param[in] context PPP context
385  * @param[in] echoReqPacket Echo-Request packet received from the peer
386  * @param[in] protocol Protocol field
387  * @return Error code
388  **/
389 
391  const PppEchoPacket *echoReqPacket, PppProtocol protocol)
392 {
393  error_t error;
394  size_t length;
395  size_t offset;
396  NetBuffer *buffer;
397  PppEchoPacket *echoRepPacket;
398 
399  //Retrieve the length of the Echo-Request packet
400  length = ntohs(echoReqPacket->length);
401 
402  //Make sure the length is valid
403  if(length < sizeof(PppEchoPacket))
404  return ERROR_INVALID_LENGTH;
405  if(length > context->peerConfig.mru)
406  return ERROR_INVALID_LENGTH;
407 
408  //Allocate a buffer memory to hold the Echo-Reply packet
409  buffer = pppAllocBuffer(sizeof(PppEchoPacket), &offset);
410  //Failed to allocate memory?
411  if(buffer == NULL)
412  return ERROR_OUT_OF_MEMORY;
413 
414  //Point to the Echo-Reply packet
415  echoRepPacket = netBufferAt(buffer, offset, 0);
416 
417  //Format packet header
418  echoRepPacket->code = PPP_CODE_ECHO_REP;
419  echoRepPacket->identifier = echoReqPacket->identifier;
420  echoRepPacket->length = htons(length);
421  echoRepPacket->magicNumber = context->localConfig.magicNumber;
422 
423  //The data field of the Echo-Request packet is copied into the data
424  //field of the Echo-Reply packet
425  error = netBufferAppend(buffer, echoReqPacket->data, length - sizeof(PppEchoPacket));
426 
427  //Check status code
428  if(!error)
429  {
430  //Debug message
431  TRACE_INFO("Sending Echo-Reply packet (%" PRIuSIZE " bytes)...\r\n", length);
432 
433  //Send PPP frame
434  error = pppSendFrame(context->interface, buffer, offset, protocol);
435  }
436 
437  //Free previously allocated memory block
438  netBufferFree(buffer);
439 
440  //Return status code
441  return error;
442 }
443 
444 
445 /**
446  * @brief Add an option to a Configure packet
447  * @param[in,out] packet Pointer to the Configure packet
448  * @param[in] optionType Option type
449  * @param[in] optionValue Option value
450  * @param[in] optionLen Length of the option value
451  * @return Error code
452  **/
453 
454 error_t pppAddOption(PppConfigurePacket *packet, uint8_t optionType,
455  const void *optionValue, uint8_t optionLen)
456 {
457  PppOption *option;
458 
459  //Make sure the length is valid
460  if(optionLen > (UINT8_MAX - sizeof(PppOption)))
461  return ERROR_INVALID_LENGTH;
462 
463  //Point to the end of the Configure packet
464  option = (PppOption *) ((uint8_t *) packet + packet->length);
465 
466  //Write specified option at current location
467  option->type = optionType;
468  option->length = optionLen + sizeof(PppOption);
469  //Copy option data
470  osMemcpy(option->data, optionValue, optionLen);
471 
472  //Update the length of the Configure packet
473  packet->length += optionLen + sizeof(PppOption);
474 
475  //Successful processing
476  return NO_ERROR;
477 }
478 
479 #endif
#define htons(value)
Definition: cpu_endian.h:413
Data logging functions for debugging purpose (PPP)
@ PPP_CODE_CONFIGURE_REJ
Configure-Reject.
Definition: ppp.h:219
uint8_t code
Definition: coap_common.h:179
#define PppPacket
Definition: ppp.h:37
@ PPP_CODE_CONFIGURE_ACK
Configure-Ack.
Definition: ppp.h:217
error_t ipv6cpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse IPV6CP configuration option.
Definition: ipv6cp.c:918
uint8_t protocol
Definition: ipv4.h:326
PppProtocol
Protocol field values.
Definition: ppp.h:198
@ PPP_CODE_PROTOCOL_REJ
Protocol-Reject.
Definition: ppp.h:223
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
IPV6CP (PPP IPv6 Control Protocol)
error_t pppSendProtocolRej(PppContext *context, uint8_t identifier, uint16_t protocol, const uint8_t *information, size_t length)
Send Protocol-Reject packet.
Definition: ppp_misc.c:329
PppConfigurePacket
Definition: ppp.h:274
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1305
#define PppContext
Definition: ppp.h:38
error_t pppSendCodeRej(PppContext *context, const PppPacket *packet, uint8_t identifier, PppProtocol protocol)
Send Code-Reject packet.
Definition: ppp_misc.c:268
PppCodeRejPacket
Definition: ppp.h:300
IPCP (PPP Internet Protocol Control Protocol)
@ PPP_CODE_CODE_REJ
Code-Reject.
Definition: ppp.h:222
LCP (PPP Link Control Protocol)
error_t pppAddOption(PppConfigurePacket *packet, uint8_t optionType, const void *optionValue, uint8_t optionLen)
Add an option to a Configure packet.
Definition: ppp_misc.c:454
error_t lcpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse LCP configuration option.
Definition: lcp.c:1329
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
@ PPP_CODE_ECHO_REP
Echo-Reply.
Definition: ppp.h:225
error_t
Error codes.
Definition: error.h:43
PppCode
Code field values.
Definition: ppp.h:215
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ PPP_CODE_CONFIGURE_NAK
Configure-Nak.
Definition: ppp.h:218
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
@ PPP_PROTOCOL_IPV6CP
IPv6 Control Protocol.
Definition: ppp.h:202
#define MIN(a, b)
Definition: os_port.h:63
error_t pppSendTerminateAck(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Ack packet.
Definition: ppp_misc.c:217
@ PPP_CODE_TERMINATE_ACK
Terminate-Ack.
Definition: ppp.h:221
#define ntohs(value)
Definition: cpu_endian.h:421
error_t pppSendEchoRep(PppContext *context, const PppEchoPacket *echoReqPacket, PppProtocol protocol)
Send Echo-Reply packet.
Definition: ppp_misc.c:390
@ PPP_PROTOCOL_LCP
Link Control Protocol.
Definition: ppp.h:203
PppEchoPacket
Definition: ppp.h:328
@ PPP_PROTOCOL_IPCP
IP Control Protocol.
Definition: ppp.h:201
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1035
error_t ipcpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse IPCP configuration option.
Definition: ipcp.c:984
error_t pppDumpPacket(const PppPacket *packet, size_t length, PppProtocol protocol)
Dump LCP/NCP packet for debugging purpose.
Definition: ppp_debug.c:143
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:604
PPP miscellaneous functions.
error_t pppSendConfigureAckNak(PppContext *context, const PppConfigurePacket *configureReqPacket, PppProtocol protocol, PppCode code)
Send Configure-Ack, Nak or Reject packet.
Definition: ppp_misc.c:56
PppTerminatePacket
Definition: ppp.h:287
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:322
uint8_t identifier[]
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
error_t pppSendTerminateReq(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Request packet.
Definition: ppp_misc.c:167
PppOption
Definition: ppp.h:354
#define PRIuSIZE
TCP/IP stack core.
@ NO_ERROR
Success.
Definition: error.h:44
@ PPP_CODE_TERMINATE_REQ
Terminate-Request.
Definition: ppp.h:220
Debugging facilities.
PppProtocolRejPacket
Definition: ppp.h:314