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-2019 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 1.9.6
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);
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  //Return status code
154  return error;
155 }
156 
157 
158 /**
159  * @brief Send Terminate-Request packet
160  * @param[in] context PPP context
161  * @param[in] identifier Identifier field
162  * @param[in] protocol Protocol field
163  * @return Error code
164  **/
165 
168 {
169  error_t error;
170  size_t length;
171  size_t offset;
172  NetBuffer *buffer;
173  PppTerminatePacket *terminateReqPacket;
174 
175  //Length of the Terminate-Request packet
176  length = sizeof(PppTerminatePacket);
177 
178  //Allocate a buffer memory to hold the Terminate-Request packet
179  buffer = pppAllocBuffer(length, &offset);
180  //Failed to allocate memory?
181  if(buffer == NULL)
182  return ERROR_OUT_OF_MEMORY;
183 
184  //Point to the Terminate-Request packet
185  terminateReqPacket = netBufferAt(buffer, offset);
186 
187  //Format packet header
188  terminateReqPacket->code = PPP_CODE_TERMINATE_REQ;
189  terminateReqPacket->identifier = identifier;
190  terminateReqPacket->length = htons(length);
191 
192  //Debug message
193  TRACE_INFO("Sending Terminate-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
194  //Dump packet contents for debugging purpose
195  pppDumpPacket((PppPacket *) terminateReqPacket, length, protocol);
196 
197  //Send PPP frame
198  error = pppSendFrame(context->interface, buffer, offset, protocol);
199 
200  //Free previously allocated memory block
201  netBufferFree(buffer);
202  //Return status code
203  return error;
204 }
205 
206 
207 /**
208  * @brief Send Terminate-Ack packet
209  * @param[in] context PPP context
210  * @param[in] identifier Identifier field
211  * @param[in] protocol Protocol field
212  * @return Error code
213  **/
214 
217 {
218  error_t error;
219  size_t length;
220  size_t offset;
221  NetBuffer *buffer;
222  PppTerminatePacket *terminateAckPacket;
223 
224  //Length of the Terminate-Ack packet
225  length = sizeof(PppTerminatePacket);
226 
227  //Allocate a buffer memory to hold the Terminate-Ack packet
228  buffer = pppAllocBuffer(length, &offset);
229  //Failed to allocate memory?
230  if(buffer == NULL)
231  return ERROR_OUT_OF_MEMORY;
232 
233  //Point to the Terminate-Ack packet
234  terminateAckPacket = netBufferAt(buffer, offset);
235 
236  //Format packet header
237  terminateAckPacket->code = PPP_CODE_TERMINATE_ACK;
238  terminateAckPacket->identifier = identifier;
239  terminateAckPacket->length = htons(length);
240 
241  //Debug message
242  TRACE_INFO("Sending Terminate-Ack packet (%" PRIuSIZE " bytes)...\r\n", length);
243  //Dump packet contents for debugging purpose
244  pppDumpPacket((PppPacket *) terminateAckPacket, length, protocol);
245 
246  //Send PPP frame
247  error = pppSendFrame(context->interface, buffer, offset, protocol);
248 
249  //Free previously allocated memory block
250  netBufferFree(buffer);
251  //Return status code
252  return error;
253 }
254 
255 
256 /**
257  * @brief Send Code-Reject packet
258  * @param[in] context PPP context
259  * @param[in] packet Un-interpretable packet received from the peer
260  * @param[in] identifier Identifier field
261  * @param[in] protocol Protocol field
262  * @return Error code
263  **/
264 
265 error_t pppSendCodeRej(PppContext *context, const PppPacket *packet,
267 {
268  error_t error;
269  size_t length;
270  size_t offset;
271  NetBuffer *buffer;
272  PppCodeRejPacket *codeRejPacket;
273 
274  //Calculate the length of the Code-Reject packet
275  length = ntohs(packet->length) + sizeof(PppCodeRejPacket);
276 
277  //The rejected packet must be truncated to comply with
278  //the peer's established MRU
279  length = MIN(length, context->peerConfig.mru);
280 
281  //Allocate a buffer memory to hold the Code-Reject packet
282  buffer = pppAllocBuffer(sizeof(PppCodeRejPacket), &offset);
283  //Failed to allocate memory?
284  if(buffer == NULL)
285  return ERROR_OUT_OF_MEMORY;
286 
287  //Point to the Code-Reject packet
288  codeRejPacket = netBufferAt(buffer, offset);
289 
290  //Format packet header
291  codeRejPacket->code = PPP_CODE_CODE_REJ;
292  codeRejPacket->identifier = identifier;
293  codeRejPacket->length = htons(length);
294 
295  //The Rejected-Packet field contains a copy of the packet which is being rejected
296  error = netBufferAppend(buffer, packet, length - sizeof(PppCodeRejPacket));
297 
298  //Check status code
299  if(!error)
300  {
301  //Debug message
302  TRACE_INFO("Sending Code-Reject packet (%" PRIuSIZE " bytes)...\r\n", length);
303 
304  //Send PPP frame
305  error = pppSendFrame(context->interface, buffer, offset, protocol);
306  }
307 
308  //Free previously allocated memory block
309  netBufferFree(buffer);
310  //Return status code
311  return error;
312 }
313 
314 
315 /**
316  * @brief Send Protocol-Reject packet
317  * @param[in] context PPP context
318  * @param[in] identifier Identifier field
319  * @param[in] protocol Rejected protocol
320  * @param[in] information Rejected information
321  * @param[in] length Length of the rejected information
322  * @return Error code
323  **/
324 
326  uint16_t protocol, const uint8_t *information, size_t length)
327 {
328  error_t error;
329  size_t offset;
330  NetBuffer *buffer;
331  PppProtocolRejPacket *protocolRejPacket;
332 
333  //Calculate the length of the Protocol-Reject packet
334  length += sizeof(PppProtocolRejPacket);
335 
336  //The Rejected-Information must be truncated to comply with
337  //the peer's established MRU
338  length = MIN(length, context->peerConfig.mru);
339 
340  //Allocate a buffer memory to hold the Protocol-Reject packet
341  buffer = pppAllocBuffer(sizeof(PppProtocolRejPacket), &offset);
342  //Failed to allocate memory?
343  if(buffer == NULL)
344  return ERROR_OUT_OF_MEMORY;
345 
346  //Point to the Protocol-Reject packet
347  protocolRejPacket = netBufferAt(buffer, offset);
348 
349  //Format packet header
350  protocolRejPacket->code = PPP_CODE_PROTOCOL_REJ;
351  protocolRejPacket->identifier = identifier;
352  protocolRejPacket->length = htons(length);
353  protocolRejPacket->rejectedProtocol = htons(protocol);
354 
355  //The Rejected-Information field contains a copy of the
356  //packet which is being rejected
357  error = netBufferAppend(buffer, information,
358  length - sizeof(PppProtocolRejPacket));
359 
360  //Check status code
361  if(!error)
362  {
363  //Debug message
364  TRACE_INFO("Sending Protocol-Reject packet (%" PRIuSIZE " bytes)...\r\n", length);
365 
366  //Send PPP frame
367  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);
368  }
369 
370  //Free previously allocated memory block
371  netBufferFree(buffer);
372  //Return status code
373  return error;
374 }
375 
376 
377 /**
378  * @brief Send Echo-Reply packet
379  * @param[in] context PPP context
380  * @param[in] echoReqPacket Echo-Request packet received from the peer
381  * @param[in] protocol Protocol field
382  * @return Error code
383  **/
384 
386  const PppEchoPacket *echoReqPacket, PppProtocol protocol)
387 {
388  error_t error;
389  size_t length;
390  size_t offset;
391  NetBuffer *buffer;
392  PppEchoPacket *echoRepPacket;
393 
394  //Retrieve the length of the Echo-Request packet
395  length = ntohs(echoReqPacket->length);
396 
397  //Make sure the length is valid
398  if(length < sizeof(PppEchoPacket))
399  return ERROR_INVALID_LENGTH;
400  if(length > context->peerConfig.mru)
401  return ERROR_INVALID_LENGTH;
402 
403  //Allocate a buffer memory to hold the Echo-Reply packet
404  buffer = pppAllocBuffer(sizeof(PppEchoPacket), &offset);
405  //Failed to allocate memory?
406  if(buffer == NULL)
407  return ERROR_OUT_OF_MEMORY;
408 
409  //Point to the Echo-Reply packet
410  echoRepPacket = netBufferAt(buffer, offset);
411 
412  //Format packet header
413  echoRepPacket->code = PPP_CODE_ECHO_REP;
414  echoRepPacket->identifier = echoReqPacket->identifier;
415  echoRepPacket->length = htons(length);
416  echoRepPacket->magicNumber = context->localConfig.magicNumber;
417 
418  //The data field of the Echo-Request packet is copied into the data
419  //field of the Echo-Reply packet
420  error = netBufferAppend(buffer, echoReqPacket->data, length - sizeof(PppEchoPacket));
421 
422  //Check status code
423  if(!error)
424  {
425  //Debug message
426  TRACE_INFO("Sending Echo-Reply packet (%" PRIuSIZE " bytes)...\r\n", length);
427 
428  //Send PPP frame
429  error = pppSendFrame(context->interface, buffer, offset, protocol);
430  }
431 
432  //Free previously allocated memory block
433  netBufferFree(buffer);
434  //Return status code
435  return error;
436 }
437 
438 
439 /**
440  * @brief Add an option to a Configure packet
441  * @param[in,out] packet Pointer to the Configure packet
442  * @param[in] optionType Option type
443  * @param[in] optionValue Option value
444  * @param[in] optionLen Length of the option value
445  * @return Error code
446  **/
447 
448 error_t pppAddOption(PppConfigurePacket *packet, uint8_t optionType,
449  const void *optionValue, uint8_t optionLen)
450 {
451  PppOption *option;
452 
453  //Make sure the length is valid
454  if(optionLen > (UINT8_MAX - sizeof(PppOption)))
455  return ERROR_INVALID_LENGTH;
456 
457  //Point to the end of the Configure packet
458  option = (PppOption *) ((uint8_t *) packet + packet->length);
459 
460  //Write specified option at current location
461  option->type = optionType;
462  option->length = optionLen + sizeof(PppOption);
463  //Copy option data
464  memcpy(option->data, optionValue, optionLen);
465 
466  //Update the length of the Configure packet
467  packet->length += optionLen + sizeof(PppOption);
468 
469  //Successful processing
470  return NO_ERROR;
471 }
472 
473 #endif
#define htons(value)
Definition: cpu_endian.h:392
uint8_t length
Definition: dtls_misc.h:149
Data logging functions for debugging purpose (PPP)
@ PPP_CODE_CONFIGURE_REJ
Configure-Reject.
Definition: ppp.h:219
uint8_t code
Definition: coap_common.h:181
#define PppPacket
Definition: ppp.h:37
@ PPP_CODE_CONFIGURE_ACK
Configure-Ack.
Definition: ppp.h:217
__start_packed struct @286 PppTerminatePacket
Terminate-Request and Terminate-Ack packet.
error_t ipv6cpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse IPV6CP configuration option.
Definition: ipv6cp.c:929
PppProtocol
Protocol field values.
Definition: ppp.h:197
@ PPP_CODE_PROTOCOL_REJ
Protocol-Reject.
Definition: ppp.h:223
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
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:325
__start_packed struct @291 PppOption
LCP/NCP option.
@ 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:1265
__start_packed struct @289 PppEchoPacket
Echo-Request and Echo-Reply packet.
#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:265
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:448
error_t lcpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse LCP configuration option.
Definition: lcp.c:1320
@ PPP_CODE_ECHO_REP
Echo-Reply.
Definition: ppp.h:225
error_t
Error codes.
Definition: error.h:42
uint8_t protocol
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
uint8_t identifier[]
PppCode
Code field values.
Definition: ppp.h:214
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:109
@ PPP_CODE_CONFIGURE_NAK
Configure-Nak.
Definition: ppp.h:218
__start_packed struct @288 PppProtocolRejPacket
Protocol-Reject packet.
#define TRACE_INFO(...)
Definition: debug.h:94
@ PPP_PROTOCOL_IPV6CP
IPv6 Control Protocol.
Definition: ppp.h:202
#define MIN(a, b)
Definition: os_port.h:62
error_t pppSendTerminateAck(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Ack packet.
Definition: ppp_misc.c:215
@ PPP_CODE_TERMINATE_ACK
Terminate-Ack.
Definition: ppp.h:221
#define ntohs(value)
Definition: cpu_endian.h:398
error_t pppSendEchoRep(PppContext *context, const PppEchoPacket *echoReqPacket, PppProtocol protocol)
Send Echo-Reply packet.
Definition: ppp_misc.c:385
@ PPP_PROTOCOL_LCP
Link Control Protocol.
Definition: ppp.h:203
__start_packed struct @285 PppConfigurePacket
Configure-Request, Configure-Ack, Configure-Nak and Configure-Reject packets.
@ 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:1006
error_t ipcpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse IPCP configuration option.
Definition: ipcp.c:983
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:586
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
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:320
error_t pppSendTerminateReq(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Request packet.
Definition: ppp_misc.c:166
#define PRIuSIZE
Definition: compiler_port.h:78
TCP/IP stack core.
@ NO_ERROR
Success.
Definition: error.h:44
@ PPP_CODE_TERMINATE_REQ
Terminate-Request.
Definition: ppp.h:220
Debugging facilities.
__start_packed struct @287 PppCodeRejPacket
Code-Reject packet.