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