1/*********************************************************************
2   PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
3   See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
4
5   Authors: Serge Gadeyne, Daniele Lacamera, Maxime Vincent
6
7 *********************************************************************/
8
9
10#include <stdint.h>
11#include <stdlib.h>
12#include <string.h>
13#include <stdio.h>
14
15#include "pico_device.h"
16#include "pico_dev_ppp.h"
17#include "pico_stack.h"
18#include "pico_ipv4.h"
19#include "pico_md5.h"
20#include "pico_dns_client.h"
21
22#ifdef DEBUG_PPP
23    #define ppp_dbg dbg
24#else
25    #define ppp_dbg(...) do {} while(0)
26#endif
27
28/* We should define this in a global header. */
29#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
30
31#define PICO_PPP_MRU 1514 /* RFC default MRU */
32#define PICO_PPP_MTU 1500
33#define PPP_MAXPKT 2048
34#define PPP_MAX_APN 134
35#define PPP_MAX_USERNAME 134
36#define PPP_MAX_PASSWORD 134
37#define PPP_HDR_SIZE 3u
38#define PPP_PROTO_SLOT_SIZE 2u
39#define PPP_FCS_SIZE 2u
40#define PPP_PROTO_LCP short_be(0xc021)
41#define PPP_PROTO_IP  short_be(0x0021)
42#define PPP_PROTO_PAP short_be(0xc023)
43#define PPP_PROTO_CHAP short_be(0xc223)
44#define PPP_PROTO_IPCP short_be(0x8021)
45
46#define PICO_CONF_REQ 1
47#define PICO_CONF_ACK 2
48#define PICO_CONF_NAK 3
49#define PICO_CONF_REJ 4
50#define PICO_CONF_TERM      5
51#define PICO_CONF_TERM_ACK  6
52#define PICO_CONF_CODE_REJ  7
53#define PICO_CONF_PROTO_REJ 8
54#define PICO_CONF_ECHO_REQ  9
55#define PICO_CONF_ECHO_REP  10
56#define PICO_CONF_DISCARD_REQ 11
57
58#define LCPOPT_MRU          1u /* param size: 4, fixed: MRU     */
59#define LCPOPT_AUTH         3u /* param size: 4-5: AUTH proto   */
60#define LCPOPT_QUALITY      4u /* unused for now                */
61#define LCPOPT_MAGIC        5u /* param size: 6, fixed: Magic   */
62#define LCPOPT_PROTO_COMP   7u /* param size: 0, flag           */
63#define LCPOPT_ADDRCTL_COMP 8u /* param size: 0, flag           */
64
65#define CHAP_MD5_SIZE   16u
66#define CHAP_CHALLENGE  1
67#define CHAP_RESPONSE   2
68#define CHAP_SUCCESS    3
69#define CHAP_FAILURE    4
70#define CHALLENGE_SIZE(ppp, ch) ((size_t)((1 + strlen(ppp->password) + short_be((ch)->len))))
71
72#define PAP_AUTH_REQ 1
73#define PAP_AUTH_ACK 2
74#define PAP_AUTH_NAK 3
75
76
77#define PICO_PPP_DEFAULT_TIMER (3) /* seconds */
78#define PICO_PPP_DEFAULT_MAX_TERMINATE (2)
79#define PICO_PPP_DEFAULT_MAX_CONFIGURE (10)
80#define PICO_PPP_DEFAULT_MAX_FAILURE   (5)
81#define PICO_PPP_DEFAULT_MAX_DIALTIME  (20)
82
83#define IPCP_ADDR_LEN 6u
84#define IPCP_VJ_LEN 6u
85#define IPCP_OPT_IP 0x03
86#define IPCP_OPT_VJ 0x02
87#define IPCP_OPT_DNS1 0x81
88#define IPCP_OPT_NBNS1 0x82
89#define IPCP_OPT_DNS2 0x83
90#define IPCP_OPT_NBNS2 0x84
91
92static uint8_t LCPOPT_LEN[9] = {
93    0, 4, 0, 4, 4, 6, 2, 2, 2
94};
95
96
97/* Protocol defines */
98static const unsigned char AT_S3          = 0x0du;
99static const unsigned char AT_S4          = 0x0au;
100static const unsigned char PPPF_FLAG_SEQ  = 0x7eu;
101static const unsigned char PPPF_CTRL_ESC  = 0x7du;
102static const unsigned char PPPF_ADDR      = 0xffu;
103static const unsigned char PPPF_CTRL      = 0x03u;
104
105static int ppp_devnum = 0;
106static uint8_t ppp_recv_buf[PPP_MAXPKT];
107
108PACKED_STRUCT_DEF pico_lcp_hdr {
109    uint8_t code;
110    uint8_t id;
111    uint16_t len;
112};
113
114PACKED_STRUCT_DEF pico_chap_hdr {
115    uint8_t code;
116    uint8_t id;
117    uint16_t len;
118};
119
120PACKED_STRUCT_DEF pico_pap_hdr {
121    uint8_t code;
122    uint8_t id;
123    uint16_t len;
124};
125
126PACKED_STRUCT_DEF pico_ipcp_hdr {
127    uint8_t code;
128    uint8_t id;
129    uint16_t len;
130};
131
132enum ppp_modem_state {
133    PPP_MODEM_STATE_INITIAL = 0,
134    PPP_MODEM_STATE_RESET,
135    PPP_MODEM_STATE_ECHO,
136    PPP_MODEM_STATE_CREG,
137    PPP_MODEM_STATE_CGREG,
138    PPP_MODEM_STATE_CGDCONT,
139    PPP_MODEM_STATE_CGATT,
140    PPP_MODEM_STATE_DIAL,
141    PPP_MODEM_STATE_CONNECTED,
142    PPP_MODEM_STATE_MAX
143};
144
145enum ppp_modem_event {
146    PPP_MODEM_EVENT_START = 0,
147    PPP_MODEM_EVENT_STOP,
148    PPP_MODEM_EVENT_OK,
149    PPP_MODEM_EVENT_CONNECT,
150    PPP_MODEM_EVENT_TIMEOUT,
151    PPP_MODEM_EVENT_MAX
152};
153
154enum ppp_lcp_state {
155    PPP_LCP_STATE_INITIAL = 0,
156    PPP_LCP_STATE_STARTING,
157    PPP_LCP_STATE_CLOSED,
158    PPP_LCP_STATE_STOPPED,
159    PPP_LCP_STATE_CLOSING,
160    PPP_LCP_STATE_STOPPING,
161    PPP_LCP_STATE_REQ_SENT,
162    PPP_LCP_STATE_ACK_RCVD,
163    PPP_LCP_STATE_ACK_SENT,
164    PPP_LCP_STATE_OPENED,
165    PPP_LCP_STATE_MAX
166};
167
168enum ppp_lcp_event {
169    PPP_LCP_EVENT_UP = 0,
170    PPP_LCP_EVENT_DOWN,
171    PPP_LCP_EVENT_OPEN,
172    PPP_LCP_EVENT_CLOSE,
173    PPP_LCP_EVENT_TO_POS,
174    PPP_LCP_EVENT_TO_NEG,
175    PPP_LCP_EVENT_RCR_POS,
176    PPP_LCP_EVENT_RCR_NEG,
177    PPP_LCP_EVENT_RCA,
178    PPP_LCP_EVENT_RCN,
179    PPP_LCP_EVENT_RTR,
180    PPP_LCP_EVENT_RTA,
181    PPP_LCP_EVENT_RUC,
182    PPP_LCP_EVENT_RXJ_POS,
183    PPP_LCP_EVENT_RXJ_NEG,
184    PPP_LCP_EVENT_RXR,
185    PPP_LCP_EVENT_MAX
186};
187
188enum ppp_auth_state {
189    PPP_AUTH_STATE_INITIAL = 0,
190    PPP_AUTH_STATE_STARTING,
191    PPP_AUTH_STATE_RSP_SENT,
192    PPP_AUTH_STATE_REQ_SENT,
193    PPP_AUTH_STATE_AUTHENTICATED,
194    PPP_AUTH_STATE_MAX
195};
196
197enum ppp_auth_event {
198    PPP_AUTH_EVENT_UP_NONE = 0,
199    PPP_AUTH_EVENT_UP_PAP,
200    PPP_AUTH_EVENT_UP_CHAP,
201    PPP_AUTH_EVENT_DOWN,
202    PPP_AUTH_EVENT_RAC,
203    PPP_AUTH_EVENT_RAA,
204    PPP_AUTH_EVENT_RAN,
205    PPP_AUTH_EVENT_TO,
206    PPP_AUTH_EVENT_MAX
207};
208
209enum ppp_ipcp_state {
210    PPP_IPCP_STATE_INITIAL = 0,
211    PPP_IPCP_STATE_REQ_SENT,
212    PPP_IPCP_STATE_ACK_RCVD,
213    PPP_IPCP_STATE_ACK_SENT,
214    PPP_IPCP_STATE_OPENED,
215    PPP_IPCP_STATE_MAX
216};
217
218enum ppp_ipcp_event {
219    PPP_IPCP_EVENT_UP = 0,
220    PPP_IPCP_EVENT_DOWN,
221    PPP_IPCP_EVENT_RCR_POS,
222    PPP_IPCP_EVENT_RCR_NEG,
223    PPP_IPCP_EVENT_RCA,
224    PPP_IPCP_EVENT_RCN,
225    PPP_IPCP_EVENT_TO,
226    PPP_IPCP_EVENT_MAX
227};
228
229enum pico_ppp_state {
230    PPP_MODEM_RST = 0,
231    PPP_MODEM_CREG,
232    PPP_MODEM_CGREG,
233    PPP_MODEM_CGDCONT,
234    PPP_MODEM_CGATT,
235    PPP_MODEM_CONNECT,
236    /* From here on, PPP states */
237    PPP_ESTABLISH,
238    PPP_AUTH,
239    PPP_NETCONFIG,
240    PPP_NETWORK,
241    PPP_TERMINATE,
242    /* MAXSTATE is the last one */
243    PPP_MODEM_MAXSTATE
244};
245
246
247#define IPCP_ALLOW_IP 0x01u
248#define IPCP_ALLOW_DNS1 0x02u
249#define IPCP_ALLOW_DNS2 0x04u
250#define IPCP_ALLOW_NBNS1 0x08u
251#define IPCP_ALLOW_NBNS2 0x10u
252
253struct pico_device_ppp {
254    struct pico_device dev;
255    int autoreconnect;
256    enum ppp_modem_state modem_state;
257    enum ppp_lcp_state lcp_state;
258    enum ppp_auth_state auth_state;
259    enum ppp_ipcp_state ipcp_state;
260    enum pico_ppp_state state;
261    char apn[PPP_MAX_APN];
262    char password[PPP_MAX_PASSWORD];
263    char username[PPP_MAX_USERNAME];
264    uint16_t lcpopt_local;
265    uint16_t lcpopt_peer;
266    uint8_t *pkt;
267    uint32_t len;
268    uint16_t rej;
269    uint16_t auth;
270    int (*serial_recv)(struct pico_device *dev, void *buf, int len);
271    int (*serial_send)(struct pico_device *dev, const void *buf, int len);
272    int (*serial_set_speed)(struct pico_device *dev, uint32_t speed);
273    uint32_t ipcp_allowed_fields;
274    uint32_t ipcp_ip;
275    uint32_t ipcp_dns1;
276    uint32_t ipcp_nbns1;
277    uint32_t ipcp_dns2;
278    uint32_t ipcp_nbns2;
279    uint32_t timer;
280    uint8_t timer_val;
281    uint8_t timer_count;
282    uint8_t frame_id;
283    uint8_t timer_on;
284    uint16_t mru;
285};
286
287
288/* Unit test interceptor */
289static void (*mock_modem_state)(struct pico_device_ppp *ppp, enum ppp_modem_event event) = NULL;
290static void (*mock_lcp_state)(struct pico_device_ppp *ppp, enum ppp_lcp_event event) = NULL;
291static void (*mock_auth_state)(struct pico_device_ppp *ppp, enum ppp_auth_event event) = NULL;
292static void (*mock_ipcp_state)(struct pico_device_ppp *ppp, enum ppp_ipcp_event event) = NULL;
293
294/* Debug prints */
295#ifdef PPP_DEBUG
296static void lcp_optflags_print(struct pico_device_ppp *ppp, uint8_t *opts, uint32_t opts_len);
297#endif
298
299#define PPP_TIMER_ON_MODEM      0x01u
300#define PPP_TIMER_ON_LCPREQ     0x04u
301#define PPP_TIMER_ON_LCPTERM    0x08u
302#define PPP_TIMER_ON_AUTH       0x10u
303#define PPP_TIMER_ON_IPCP       0x20u
304
305/* Escape and send */
306static int ppp_serial_send_escape(struct pico_device_ppp *ppp, void *buf, int len)
307{
308    uint8_t *in_buf = (uint8_t *)buf;
309    uint8_t *out_buf = NULL;
310    int esc_char_count = 0;
311    int newlen = 0, ret = -1;
312    int i, j;
313
314#ifdef PPP_DEBUG
315    {
316        uint32_t idx;
317        if (len > 0) {
318            ppp_dbg("PPP >>>> ");
319            for(idx = 0; idx < (uint32_t)len; idx++) {
320                ppp_dbg(" %02x", ((uint8_t *)buf)[idx]);
321            }
322            ppp_dbg("\n");
323        }
324    }
325#endif
326
327    for (i = 1; i < (len - 1); i++) /* from 1 to len -1, as start/stop are not escaped */
328    {
329        if (((in_buf[i] + 1u) >> 1) == 0x3Fu)
330            esc_char_count++;
331    }
332    if (!esc_char_count) {
333        return ppp->serial_send(&ppp->dev, buf, len);
334    }
335
336    newlen = len + esc_char_count;
337    out_buf = PICO_ZALLOC((uint32_t)newlen);
338    if(!out_buf)
339        return -1;
340
341    /* Start byte. */
342    out_buf[0] = in_buf[0];
343    for(i = 1, j = 1; i < (len - 1); i++) {
344        if (((in_buf[i] + 1u) >> 1) == 0x3Fu) {
345            out_buf[j++] = PPPF_CTRL_ESC;
346            out_buf[j++] = in_buf[i] ^ 0x20;
347        } else {
348            out_buf[j++] = in_buf[i];
349        }
350    }
351    /* Stop byte. */
352    out_buf[newlen - 1] = in_buf[len - 1];
353
354    ret = ppp->serial_send(&ppp->dev, out_buf, newlen);
355
356    PICO_FREE(out_buf);
357
358    if (ret == newlen)
359        return len;
360
361    return ret;
362
363}
364
365static void lcp_timer_start(struct pico_device_ppp *ppp, uint8_t timer_type)
366{
367    uint8_t count = 0;
368    ppp->timer_on |= timer_type;
369
370    if (ppp->timer_val == 0) {
371        ppp->timer_val = PICO_PPP_DEFAULT_TIMER;
372    }
373
374    if (timer_type == PPP_TIMER_ON_LCPTERM) {
375        count = PICO_PPP_DEFAULT_MAX_TERMINATE;
376    }
377
378    if (timer_type == PPP_TIMER_ON_LCPREQ) {
379        count = PICO_PPP_DEFAULT_MAX_CONFIGURE;
380    }
381
382    if (timer_type == 0) {
383        ppp->timer_on |= PPP_TIMER_ON_LCPREQ;
384        ppp->timer_count = 0;
385    }
386
387    if (ppp->timer_count == 0)
388        ppp->timer_count = count;
389}
390
391static void lcp_zero_restart_count(struct pico_device_ppp *ppp)
392{
393    lcp_timer_start(ppp, 0);
394}
395
396static void lcp_timer_stop(struct pico_device_ppp *ppp, uint8_t timer_type)
397{
398    ppp->timer_on = (uint8_t)ppp->timer_on & (uint8_t)(~timer_type);
399}
400
401
402#define PPP_FSM_MAX_ACTIONS 3
403
404struct pico_ppp_fsm {
405    int next_state;
406    void (*event_handler[PPP_FSM_MAX_ACTIONS]) (struct pico_device_ppp *);
407};
408
409#define LCPOPT_SET_LOCAL(ppp, opt)          ppp->lcpopt_local |= (uint16_t)(1u << opt)
410#define LCPOPT_SET_PEER(ppp, opt)           ppp->lcpopt_peer  |= (uint16_t)(1u << opt)
411#define LCPOPT_UNSET_LOCAL(ppp, opt)        ppp->lcpopt_local &= (uint16_t) ~(1u << opt)
412#define LCPOPT_UNSET_LOCAL_MASK(ppp, opt)   ppp->lcpopt_local &= (uint16_t) ~(opt)
413#define LCPOPT_UNSET_PEER(ppp, opt)         ppp->lcpopt_peer  &= (uint16_t) ~(1u << opt)
414#define LCPOPT_ISSET_LOCAL(ppp, opt)      ((ppp->lcpopt_local & (uint16_t)(1u << opt)) != 0)
415#define LCPOPT_ISSET_PEER(ppp, opt)       ((ppp->lcpopt_peer  & (uint16_t)(1u << opt)) != 0)
416
417static void evaluate_modem_state(struct pico_device_ppp *ppp, enum ppp_modem_event event);
418static void evaluate_lcp_state(struct pico_device_ppp *ppp, enum ppp_lcp_event event);
419static void evaluate_auth_state(struct pico_device_ppp *ppp, enum ppp_auth_event event);
420static void evaluate_ipcp_state(struct pico_device_ppp *ppp, enum ppp_ipcp_event event);
421
422
423static uint32_t ppp_ctl_packet_size(struct pico_device_ppp *ppp, uint16_t proto, uint32_t *size)
424{
425    uint32_t prefix = 0;
426
427    IGNORE_PARAMETER(ppp);
428    IGNORE_PARAMETER(proto);
429
430    prefix += PPP_HDR_SIZE; /* 7e ff 03 ... */
431    prefix += PPP_PROTO_SLOT_SIZE;
432    *size  += prefix;
433    *size  += PPP_FCS_SIZE;
434    (*size)++; /* STOP byte 0x7e */
435    return prefix;
436}
437
438/* CRC16 / FCS Calculation */
439static uint16_t ppp_fcs_char(uint16_t old_crc, uint8_t data)
440{
441    uint16_t word = (old_crc ^ data) & (uint16_t)0x00FFu;
442    word = (uint16_t)(word ^ (uint16_t)((word << 4u) & (uint16_t)0x00FFu));
443    word = (uint16_t)((word << 8u) ^ (word << 3u) ^ (word >> 4u));
444    return ((old_crc >> 8u) ^ word);
445}
446
447static uint16_t ppp_fcs_continue(uint16_t fcs, uint8_t *buf, uint32_t len)
448{
449    uint8_t *pos = buf;
450    for (pos = buf; pos < buf + len; pos++)
451    {
452        fcs = ppp_fcs_char(fcs, *pos);
453    }
454    return fcs;
455}
456
457static uint16_t ppp_fcs_finish(uint16_t fcs)
458{
459    return fcs ^ 0xFFFF;
460}
461
462static uint16_t ppp_fcs_start(uint8_t *buf, uint32_t len)
463{
464    uint16_t fcs = 0xFFFF;
465    return ppp_fcs_continue(fcs, buf, len);
466}
467
468static int ppp_fcs_verify(uint8_t *buf, uint32_t len)
469{
470    uint16_t fcs = ppp_fcs_start(buf, len - 2);
471    fcs = ppp_fcs_finish(fcs);
472    if ((((fcs & 0xFF00u) >> 8) != buf[len - 1]) || ((fcs & 0xFFu) != buf[len - 2])) {
473        return -1;
474    }
475
476    return 0;
477}
478
479/* Serial send (DTE->DCE) functions */
480static int pico_ppp_ctl_send(struct pico_device *dev, uint16_t code, uint8_t *pkt, uint32_t len)
481{
482    struct pico_device_ppp *ppp = (struct pico_device_ppp *) dev;
483    uint16_t fcs;
484    uint8_t *ptr = pkt;
485    int i = 0;
486
487    if (!ppp->serial_send)
488        return (int)len;
489
490    /* PPP Header */
491    ptr[i++] = PPPF_FLAG_SEQ;
492    ptr[i++] = PPPF_ADDR;
493    ptr[i++] = PPPF_CTRL;
494    /* protocol */
495    ptr[i++] = (uint8_t)(code & 0xFFu);
496    ptr[i++] = (uint8_t)((code & 0xFF00u) >> 8);
497
498    /* payload is already in place. Calculate FCS. */
499    fcs = ppp_fcs_start(pkt + 1, len - 4); /* FCS excludes: start (1), FCS(2), stop(1), total 4 bytes */
500    fcs = ppp_fcs_finish(fcs);
501    pkt[len - 3] = (uint8_t)(fcs & 0xFFu);
502    pkt[len - 2] = (uint8_t)((fcs & 0xFF00u) >> 8);
503    pkt[len - 1] = PPPF_FLAG_SEQ;
504    ppp_serial_send_escape(ppp, pkt, (int)len);
505    return (int)len;
506}
507
508static uint8_t pico_ppp_data_buffer[PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + PICO_PPP_MTU + PPP_FCS_SIZE + 1];
509static int pico_ppp_send(struct pico_device *dev, void *buf, int len)
510{
511    struct pico_device_ppp *ppp = (struct pico_device_ppp *) dev;
512    uint16_t fcs = 0;
513    int fcs_start;
514    int i = 0;
515
516    ppp_dbg(" >>>>>>>>> PPP OUT\n");
517
518    if (ppp->ipcp_state != PPP_IPCP_STATE_OPENED)
519        return len;
520
521    if (!ppp->serial_send)
522        return len;
523
524    pico_ppp_data_buffer[i++] = PPPF_FLAG_SEQ;
525    if (!LCPOPT_ISSET_PEER(ppp, LCPOPT_ADDRCTL_COMP))
526    {
527        pico_ppp_data_buffer[i++] = PPPF_ADDR;
528        pico_ppp_data_buffer[i++] = PPPF_CTRL;
529    }
530
531    fcs_start = i;
532
533    if (!LCPOPT_ISSET_PEER(ppp, LCPOPT_PROTO_COMP))
534    {
535        pico_ppp_data_buffer[i++] = 0x00;
536    }
537
538    pico_ppp_data_buffer[i++] = 0x21;
539    memcpy(pico_ppp_data_buffer + i, buf, (uint32_t)len);
540    i += len;
541    fcs = ppp_fcs_start(pico_ppp_data_buffer + fcs_start, (uint32_t)(i - fcs_start));
542    fcs = ppp_fcs_finish(fcs);
543    pico_ppp_data_buffer[i++] = (uint8_t)(fcs & 0xFFu);
544    pico_ppp_data_buffer[i++] = (uint8_t)((fcs & 0xFF00u) >> 8);
545    pico_ppp_data_buffer[i++] = PPPF_FLAG_SEQ;
546
547    ppp_serial_send_escape(ppp, pico_ppp_data_buffer, i);
548    return len;
549}
550
551
552/* FSM functions */
553
554static void ppp_modem_start_timer(struct pico_device_ppp *ppp)
555{
556    ppp->timer_on = ppp->timer_on | PPP_TIMER_ON_MODEM;
557    ppp->timer_val = PICO_PPP_DEFAULT_TIMER;
558}
559
560#define PPP_AT_CREG0 "ATZ\r\n"
561static void ppp_modem_send_reset(struct pico_device_ppp *ppp)
562{
563    if (ppp->serial_send)
564        ppp->serial_send(&ppp->dev, PPP_AT_CREG0, strlen(PPP_AT_CREG0));
565
566    ppp_modem_start_timer(ppp);
567}
568
569#define PPP_AT_CREG1 "ATE0\r\n"
570static void ppp_modem_send_echo(struct pico_device_ppp *ppp)
571{
572    if (ppp->serial_send)
573        ppp->serial_send(&ppp->dev, PPP_AT_CREG1, strlen(PPP_AT_CREG1));
574
575    ppp_modem_start_timer(ppp);
576}
577
578#define PPP_AT_CREG2 "AT+CREG=1\r\n"
579static void ppp_modem_send_creg(struct pico_device_ppp *ppp)
580{
581    if (ppp->serial_send)
582        ppp->serial_send(&ppp->dev, PPP_AT_CREG2, strlen(PPP_AT_CREG2));
583
584    ppp_modem_start_timer(ppp);
585}
586
587#define PPP_AT_CGREG "AT+CGREG=1\r\n"
588static void ppp_modem_send_cgreg(struct pico_device_ppp *ppp)
589{
590    if (ppp->serial_send)
591        ppp->serial_send(&ppp->dev, PPP_AT_CGREG, strlen(PPP_AT_CGREG));
592
593    ppp_modem_start_timer(ppp);
594}
595
596
597#define PPP_AT_CGDCONT "AT+CGDCONT=1,\"IP\",\"%s\",,,\r\n"
598static void ppp_modem_send_cgdcont(struct pico_device_ppp *ppp)
599{
600    char at_cgdcont[200];
601
602    if (ppp->serial_send) {
603        snprintf(at_cgdcont, 200, PPP_AT_CGDCONT, ppp->apn);
604        ppp->serial_send(&ppp->dev, at_cgdcont, (int)strlen(at_cgdcont));
605    }
606
607    ppp_modem_start_timer(ppp);
608}
609
610
611#define PPP_AT_CGATT "AT+CGATT=1\r\n"
612static void ppp_modem_send_cgatt(struct pico_device_ppp *ppp)
613{
614    if (ppp->serial_send)
615        ppp->serial_send(&ppp->dev, PPP_AT_CGATT, strlen(PPP_AT_CGATT));
616
617    ppp_modem_start_timer(ppp);
618}
619
620#ifdef PICOTCP_PPP_SUPPORT_QUERIES
621#define PPP_AT_CGATT_Q "AT+CGATT?\r\n"
622static void ppp_modem_send_cgatt_q(struct pico_device_ppp *ppp)
623{
624    if (ppp->serial_send)
625        ppp->serial_send(&ppp->dev, PPP_AT_CGATT_Q, strlen(PPP_AT_CGATT_Q));
626
627    ppp_modem_start_timer(ppp);
628}
629#define PPP_AT_CGDCONT_Q "AT+CGDCONT?\r\n"
630static void ppp_modem_send_cgdcont_q(struct pico_device_ppp *ppp)
631{
632    if (ppp->serial_send)
633        ppp->serial_send(&ppp->dev, PPP_AT_CGDCONT_Q, strlen(PPP_AT_CGDCONT_Q));
634
635    ppp_modem_start_timer(ppp);
636}
637
638#define PPP_AT_CGREG_Q "AT+CGREG?\r\n"
639static void ppp_modem_send_cgreg_q(struct pico_device_ppp *ppp)
640{
641    if (ppp->serial_send)
642        ppp->serial_send(&ppp->dev, PPP_AT_CGREG_Q, strlen(PPP_AT_CGREG_Q));
643
644    ppp_modem_start_timer(ppp);
645}
646
647#define PPP_AT_CREG3 "AT+CREG?\r\n"
648static void ppp_modem_send_creg_q(struct pico_device_ppp *ppp)
649{
650    if (ppp->serial_send)
651        ppp->serial_send(&ppp->dev, PPP_AT_CREG3, strlen(PPP_AT_CREG3));
652
653    ppp_modem_start_timer(ppp);
654}
655#endif /* PICOTCP_PPP_SUPPORT_QUERIES */
656
657#define PPP_AT_DIALIN "ATD*99***1#\r\n"
658static void ppp_modem_send_dial(struct pico_device_ppp *ppp)
659{
660    if (ppp->serial_send)
661        ppp->serial_send(&ppp->dev, PPP_AT_DIALIN, strlen(PPP_AT_DIALIN));
662
663    ppp_modem_start_timer(ppp);
664    ppp->timer_val = PICO_PPP_DEFAULT_MAX_DIALTIME;
665}
666
667static void ppp_modem_connected(struct pico_device_ppp *ppp)
668{
669    ppp_dbg("PPP: Modem connected to peer.\n");
670    evaluate_lcp_state(ppp, PPP_LCP_EVENT_UP);
671}
672
673#define PPP_ATH "+++ATH\r\n"
674static void ppp_modem_disconnected(struct pico_device_ppp *ppp)
675{
676    ppp_dbg("PPP: Modem disconnected.\n");
677    if (ppp->serial_send)
678        ppp->serial_send(&ppp->dev, PPP_ATH, strlen(PPP_ATH));
679
680    evaluate_lcp_state(ppp, PPP_LCP_EVENT_DOWN);
681}
682
683static const struct pico_ppp_fsm ppp_modem_fsm[PPP_MODEM_STATE_MAX][PPP_MODEM_EVENT_MAX] = {
684    [PPP_MODEM_STATE_INITIAL] = {
685        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} },
686        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
687        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_INITIAL, {} },
688        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_INITIAL, {} },
689        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_INITIAL, {ppp_modem_send_reset} }
690    },
691    [PPP_MODEM_STATE_RESET] = {
692        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_RESET, {} },
693        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
694        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_ECHO, { ppp_modem_send_echo } },
695        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_RESET, {} },
696        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
697    },
698    [PPP_MODEM_STATE_ECHO] = {
699        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_ECHO, {} },
700        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
701        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_CREG, { ppp_modem_send_creg } },
702        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_ECHO, {} },
703        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
704    },
705    [PPP_MODEM_STATE_CREG] = {
706        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_CREG, {} },
707        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
708        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_CGREG, { ppp_modem_send_cgreg } },
709        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_CREG, {} },
710        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
711    },
712    [PPP_MODEM_STATE_CGREG] = {
713        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_CGREG, {} },
714        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
715        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_CGDCONT, { ppp_modem_send_cgdcont } },
716        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_CGREG, {} },
717        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
718    },
719    [PPP_MODEM_STATE_CGDCONT] = {
720        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_CGDCONT, {} },
721        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
722        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_CGATT, { ppp_modem_send_cgatt } },
723        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_CGDCONT, {} },
724        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
725    },
726    [PPP_MODEM_STATE_CGATT] = {
727        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_CGATT, {} },
728        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
729        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_DIAL, { ppp_modem_send_dial } },
730        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_CGATT, {} },
731        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
732    },
733    [PPP_MODEM_STATE_DIAL] = {
734        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_DIAL, {} },
735        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, {} },
736        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_DIAL, {} },
737        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_CONNECTED, { ppp_modem_connected } },
738        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_RESET, {ppp_modem_send_reset} }
739    },
740    [PPP_MODEM_STATE_CONNECTED] = {
741        [PPP_MODEM_EVENT_START]   = { PPP_MODEM_STATE_CONNECTED, {} },
742        [PPP_MODEM_EVENT_STOP]    = { PPP_MODEM_STATE_INITIAL, { ppp_modem_disconnected } },
743        [PPP_MODEM_EVENT_OK]      = { PPP_MODEM_STATE_CONNECTED, {} },
744        [PPP_MODEM_EVENT_CONNECT] = { PPP_MODEM_STATE_CONNECTED, {} },
745        [PPP_MODEM_EVENT_TIMEOUT] = { PPP_MODEM_STATE_CONNECTED, {} }
746    }
747};
748static void evaluate_modem_state(struct pico_device_ppp *ppp, enum ppp_modem_event event)
749{
750    const struct pico_ppp_fsm *fsm;
751    int i;
752    if (mock_modem_state) {
753        mock_modem_state(ppp, event);
754        return;
755    }
756
757    fsm = &ppp_modem_fsm[ppp->modem_state][event];
758
759    ppp->modem_state = (enum ppp_modem_state)fsm->next_state;
760
761    for (i = 0; i < PPP_FSM_MAX_ACTIONS; i++) {
762        if (fsm->event_handler[i])
763            fsm->event_handler[i](ppp);
764    }
765}
766
767static void ppp_modem_recv(struct pico_device_ppp *ppp, void *data, uint32_t len)
768{
769    IGNORE_PARAMETER(len);
770
771    ppp_dbg("PPP: Recv: '%s'\n", (char *)data);
772
773    if (strcmp(data, "OK") == 0) {
774        evaluate_modem_state(ppp, PPP_MODEM_EVENT_OK);
775    }
776
777    if (strcmp(data, "ERROR") == 0) {
778        evaluate_modem_state(ppp, PPP_MODEM_EVENT_STOP);
779    }
780
781    if (strncmp(data, "CONNECT", 7) == 0) {
782        evaluate_modem_state(ppp, PPP_MODEM_EVENT_CONNECT);
783    }
784}
785
786static void lcp_send_configure_request(struct pico_device_ppp *ppp)
787{
788#   define MY_LCP_REQ_SIZE 12 /* Max value. */
789    struct pico_lcp_hdr *req;
790    uint8_t *lcpbuf, *opts;
791    uint32_t size = MY_LCP_REQ_SIZE;
792    uint32_t prefix;
793    uint32_t optsize = 0;
794
795    prefix = ppp_ctl_packet_size(ppp, PPP_PROTO_LCP, &size);
796    lcpbuf = PICO_ZALLOC(size);
797    if (!lcpbuf)
798        return;
799
800    req = (struct pico_lcp_hdr *)(lcpbuf + prefix);
801
802    opts = lcpbuf + prefix + (sizeof(struct pico_lcp_hdr));
803    /* uint8_t my_pkt[] = { 0x7e, 0xff, 0x03, 0xc0, 0x21, 0x01, 0x00, 0x00, 0x06, 0x07, 0x02, 0x64, 0x7b, 0x7e }; */
804
805    ppp_dbg("Sending LCP CONF REQ\n");
806    req->code = PICO_CONF_REQ;
807    req->id = ppp->frame_id++;
808
809    if (LCPOPT_ISSET_LOCAL(ppp, LCPOPT_PROTO_COMP)) {
810        opts[optsize++] = LCPOPT_PROTO_COMP;
811        opts[optsize++] = LCPOPT_LEN[LCPOPT_PROTO_COMP];
812    }
813
814    if (LCPOPT_ISSET_LOCAL(ppp, LCPOPT_MRU)) {
815        opts[optsize++] = LCPOPT_MRU;
816        opts[optsize++] = LCPOPT_LEN[LCPOPT_MRU];
817        opts[optsize++] = (uint8_t)((ppp->mru >> 8) & 0xFF);
818        opts[optsize++] = (uint8_t)(ppp->mru & 0xFF);
819    } else {
820        ppp->mru = PICO_PPP_MRU;
821    }
822
823    if (LCPOPT_ISSET_LOCAL(ppp, LCPOPT_ADDRCTL_COMP)) {
824        opts[optsize++] = LCPOPT_ADDRCTL_COMP;
825        opts[optsize++] = LCPOPT_LEN[LCPOPT_ADDRCTL_COMP];
826    }
827
828    req->len = short_be((uint16_t)((unsigned long)optsize + sizeof(struct pico_lcp_hdr)));
829
830#ifdef PPP_DEBUG
831    lcp_optflags_print(ppp, opts, optsize);
832#endif
833
834    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_LCP,
835                      lcpbuf,               /* Start of PPP packet */
836                      (uint32_t)(prefix +              /* PPP Header, etc. */
837                                 sizeof(struct pico_lcp_hdr) + /* LCP HDR */
838                                 optsize +  /* Actual options size */
839                                 PPP_FCS_SIZE + /* FCS at the end of the frame */
840                                 1u)          /* STOP Byte */
841                      );
842    PICO_FREE(lcpbuf);
843    ppp->timer_val = PICO_PPP_DEFAULT_TIMER;
844    lcp_timer_start(ppp, PPP_TIMER_ON_LCPREQ);
845}
846
847#ifdef PPP_DEBUG
848static void lcp_optflags_print(struct pico_device_ppp *ppp, uint8_t *opts, uint32_t opts_len)
849{
850    uint8_t *p = opts;
851    int off;
852    IGNORE_PARAMETER(ppp);
853    ppp_dbg("Parsing options:\n");
854    while(p < (opts + opts_len)) {
855        int i;
856
857        ppp_dbg("-- LCP opt: %d - len: %d - data:", p[0], p[1]);
858        for (i = 0; i < p[1] - 2; i++)
859        {
860            ppp_dbg(" %02X", p[2 + i]);
861        }
862        ppp_dbg("\n");
863
864        off = p[1];
865        if (!off)
866            break;
867
868        p += off;
869    }
870}
871#endif
872
873/* setting adjust_opts will adjust our options to the ones supplied */
874static uint16_t lcp_optflags(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len, int adjust_opts)
875{
876    uint16_t flags = 0;
877    uint8_t *p = pkt +  sizeof(struct pico_lcp_hdr);
878    int off;
879    while(p < (pkt + len)) {
880        flags = (uint16_t)((uint16_t)(1u << (uint16_t)p[0]) | flags);
881
882        if (adjust_opts && ppp)
883        {
884            switch (p[0])
885            {
886            case LCPOPT_MRU:
887                /* XXX: Can we accept any MRU ? */
888                ppp_dbg("Adjusting MRU to %02x%02x\n", p[2], p[3]);
889                ppp->mru = (uint16_t)((p[2] << 8) + p[3]);
890                break;
891            case LCPOPT_AUTH:
892                ppp_dbg("Setting AUTH to %02x%02x\n", p[2], p[3]);
893                ppp->auth = (uint16_t)((p[2] << 8) + p[3]);
894                break;
895            default:
896                break;
897            }
898        }
899
900        off = p[1]; /* opt length field */
901        if (!off)
902            break;
903
904        p += off;
905    }
906#ifdef PPP_DEBUG
907    lcp_optflags_print(ppp, pkt +  sizeof(struct pico_lcp_hdr), (uint32_t)(len - sizeof(struct pico_lcp_hdr)));
908#endif
909    return flags;
910}
911
912
913static void lcp_send_configure_ack(struct pico_device_ppp *ppp)
914{
915    uint8_t ack[ppp->len + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_lcp_hdr) + PPP_FCS_SIZE + 1];
916    struct pico_lcp_hdr *ack_hdr = (struct pico_lcp_hdr *) (ack + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
917    struct pico_lcp_hdr *lcpreq = (struct pico_lcp_hdr *)ppp->pkt;
918    memcpy(ack + PPP_HDR_SIZE +  PPP_PROTO_SLOT_SIZE, ppp->pkt, ppp->len);
919    ack_hdr->code = PICO_CONF_ACK;
920    ack_hdr->id = lcpreq->id;
921    ack_hdr->len = lcpreq->len;
922    ppp_dbg("Sending LCP CONF ACK\n");
923    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_LCP, ack,
924                      PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE +  /* PPP Header, etc. */
925                      short_be(lcpreq->len) +               /* Actual options size + hdr (whole lcp packet) */
926                      PPP_FCS_SIZE +                        /* FCS at the end of the frame */
927                      1                                     /* STOP Byte */
928                      );
929}
930
931static void lcp_send_terminate_request(struct pico_device_ppp *ppp)
932{
933    uint8_t term[PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_lcp_hdr) + PPP_FCS_SIZE + 1];
934    struct pico_lcp_hdr *term_hdr = (struct pico_lcp_hdr *) (term + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
935    term_hdr->code = PICO_CONF_TERM;
936    term_hdr->id = ppp->frame_id++;
937    term_hdr->len = short_be((uint16_t)sizeof(struct pico_lcp_hdr));
938    ppp_dbg("Sending LCP TERMINATE REQUEST\n");
939    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_LCP, term,
940                      PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE +  /* PPP Header, etc. */
941                      sizeof(struct pico_lcp_hdr) +         /* Actual options size + hdr (whole lcp packet) */
942                      PPP_FCS_SIZE +                        /* FCS at the end of the frame */
943                      1                                     /* STOP Byte */
944                      );
945    lcp_timer_start(ppp, PPP_TIMER_ON_LCPTERM);
946}
947
948static void lcp_send_terminate_ack(struct pico_device_ppp *ppp)
949{
950    uint8_t ack[ppp->len + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_lcp_hdr) + PPP_FCS_SIZE + 1];
951    struct pico_lcp_hdr *ack_hdr = (struct pico_lcp_hdr *) (ack + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
952    struct pico_lcp_hdr *lcpreq = (struct pico_lcp_hdr *)ppp->pkt;
953    memcpy(ack + PPP_HDR_SIZE +  PPP_PROTO_SLOT_SIZE, ppp->pkt, ppp->len);
954    ack_hdr->code = PICO_CONF_TERM_ACK;
955    ack_hdr->id = lcpreq->id;
956    ack_hdr->len = lcpreq->len;
957    ppp_dbg("Sending LCP TERM ACK\n");
958    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_LCP, ack,
959                      PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE +  /* PPP Header, etc. */
960                      short_be(lcpreq->len) +               /* Actual options size + hdr (whole lcp packet) */
961                      PPP_FCS_SIZE +                        /* FCS at the end of the frame */
962                      1                                     /* STOP Byte */
963                      );
964}
965
966static void lcp_send_configure_nack(struct pico_device_ppp *ppp)
967{
968    uint8_t reject[64];
969    uint8_t *p = ppp->pkt +  sizeof(struct pico_lcp_hdr);
970    struct pico_lcp_hdr *lcpreq = (struct pico_lcp_hdr *)ppp->pkt;
971    struct pico_lcp_hdr *lcprej = (struct pico_lcp_hdr *)(reject + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
972    uint8_t *dst_opts = reject + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_lcp_hdr);
973    uint32_t dstopts_len = 0;
974    ppp_dbg("CONF_NACK: rej = %04X\n", ppp->rej);
975    while (p < (ppp->pkt + ppp->len)) {
976        uint8_t i = 0;
977        if ((1u << p[0]) & ppp->rej || (p[0] > 8u)) {       /* Reject anything we dont support or with option id >8 */
978            ppp_dbg("rejecting option %d -- ", p[0]);
979            dst_opts[dstopts_len++] = p[0];
980
981            ppp_dbg("len: %d -- ", p[1]);
982            dst_opts[dstopts_len++] = p[1];
983
984            ppp_dbg("data: ");
985            for(i = 0; i < p[1] - 2u; i++) {                   /* length includes type, length and data fields */
986                dst_opts[dstopts_len++] = p[2 + i];
987                ppp_dbg("%02X ", p[2 + i]);
988            }
989            ppp_dbg("\n");
990        }
991
992        p += p[1];
993    }
994    lcprej->code = PICO_CONF_REJ;
995    lcprej->id = lcpreq->id;
996    lcprej->len = short_be((uint16_t)(dstopts_len + sizeof(struct pico_lcp_hdr)));
997
998    ppp_dbg("Sending LCP CONF REJ\n");
999#ifdef PPP_DEBUG
1000    lcp_optflags_print(ppp, dst_opts, dstopts_len);
1001#endif
1002
1003    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_LCP, reject,
1004                      (uint32_t)(PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE +  /* PPP Header, etc. */
1005                                 sizeof(struct pico_lcp_hdr) + /* LCP HDR */
1006                                 dstopts_len +              /* Actual options size */
1007                                 PPP_FCS_SIZE +             /* FCS at the end of the frame */
1008                                 1u)                          /* STOP Byte */
1009                      );
1010}
1011
1012static void lcp_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1013{
1014    uint16_t optflags;
1015    if (!ppp)
1016        return;
1017
1018    if (pkt[0] == PICO_CONF_REQ) {
1019        uint16_t rejected = 0;
1020        ppp_dbg("Received LCP CONF REQ\n");
1021        optflags = lcp_optflags(ppp, pkt, len, 1u);
1022        rejected = (uint16_t)(optflags & (~ppp->lcpopt_local));
1023        ppp->pkt = pkt;
1024        ppp->len = len;
1025        ppp->rej = rejected;
1026        if (rejected) {
1027            evaluate_lcp_state(ppp, PPP_LCP_EVENT_RCR_NEG);
1028        } else {
1029            ppp->lcpopt_peer = optflags;
1030            evaluate_lcp_state(ppp, PPP_LCP_EVENT_RCR_POS);
1031        }
1032
1033        return;
1034    }
1035
1036    if (pkt[0] == PICO_CONF_ACK) {
1037        ppp_dbg("Received LCP CONF ACK\nOptflags: %04x\n", lcp_optflags(NULL, pkt, len, 0u));
1038        evaluate_lcp_state(ppp, PPP_LCP_EVENT_RCA);
1039        return;
1040    }
1041
1042    if (pkt[0] == PICO_CONF_NAK) {
1043        /* Every instance of the received Configuration Options is recognizable, but some values are not acceptable */
1044        optflags = lcp_optflags(ppp, pkt, len, 1u); /* We want our options adjusted */
1045        ppp_dbg("Received LCP CONF NAK - changed optflags: %04X\n", optflags);
1046        evaluate_lcp_state(ppp, PPP_LCP_EVENT_RCN);
1047        return;
1048    }
1049
1050    if (pkt[0] == PICO_CONF_REJ) {
1051        /* Some Configuration Options received in a Configure-Request are not recognizable or are not acceptable for negotiation */
1052        optflags = lcp_optflags(ppp, pkt, len, 0u);
1053        ppp_dbg("Received LCP CONF REJ - will disable optflags: %04X\n", optflags);
1054        /* Disable the options that are not supported by the peer */
1055        LCPOPT_UNSET_LOCAL_MASK(ppp, optflags);
1056        evaluate_lcp_state(ppp, PPP_LCP_EVENT_RCN);
1057        return;
1058    }
1059
1060    if (pkt[0] == PICO_CONF_ECHO_REQ) {
1061        ppp_dbg("Received LCP ECHO REQ\n");
1062        evaluate_lcp_state(ppp, PPP_LCP_EVENT_RXR);
1063        return;
1064    }
1065}
1066
1067static void pap_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1068{
1069    struct pico_pap_hdr *p = (struct pico_pap_hdr *)pkt;
1070    (void)len;
1071    if (!p)
1072        return;
1073
1074    if (ppp->auth != 0xc023)
1075        return;
1076
1077    switch(p->code) {
1078    case PAP_AUTH_ACK:
1079        ppp_dbg("PAP: Received Authentication OK!\n");
1080        evaluate_auth_state(ppp, PPP_AUTH_EVENT_RAA);
1081        break;
1082    case PAP_AUTH_NAK:
1083        ppp_dbg("PAP: Received Authentication Reject!\n");
1084        evaluate_auth_state(ppp, PPP_AUTH_EVENT_RAN);
1085        break;
1086
1087    default:
1088        ppp_dbg("PAP: Received invalid packet with code %d\n", p->code);
1089    }
1090}
1091
1092
1093static void chap_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1094{
1095    struct pico_chap_hdr *ch = (struct pico_chap_hdr *)pkt;
1096
1097    if (!pkt)
1098        return;
1099
1100    if (ppp->auth != 0xc223)
1101        return;
1102
1103    switch(ch->code) {
1104    case CHAP_CHALLENGE:
1105        ppp_dbg("Received CHAP CHALLENGE\n");
1106        ppp->pkt = pkt;
1107        ppp->len = len;
1108        evaluate_auth_state(ppp, PPP_AUTH_EVENT_RAC);
1109        break;
1110    case CHAP_SUCCESS:
1111        ppp_dbg("Received CHAP SUCCESS\n");
1112        evaluate_auth_state(ppp, PPP_AUTH_EVENT_RAA);
1113        break;
1114    case CHAP_FAILURE:
1115        ppp_dbg("Received CHAP FAILURE\n");
1116        evaluate_auth_state(ppp, PPP_AUTH_EVENT_RAN);
1117        break;
1118    }
1119}
1120
1121
1122static void ipcp_send_ack(struct pico_device_ppp *ppp)
1123{
1124    uint8_t ack[ppp->len + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_lcp_hdr) + PPP_FCS_SIZE + 1];
1125    struct pico_ipcp_hdr *ack_hdr = (struct pico_ipcp_hdr *) (ack + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
1126    struct pico_ipcp_hdr *ipcpreq = (struct pico_ipcp_hdr *)ppp->pkt;
1127    memcpy(ack + PPP_HDR_SIZE +  PPP_PROTO_SLOT_SIZE, ppp->pkt, ppp->len);
1128    ack_hdr->code = PICO_CONF_ACK;
1129    ack_hdr->id = ipcpreq->id;
1130    ack_hdr->len = ipcpreq->len;
1131    ppp_dbg("Sending IPCP CONF ACK\n");
1132    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_IPCP, ack,
1133                      PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE +  /* PPP Header, etc. */
1134                      short_be(ipcpreq->len) +               /* Actual options size + hdr (whole ipcp packet) */
1135                      PPP_FCS_SIZE +                        /* FCS at the end of the frame */
1136                      1                                     /* STOP Byte */
1137                      );
1138}
1139
1140static inline uint32_t ipcp_request_options_size(struct pico_device_ppp *ppp)
1141{
1142    uint32_t size = 0;
1143
1144/*    if (ppp->ipcp_ip) */
1145    size += IPCP_ADDR_LEN;
1146/*    if (ppp->ipcp_dns1) */
1147    size += IPCP_ADDR_LEN;
1148/*    if (ppp->ipcp_dns2) */
1149    size += IPCP_ADDR_LEN;
1150    if (ppp->ipcp_nbns1)
1151        size += IPCP_ADDR_LEN;
1152
1153    if (ppp->ipcp_nbns2)
1154        size += IPCP_ADDR_LEN;
1155
1156    return size;
1157}
1158
1159static int ipcp_request_add_address(uint8_t *dst, uint8_t tag, uint32_t arg)
1160{
1161    uint32_t addr = long_be(arg);
1162    dst[0] = tag;
1163    dst[1] = IPCP_ADDR_LEN;
1164    dst[2] = (uint8_t)((addr & 0xFF000000u) >> 24);
1165    dst[3] = (uint8_t)((addr & 0x00FF0000u) >> 16);
1166    dst[4] = (uint8_t)((addr & 0x0000FF00u) >> 8);
1167    dst[5] = (addr & 0x000000FFu);
1168    return IPCP_ADDR_LEN;
1169}
1170
1171static void ipcp_request_fill(struct pico_device_ppp *ppp, uint8_t *opts)
1172{
1173    if (ppp->ipcp_allowed_fields & IPCP_ALLOW_IP)
1174        opts += ipcp_request_add_address(opts, IPCP_OPT_IP, ppp->ipcp_ip);
1175
1176    if (ppp->ipcp_allowed_fields & IPCP_ALLOW_DNS1)
1177        opts += ipcp_request_add_address(opts, IPCP_OPT_DNS1, ppp->ipcp_dns1);
1178
1179    if (ppp->ipcp_allowed_fields & IPCP_ALLOW_DNS2)
1180        opts += ipcp_request_add_address(opts, IPCP_OPT_DNS2, ppp->ipcp_dns2);
1181
1182    if ((ppp->ipcp_allowed_fields & IPCP_ALLOW_NBNS1) &&  (ppp->ipcp_nbns1))
1183        opts += ipcp_request_add_address(opts, IPCP_OPT_NBNS1, ppp->ipcp_nbns1);
1184
1185    if ((ppp->ipcp_allowed_fields & IPCP_ALLOW_NBNS2) &&  (ppp->ipcp_nbns2))
1186        opts += ipcp_request_add_address(opts, IPCP_OPT_NBNS2, ppp->ipcp_nbns2);
1187}
1188
1189static void ipcp_send_req(struct pico_device_ppp *ppp)
1190{
1191    uint8_t ipcp_req[PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_ipcp_hdr) + ipcp_request_options_size(ppp) + PPP_FCS_SIZE + 1];
1192    uint32_t prefix = PPP_HDR_SIZE +  PPP_PROTO_SLOT_SIZE;
1193    struct pico_ipcp_hdr *ih = (struct pico_ipcp_hdr *) (ipcp_req + prefix);
1194    uint8_t *p = ipcp_req + prefix + sizeof(struct pico_ipcp_hdr);
1195    uint16_t len = (uint16_t)(ipcp_request_options_size(ppp) + sizeof(struct pico_ipcp_hdr));
1196
1197    ih->id = ppp->frame_id++;
1198    ih->code = PICO_CONF_REQ;
1199    ih->len = short_be(len);
1200    ipcp_request_fill(ppp, p);
1201
1202    ppp_dbg("Sending IPCP CONF REQ, ipcp size = %d\n", len);
1203    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_IPCP,
1204                      ipcp_req,             /* Start of PPP packet */
1205                      (uint32_t)(prefix +   /* PPP Header, etc. */
1206                                 (uint32_t)len + /* IPCP Header + options */
1207                                 PPP_FCS_SIZE + /* FCS at the end of the frame */
1208                                 1u)        /* STOP Byte */
1209                      );
1210}
1211
1212static void ipcp_reject_vj(struct pico_device_ppp *ppp, uint8_t *comp_req)
1213{
1214    uint8_t ipcp_req[PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_ipcp_hdr) + IPCP_VJ_LEN + PPP_FCS_SIZE + 1];
1215    uint32_t prefix = PPP_HDR_SIZE +  PPP_PROTO_SLOT_SIZE;
1216    struct pico_ipcp_hdr *ih = (struct pico_ipcp_hdr *) (ipcp_req + prefix);
1217    uint8_t *p = ipcp_req + prefix + sizeof(struct pico_ipcp_hdr);
1218    uint32_t i;
1219
1220    ih->id = ppp->frame_id++;
1221    ih->code = PICO_CONF_REQ;
1222    ih->len = short_be(IPCP_VJ_LEN + sizeof(struct pico_ipcp_hdr));
1223    for(i = 0; i < IPCP_OPT_VJ; i++)
1224        p[i] = comp_req[i + sizeof(struct pico_ipcp_hdr)];
1225    ppp_dbg("Sending IPCP CONF REJ VJ\n");
1226    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_IPCP,
1227                      ipcp_req,             /* Start of PPP packet */
1228                      (uint32_t)(prefix +              /* PPP Header, etc. */
1229                                 sizeof(struct pico_ipcp_hdr) + /* LCP HDR */
1230                                 IPCP_VJ_LEN + /* Actual options size */
1231                                 PPP_FCS_SIZE + /* FCS at the end of the frame */
1232                                 1u)         /* STOP Byte */
1233                      );
1234}
1235
1236static void ppp_ipv4_conf(struct pico_device_ppp *ppp)
1237{
1238    struct pico_ip4 ip;
1239    struct pico_ip4 nm;
1240    struct pico_ip4 dns1;
1241    struct pico_ip4 dns2;
1242    struct pico_ip4 any = {
1243        0
1244    };
1245    ip.addr = ppp->ipcp_ip;
1246    nm.addr = 0xFFFFFF00;
1247    pico_ipv4_link_add(&ppp->dev, ip, nm);
1248    pico_ipv4_route_add(any, any, any, 1, pico_ipv4_link_by_dev(&ppp->dev));
1249
1250    dns1.addr = ppp->ipcp_dns1;
1251    dns2.addr = ppp->ipcp_dns2;
1252    pico_dns_client_nameserver(&dns1, PICO_DNS_NS_ADD);
1253    pico_dns_client_nameserver(&dns2, PICO_DNS_NS_ADD);
1254}
1255
1256
1257static void ipcp_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1258{
1259    struct pico_ipcp_hdr *ih = (struct pico_ipcp_hdr *)pkt;
1260    uint8_t *p = pkt + sizeof(struct pico_ipcp_hdr);
1261    int reject = 0;
1262    while (p < pkt + len) {
1263        if (p[0] == IPCP_OPT_VJ) {
1264            reject++;
1265        }
1266
1267        if (p[0] == IPCP_OPT_IP) {
1268            if (ih->code != PICO_CONF_REJ)
1269                ppp->ipcp_ip = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
1270            else {
1271                ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_IP);
1272                ppp->ipcp_ip = 0;
1273            }
1274        }
1275
1276        if (p[0] == IPCP_OPT_DNS1) {
1277            if (ih->code != PICO_CONF_REJ)
1278                ppp->ipcp_dns1 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
1279            else {
1280                ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_DNS1);
1281                ppp->ipcp_dns1 = 0;
1282            }
1283        }
1284
1285        if (p[0] == IPCP_OPT_NBNS1) {
1286            if (ih->code != PICO_CONF_REJ)
1287                ppp->ipcp_nbns1 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
1288            else {
1289                ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_NBNS1);
1290                ppp->ipcp_nbns1 = 0;
1291            }
1292        }
1293
1294        if (p[0] == IPCP_OPT_DNS2) {
1295            if (ih->code != PICO_CONF_REJ)
1296                ppp->ipcp_dns2 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
1297            else {
1298                ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_DNS2);
1299                ppp->ipcp_dns2 = 0;
1300            }
1301        }
1302
1303        if (p[0] == IPCP_OPT_NBNS2) {
1304            if (ih->code != PICO_CONF_REJ)
1305                ppp->ipcp_nbns2 = long_be((uint32_t)((p[2] << 24) + (p[3] << 16) + (p[4] << 8) + p[5]));
1306            else {
1307                ppp->ipcp_allowed_fields &= (~IPCP_ALLOW_NBNS2);
1308                ppp->ipcp_nbns2 = 0;
1309            }
1310        }
1311
1312        p += p[1];
1313    }
1314    if (reject) {
1315        ipcp_reject_vj(ppp, p);
1316        return;
1317    }
1318
1319    ppp->pkt = pkt;
1320    ppp->len = len;
1321
1322    switch(ih->code) {
1323    case PICO_CONF_ACK:
1324        ppp_dbg("Received IPCP CONF ACK\n");
1325        evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCA);
1326        break;
1327    case PICO_CONF_REQ:
1328        ppp_dbg("Received IPCP CONF REQ\n");
1329        evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCR_POS);
1330        break;
1331    case PICO_CONF_NAK:
1332        ppp_dbg("Received IPCP CONF NAK\n");
1333        evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCN);
1334        break;
1335    case PICO_CONF_REJ:
1336        ppp_dbg("Received IPCP CONF REJ\n");
1337
1338        evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_RCN);
1339        break;
1340    }
1341}
1342
1343static void ipcp6_process_in(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1344{
1345    IGNORE_PARAMETER(ppp);
1346    IGNORE_PARAMETER(pkt);
1347    IGNORE_PARAMETER(len);
1348}
1349
1350static void ppp_process_packet_payload(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1351{
1352    if (pkt[0] == 0xc0) {
1353        /* Link control packet */
1354        if (pkt[1] == 0x21) {
1355            /* LCP */
1356            lcp_process_in(ppp, pkt + 2, len - 2);
1357        }
1358
1359        if (pkt[1] == 0x23) {
1360            /* PAP */
1361            pap_process_in(ppp, pkt + 2, len - 2);
1362        }
1363
1364        return;
1365    }
1366
1367    if ((pkt[0] == 0xc2) && (pkt[1] == 0x23)) {
1368        /*  CHAP */
1369        chap_process_in(ppp, pkt + 2, len - 2);
1370        return;
1371    }
1372
1373    if (pkt[0] == 0x80) {
1374        /* IP assignment (IPCP/IPCP6) */
1375        if (pkt[1] == 0x21) {
1376            /* IPCP */
1377            ipcp_process_in(ppp, pkt + 2, len - 2);
1378        }
1379
1380        if (pkt[1] == 0x57) {
1381            /* IPCP6 */
1382            ipcp6_process_in(ppp, pkt + 2, len - 2);
1383        }
1384
1385        return;
1386    }
1387
1388    if (pkt[0] == 0x00) {
1389        /* Uncompressed protocol: leading zero. */
1390        pkt++;
1391        len--;
1392    }
1393
1394    if ((pkt[0] == 0x21) || (pkt[0] == 0x57)) {
1395        /* IPv4 /v6 Data */
1396        pico_stack_recv(&ppp->dev, pkt + 1, len - 1);
1397        return;
1398    }
1399
1400    ppp_dbg("PPP: Unrecognized protocol %02x%02x\n", pkt[0], pkt[1]);
1401}
1402
1403static void ppp_process_packet(struct pico_device_ppp *ppp, uint8_t *pkt, uint32_t len)
1404{
1405    /* Verify incoming FCS */
1406    if (ppp_fcs_verify(pkt, len) != 0)
1407        return;
1408
1409    /* Remove trailing FCS */
1410    len -= 2;
1411
1412    /* Remove ADDR/CTRL, then process */
1413    if ((pkt[0] == PPPF_ADDR) && (pkt[1] == PPPF_CTRL)) {
1414        pkt += 2;
1415        len -= 2;
1416    }
1417
1418    ppp_process_packet_payload(ppp, pkt, len);
1419
1420}
1421
1422static void ppp_recv_data(struct pico_device_ppp *ppp, void *data, uint32_t len)
1423{
1424    uint8_t *pkt = (uint8_t *)data;
1425
1426#ifdef PPP_DEBUG
1427    uint32_t idx;
1428    if (len > 0) {
1429        ppp_dbg("PPP   <<<<< ");
1430        for(idx = 0; idx < len; idx++) {
1431            ppp_dbg(" %02x", ((uint8_t *)data)[idx]);
1432        }
1433        ppp_dbg("\n");
1434    }
1435
1436#endif
1437
1438    ppp_process_packet(ppp, pkt, len);
1439}
1440
1441static void lcp_this_layer_up(struct pico_device_ppp *ppp)
1442{
1443    ppp_dbg("PPP: LCP up.\n");
1444
1445    switch (ppp->auth) {
1446    case 0x0000:
1447        evaluate_auth_state(ppp, PPP_AUTH_EVENT_UP_NONE);
1448        break;
1449    case 0xc023:
1450        evaluate_auth_state(ppp, PPP_AUTH_EVENT_UP_PAP);
1451        break;
1452    case 0xc223:
1453        evaluate_auth_state(ppp, PPP_AUTH_EVENT_UP_CHAP);
1454        break;
1455    default:
1456        ppp_dbg("PPP: Unknown authentication protocol.\n");
1457        break;
1458    }
1459}
1460
1461static void lcp_this_layer_down(struct pico_device_ppp *ppp)
1462{
1463    ppp_dbg("PPP: LCP down.\n");
1464    evaluate_auth_state(ppp, PPP_AUTH_EVENT_DOWN);
1465}
1466
1467static void lcp_this_layer_started(struct pico_device_ppp *ppp)
1468{
1469    ppp_dbg("PPP: LCP started.\n");
1470    evaluate_modem_state(ppp, PPP_MODEM_EVENT_START);
1471}
1472
1473static void lcp_this_layer_finished(struct pico_device_ppp *ppp)
1474{
1475    ppp_dbg("PPP: LCP finished.\n");
1476    evaluate_modem_state(ppp, PPP_MODEM_EVENT_STOP);
1477}
1478
1479static void lcp_initialize_restart_count(struct pico_device_ppp *ppp)
1480{
1481    lcp_timer_start(ppp, PPP_TIMER_ON_LCPREQ);
1482}
1483
1484static void lcp_send_code_reject(struct pico_device_ppp *ppp)
1485{
1486    IGNORE_PARAMETER(ppp);
1487}
1488
1489static void lcp_send_echo_reply(struct pico_device_ppp *ppp)
1490{
1491    uint8_t reply[ppp->len + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_lcp_hdr) + PPP_FCS_SIZE + 1];
1492    struct pico_lcp_hdr *reply_hdr = (struct pico_lcp_hdr *) (reply + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
1493    struct pico_lcp_hdr *lcpreq = (struct pico_lcp_hdr *)ppp->pkt;
1494    memcpy(reply + PPP_HDR_SIZE +  PPP_PROTO_SLOT_SIZE, ppp->pkt, ppp->len);
1495    reply_hdr->code = PICO_CONF_ECHO_REP;
1496    reply_hdr->id = lcpreq->id;
1497    reply_hdr->len = lcpreq->len;
1498    ppp_dbg("Sending LCP ECHO REPLY\n");
1499    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_LCP, reply,
1500                      PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE +  /* PPP Header, etc. */
1501                      short_be(lcpreq->len) +               /* Actual options size + hdr (whole lcp packet) */
1502                      PPP_FCS_SIZE +                        /* FCS at the end of the frame */
1503                      1                                     /* STOP Byte */
1504                      );
1505}
1506
1507static const struct pico_ppp_fsm ppp_lcp_fsm[PPP_LCP_STATE_MAX][PPP_LCP_EVENT_MAX] = {
1508    [PPP_LCP_STATE_INITIAL] = {
1509        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_CLOSED, {} },
1510        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_INITIAL, {} },
1511        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_STARTING, { lcp_this_layer_started } },
1512        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_INITIAL, {} },
1513        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_INITIAL, {} },
1514        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_INITIAL, {} },
1515        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_INITIAL, {} },
1516        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_INITIAL, {} },
1517        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_INITIAL, {} },
1518        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_INITIAL, {} },
1519        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_INITIAL, {} },
1520        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_INITIAL, {} },
1521        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_INITIAL, {} },
1522        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_INITIAL, {} },
1523        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_INITIAL, {} },
1524        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_INITIAL, {} }
1525    },
1526    [PPP_LCP_STATE_STARTING] = {
1527        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_REQ_SENT, {  lcp_send_configure_request } },
1528        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, {} },
1529        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_STARTING, {} },
1530        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_INITIAL, { lcp_this_layer_finished } },
1531        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_STARTING, {} },
1532        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_STARTING, {} },
1533        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_STARTING, {} },
1534        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_STARTING, {} },
1535        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_STARTING, {} },
1536        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_STARTING, {} },
1537        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_STARTING, {} },
1538        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_STARTING, {} },
1539        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_STARTING, {} },
1540        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_STARTING, {} },
1541        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STARTING, {} },
1542        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_STARTING, {} }
1543    },
1544    [PPP_LCP_STATE_CLOSED] = {
1545        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_CLOSED, {} },
1546        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_INITIAL, {} },
1547        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_request} },
1548        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSED, {} },
1549        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_CLOSED, {} },
1550        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_CLOSED, {} },
1551        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_CLOSED, { lcp_send_terminate_ack } },
1552        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_CLOSED, { lcp_send_terminate_ack } },
1553        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_CLOSED, { lcp_send_terminate_ack } },
1554        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_CLOSED, { lcp_send_terminate_ack } },
1555        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_CLOSED, { lcp_send_terminate_ack } },
1556        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_CLOSED, {} },
1557        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_CLOSED, { lcp_send_code_reject } },
1558        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_CLOSED, {} },
1559        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_CLOSED, { lcp_this_layer_finished } },
1560        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_CLOSED, {} }
1561    },
1562    [PPP_LCP_STATE_STOPPED] = {
1563        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_STOPPED, {} },
1564        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, { lcp_this_layer_started } },
1565        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_STOPPED, {}},
1566        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSED, {}},
1567        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_STOPPED, {} },
1568        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_STOPPED, {} },
1569        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_ACK_SENT,
1570                                    { lcp_send_configure_request, lcp_send_configure_ack}},
1571        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_REQ_SENT,
1572                                    { lcp_send_configure_request, lcp_send_configure_nack}},
1573        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_STOPPED, { lcp_send_terminate_ack } },
1574        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_STOPPED, { lcp_send_terminate_ack } },
1575        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_STOPPED, { lcp_send_terminate_ack } },
1576        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_STOPPED, {} },
1577        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_STOPPED, { lcp_send_code_reject } },
1578        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_STOPPED, {} },
1579        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1580        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_STOPPED, {} }
1581    },
1582    [PPP_LCP_STATE_CLOSING] = {
1583        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_CLOSING, {} },
1584        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_INITIAL, {} },
1585        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_STOPPING, {} },
1586        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSING, {} },
1587        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_CLOSING, { lcp_send_terminate_request } },
1588        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_CLOSED, { lcp_this_layer_finished } },
1589        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_CLOSING, {} },
1590        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_CLOSING, {} },
1591        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_CLOSING, {} },
1592        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_CLOSING, {} },
1593        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_CLOSING, { lcp_send_terminate_ack } },
1594        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_CLOSED, { lcp_this_layer_finished } },
1595        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_CLOSING, { lcp_send_code_reject } },
1596        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_CLOSING, {} },
1597        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_CLOSED, { lcp_this_layer_finished } },
1598        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_CLOSING, {} }
1599    },
1600    [PPP_LCP_STATE_STOPPING] = {
1601        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_STOPPING, {} },
1602        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, {} },
1603        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_STOPPING, {} },
1604        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSING, {} },
1605        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_STOPPING, { lcp_send_terminate_request } },
1606        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1607        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_STOPPING, {} },
1608        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_STOPPING, {} },
1609        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_STOPPING, {} },
1610        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_STOPPING, {} },
1611        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_STOPPING, { lcp_send_terminate_ack } },
1612        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1613        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_STOPPING, { lcp_send_code_reject } },
1614        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_STOPPING, {} },
1615        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1616        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_STOPPING, {} }
1617    },
1618    [PPP_LCP_STATE_REQ_SENT] = {
1619        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_REQ_SENT, {} },
1620        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, {} },
1621        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_REQ_SENT, {} },
1622        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSING, { lcp_send_terminate_request } },
1623        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_request } },
1624        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1625        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_ACK_SENT, { lcp_send_configure_ack } },
1626        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_nack } },
1627        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_ACK_RCVD, { lcp_initialize_restart_count } },
1628        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_REQ_SENT, {  lcp_send_configure_request} },
1629        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_REQ_SENT, { lcp_send_terminate_ack } },
1630        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_REQ_SENT, {} },
1631        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_REQ_SENT, { lcp_send_code_reject } },
1632        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_REQ_SENT, {} },
1633        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1634        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_REQ_SENT, {} }
1635    },
1636    [PPP_LCP_STATE_ACK_RCVD] = {
1637        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_ACK_RCVD, {} },
1638        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, {} },
1639        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_ACK_RCVD, {} },
1640        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSING,  {  lcp_send_terminate_request} },
1641        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_request } },
1642        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_STOPPED,  { lcp_this_layer_finished } },
1643        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_OPENED,   { lcp_send_configure_ack, lcp_this_layer_up} },
1644        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_ACK_RCVD, { lcp_send_configure_nack } },
1645        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_request } },
1646        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_request } },
1647        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_REQ_SENT, { lcp_send_terminate_ack } },
1648        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_REQ_SENT, {} },
1649        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_ACK_RCVD, { lcp_send_code_reject } },
1650        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_REQ_SENT, {} },
1651        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STOPPED,  { lcp_this_layer_finished } },
1652        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_ACK_RCVD, {} }
1653    },
1654    [PPP_LCP_STATE_ACK_SENT] = {
1655        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_ACK_SENT, {} },
1656        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, {} },
1657        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_ACK_SENT, {} },
1658        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSING,  { lcp_send_terminate_request} },
1659        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_ACK_SENT, { lcp_send_configure_request } },
1660        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_STOPPED,  { lcp_this_layer_finished } },
1661        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_ACK_SENT, { lcp_send_configure_ack } },
1662        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_REQ_SENT, { lcp_send_configure_nack } },
1663        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_OPENED,   { lcp_this_layer_up} },
1664        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_ACK_SENT, { lcp_send_configure_request} },
1665        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_REQ_SENT, { lcp_send_terminate_ack } },
1666        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_ACK_SENT, {} },
1667        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_ACK_SENT, { lcp_send_code_reject } },
1668        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_ACK_SENT, {} },
1669        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STOPPED, { lcp_this_layer_finished } },
1670        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_ACK_SENT, {} }
1671    },
1672    [PPP_LCP_STATE_OPENED] = {
1673        [PPP_LCP_EVENT_UP]      = { PPP_LCP_STATE_OPENED, {} },
1674        [PPP_LCP_EVENT_DOWN]    = { PPP_LCP_STATE_STARTING, {lcp_this_layer_down } },
1675        [PPP_LCP_EVENT_OPEN]    = { PPP_LCP_STATE_OPENED, {} },
1676        [PPP_LCP_EVENT_CLOSE]   = { PPP_LCP_STATE_CLOSING,
1677                                    { lcp_this_layer_down, lcp_send_terminate_request }},
1678        [PPP_LCP_EVENT_TO_POS]  = { PPP_LCP_STATE_OPENED, {} },
1679        [PPP_LCP_EVENT_TO_NEG]  = { PPP_LCP_STATE_OPENED, {} },
1680        [PPP_LCP_EVENT_RCR_POS] = { PPP_LCP_STATE_ACK_SENT,
1681                                    { lcp_this_layer_down, lcp_send_terminate_request, lcp_send_configure_ack }},
1682        [PPP_LCP_EVENT_RCR_NEG] = { PPP_LCP_STATE_REQ_SENT,
1683                                    { lcp_this_layer_down, lcp_send_configure_request, lcp_send_configure_nack }},
1684        [PPP_LCP_EVENT_RCA]     = { PPP_LCP_STATE_REQ_SENT, { lcp_this_layer_down, lcp_send_terminate_request } },
1685        [PPP_LCP_EVENT_RCN]     = { PPP_LCP_STATE_REQ_SENT, { lcp_this_layer_down, lcp_send_terminate_request } },
1686        [PPP_LCP_EVENT_RTR]     = { PPP_LCP_STATE_STOPPING, { lcp_this_layer_down, lcp_zero_restart_count, lcp_send_terminate_ack} },
1687        [PPP_LCP_EVENT_RTA]     = { PPP_LCP_STATE_REQ_SENT, { lcp_this_layer_down, lcp_send_terminate_request} },
1688        [PPP_LCP_EVENT_RUC]     = { PPP_LCP_STATE_OPENED,   { lcp_send_code_reject } },
1689        [PPP_LCP_EVENT_RXJ_POS] = { PPP_LCP_STATE_OPENED,   { } },
1690        [PPP_LCP_EVENT_RXJ_NEG] = { PPP_LCP_STATE_STOPPING,
1691                                    {lcp_this_layer_down, lcp_send_terminate_request}},
1692        [PPP_LCP_EVENT_RXR]     = { PPP_LCP_STATE_OPENED, { lcp_send_echo_reply} }
1693    }
1694};
1695
1696static void evaluate_lcp_state(struct pico_device_ppp *ppp, enum ppp_lcp_event event)
1697{
1698    const struct pico_ppp_fsm *fsm, *next_fsm_to;
1699    int i;
1700    if (!ppp)
1701        return;
1702
1703    if (mock_lcp_state) {
1704        mock_lcp_state(ppp, event);
1705        return;
1706    }
1707
1708    fsm = &ppp_lcp_fsm[ppp->lcp_state][event];
1709    ppp->lcp_state = (enum ppp_lcp_state)fsm->next_state;
1710    /* RFC1661: The states in which the Restart timer is running are identifiable by
1711     * the presence of TO events.
1712     */
1713    next_fsm_to = &ppp_lcp_fsm[ppp->lcp_state][PPP_LCP_EVENT_TO_POS];
1714    if (!next_fsm_to->event_handler[0]) {
1715        /* The Restart timer is stopped when transitioning
1716         * from any state where the timer is running to a state where the timer
1717         * is not running.
1718         */
1719        lcp_timer_stop(ppp, PPP_TIMER_ON_LCPREQ);
1720        lcp_timer_stop(ppp, PPP_TIMER_ON_LCPTERM);
1721    }
1722
1723    for (i = 0; i < PPP_FSM_MAX_ACTIONS; i++) {
1724        if (fsm->event_handler[i])
1725            fsm->event_handler[i](ppp);
1726    }
1727}
1728
1729static void auth(struct pico_device_ppp *ppp)
1730{
1731    ppp_dbg("PPP: Authenticated.\n");
1732    ppp->ipcp_allowed_fields = 0xFFFF;
1733    evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_UP);
1734}
1735
1736static void deauth(struct pico_device_ppp *ppp)
1737{
1738    ppp_dbg("PPP: De-authenticated.\n");
1739    evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_DOWN);
1740}
1741
1742static void auth_abort(struct pico_device_ppp *ppp)
1743{
1744    ppp_dbg("PPP: Authentication failed!\n");
1745    ppp->timer_on = (uint8_t) (ppp->timer_on & (~PPP_TIMER_ON_AUTH));
1746    evaluate_lcp_state(ppp, PPP_LCP_EVENT_CLOSE);
1747
1748}
1749
1750static void auth_req(struct pico_device_ppp *ppp)
1751{
1752    uint16_t ppp_usr_len = 0;
1753    uint16_t ppp_pwd_len = 0;
1754    uint8_t *req = NULL, *p;
1755    struct pico_pap_hdr *hdr;
1756    uint16_t pap_len = 0;
1757    uint8_t field_len = 0;
1758    ppp_usr_len = (uint16_t)strlen(ppp->username);
1759    ppp_pwd_len = (uint16_t)strlen(ppp->password);
1760
1761    pap_len = (uint16_t)(sizeof(struct pico_pap_hdr) + 1u + 1u + ppp_usr_len + ppp_pwd_len);
1762
1763    req = PICO_ZALLOC(PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + pap_len + PPP_FCS_SIZE + 1);
1764    if (!req)
1765        return;
1766
1767    hdr = (struct pico_pap_hdr *) (req + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
1768
1769    hdr->code = PAP_AUTH_REQ;
1770    hdr->id = ppp->frame_id++;
1771    hdr->len = short_be(pap_len);
1772
1773    p = req + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_pap_hdr);
1774
1775    /* Populate authentication domain */
1776    field_len = (uint8_t)(ppp_usr_len & 0xFF);
1777    *p = field_len;
1778    ++p;
1779    if (ppp_usr_len > 0) {
1780        memcpy(p, ppp->username, ppp_usr_len);
1781        p += ppp_usr_len;
1782    }
1783
1784    /* Populate authentication password */
1785    field_len = (uint8_t)(ppp_pwd_len & 0xFF);
1786    *p = field_len;
1787    ++p;
1788    if (ppp_pwd_len > 0) {
1789        memcpy(p, ppp->password, ppp_pwd_len);
1790        p += ppp_pwd_len;
1791    }
1792
1793    ppp_dbg("PAP: Sending authentication request.\n");
1794    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_PAP,
1795                      req, /* Start of PPP packet */
1796                      (uint32_t)(
1797                          PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + /* PPP Header, etc. */
1798                          pap_len + /* Authentication packet len */
1799                          PPP_FCS_SIZE + /* FCS */
1800                          1)   /* STOP Byte */
1801                      );
1802    PICO_FREE(req);
1803}
1804
1805static void auth_rsp(struct pico_device_ppp *ppp)
1806{
1807    struct pico_chap_hdr *ch = (struct pico_chap_hdr *)ppp->pkt;
1808    uint8_t resp[PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_chap_hdr) + CHAP_MD5_SIZE + PPP_FCS_SIZE + 2];
1809    struct pico_chap_hdr *rh = (struct pico_chap_hdr *) (resp + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE);
1810    uint8_t *md5resp = resp + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_chap_hdr) + 1;
1811    uint8_t *md5resp_len = resp + PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + sizeof(struct pico_chap_hdr);
1812    uint8_t *challenge;
1813    uint32_t i = 0, pwdlen;
1814    uint8_t *recvd_challenge_len = ppp->pkt + sizeof(struct pico_chap_hdr);
1815    uint8_t *recvd_challenge = recvd_challenge_len + 1;
1816    size_t challenge_size = CHALLENGE_SIZE(ppp, ch);
1817
1818    challenge = PICO_ZALLOC(challenge_size);
1819
1820    if (!challenge)
1821        return;
1822
1823
1824    pwdlen = (uint32_t)strlen(ppp->password);
1825    challenge[i++] = ch->id;
1826    memcpy(challenge + i, ppp->password, pwdlen);
1827    i += pwdlen;
1828    memcpy(challenge + i, recvd_challenge, *recvd_challenge_len);
1829    i += *recvd_challenge_len;
1830    pico_md5sum(md5resp, challenge, i);
1831    PICO_FREE(challenge);
1832    rh->id = ch->id;
1833    rh->code = CHAP_RESPONSE;
1834    rh->len = short_be(CHAP_MD5_SIZE + sizeof(struct pico_chap_hdr) + 1);
1835    *md5resp_len = CHAP_MD5_SIZE;
1836    ppp_dbg("Sending CHAP RESPONSE, \n");
1837    pico_ppp_ctl_send(&ppp->dev, PPP_PROTO_CHAP,
1838                      resp,           /* Start of PPP packet */
1839                      (uint32_t)(
1840                          PPP_HDR_SIZE + PPP_PROTO_SLOT_SIZE + /* PPP Header, etc. */
1841                          sizeof(struct pico_chap_hdr) + /* CHAP HDR */
1842                          1                            + /* Value length */
1843                          CHAP_MD5_SIZE + /* Actual payload size */
1844                          PPP_FCS_SIZE + /* FCS at the end of the frame */
1845                          1)             /* STOP Byte */
1846                      );
1847}
1848
1849static void auth_start_timer(struct pico_device_ppp *ppp)
1850{
1851    ppp->timer_on = ppp->timer_on | PPP_TIMER_ON_AUTH;
1852    ppp->timer_val = PICO_PPP_DEFAULT_TIMER;
1853}
1854
1855static const struct pico_ppp_fsm ppp_auth_fsm[PPP_AUTH_STATE_MAX][PPP_AUTH_EVENT_MAX] = {
1856    [PPP_AUTH_STATE_INITIAL] = {
1857        [PPP_AUTH_EVENT_UP_NONE] = { PPP_AUTH_STATE_AUTHENTICATED, {auth} },
1858        [PPP_AUTH_EVENT_UP_PAP]  = { PPP_AUTH_STATE_REQ_SENT, {auth_req, auth_start_timer} },
1859        [PPP_AUTH_EVENT_UP_CHAP] = { PPP_AUTH_STATE_STARTING, {} },
1860        [PPP_AUTH_EVENT_DOWN]    = { PPP_AUTH_STATE_INITIAL, {} },
1861        [PPP_AUTH_EVENT_RAC]     = { PPP_AUTH_STATE_INITIAL, {} },
1862        [PPP_AUTH_EVENT_RAA]     = { PPP_AUTH_STATE_INITIAL, {} },
1863        [PPP_AUTH_EVENT_RAN]     = { PPP_AUTH_STATE_INITIAL, {auth_abort} },
1864        [PPP_AUTH_EVENT_TO]     =  { PPP_AUTH_STATE_INITIAL, {} }
1865    },
1866    [PPP_AUTH_STATE_STARTING] = {
1867        [PPP_AUTH_EVENT_UP_NONE] = { PPP_AUTH_STATE_STARTING, {} },
1868        [PPP_AUTH_EVENT_UP_PAP]  = { PPP_AUTH_STATE_STARTING, {} },
1869        [PPP_AUTH_EVENT_UP_CHAP] = { PPP_AUTH_STATE_STARTING, {} },
1870        [PPP_AUTH_EVENT_DOWN]    = { PPP_AUTH_STATE_INITIAL, {deauth} },
1871        [PPP_AUTH_EVENT_RAC]     = { PPP_AUTH_STATE_RSP_SENT, {auth_rsp, auth_start_timer} },
1872        [PPP_AUTH_EVENT_RAA]     = { PPP_AUTH_STATE_STARTING, {auth_start_timer} },
1873        [PPP_AUTH_EVENT_RAN]     = { PPP_AUTH_STATE_STARTING, {auth_abort} },
1874        [PPP_AUTH_EVENT_TO]     =  { PPP_AUTH_STATE_INITIAL, {auth_req, auth_start_timer} }
1875    },
1876    [PPP_AUTH_STATE_RSP_SENT] = {
1877        [PPP_AUTH_EVENT_UP_NONE] = { PPP_AUTH_STATE_RSP_SENT, {} },
1878        [PPP_AUTH_EVENT_UP_PAP]  = { PPP_AUTH_STATE_RSP_SENT, {} },
1879        [PPP_AUTH_EVENT_UP_CHAP] = { PPP_AUTH_STATE_RSP_SENT, {} },
1880        [PPP_AUTH_EVENT_DOWN]    = { PPP_AUTH_STATE_INITIAL, {deauth} },
1881        [PPP_AUTH_EVENT_RAC]     = { PPP_AUTH_STATE_RSP_SENT, {auth_rsp, auth_start_timer} },
1882        [PPP_AUTH_EVENT_RAA]     = { PPP_AUTH_STATE_AUTHENTICATED, {auth} },
1883        [PPP_AUTH_EVENT_RAN]     = { PPP_AUTH_STATE_STARTING, {auth_abort} },
1884        [PPP_AUTH_EVENT_TO]     =  { PPP_AUTH_STATE_STARTING, {auth_start_timer} }
1885    },
1886    [PPP_AUTH_STATE_REQ_SENT] = {
1887        [PPP_AUTH_EVENT_UP_NONE] = { PPP_AUTH_STATE_REQ_SENT, {} },
1888        [PPP_AUTH_EVENT_UP_PAP]  = { PPP_AUTH_STATE_REQ_SENT, {} },
1889        [PPP_AUTH_EVENT_UP_CHAP] = { PPP_AUTH_STATE_REQ_SENT, {} },
1890        [PPP_AUTH_EVENT_DOWN]    = { PPP_AUTH_STATE_INITIAL, {deauth} },
1891        [PPP_AUTH_EVENT_RAC]     = { PPP_AUTH_STATE_REQ_SENT, {} },
1892        [PPP_AUTH_EVENT_RAA]     = { PPP_AUTH_STATE_AUTHENTICATED, {auth} },
1893        [PPP_AUTH_EVENT_RAN]     = { PPP_AUTH_STATE_REQ_SENT, {auth_abort} },
1894        [PPP_AUTH_EVENT_TO]     =  { PPP_AUTH_STATE_REQ_SENT, {auth_req, auth_start_timer} }
1895    },
1896    [PPP_AUTH_STATE_AUTHENTICATED] = {
1897        [PPP_AUTH_EVENT_UP_NONE] = { PPP_AUTH_STATE_AUTHENTICATED, {} },
1898        [PPP_AUTH_EVENT_UP_PAP]  = { PPP_AUTH_STATE_AUTHENTICATED, {} },
1899        [PPP_AUTH_EVENT_UP_CHAP] = { PPP_AUTH_STATE_AUTHENTICATED, {} },
1900        [PPP_AUTH_EVENT_DOWN]    = { PPP_AUTH_STATE_INITIAL, {deauth} },
1901        [PPP_AUTH_EVENT_RAC]     = { PPP_AUTH_STATE_RSP_SENT, {auth_rsp} },
1902        [PPP_AUTH_EVENT_RAA]     = { PPP_AUTH_STATE_AUTHENTICATED, {} },
1903        [PPP_AUTH_EVENT_RAN]     = { PPP_AUTH_STATE_AUTHENTICATED, {} },
1904        [PPP_AUTH_EVENT_TO]      = { PPP_AUTH_STATE_AUTHENTICATED, {} },
1905    }
1906};
1907
1908static void evaluate_auth_state(struct pico_device_ppp *ppp, enum ppp_auth_event event)
1909{
1910    const struct pico_ppp_fsm *fsm;
1911    int i;
1912    if (mock_auth_state) {
1913        mock_auth_state(ppp, event);
1914        return;
1915    }
1916
1917    fsm = &ppp_auth_fsm[ppp->auth_state][event];
1918
1919    ppp->auth_state = (enum ppp_auth_state)fsm->next_state;
1920    for (i = 0; i < PPP_FSM_MAX_ACTIONS; i++) {
1921        if (fsm->event_handler[i])
1922            fsm->event_handler[i](ppp);
1923    }
1924}
1925
1926static void ipcp_send_nack(struct pico_device_ppp *ppp)
1927{
1928    IGNORE_PARAMETER(ppp);
1929}
1930
1931static void ipcp_bring_up(struct pico_device_ppp *ppp)
1932{
1933    ppp_dbg("PPP: IPCP up.\n");
1934
1935    if (ppp->ipcp_ip) {
1936        char my_ip[16], my_dns[16];
1937        pico_ipv4_to_string(my_ip, ppp->ipcp_ip);
1938        ppp_dbg("Received IP config %s\n", my_ip);
1939        pico_ipv4_to_string(my_dns, ppp->ipcp_dns1);
1940        ppp_dbg("Received DNS: %s\n", my_dns);
1941        ppp_ipv4_conf(ppp);
1942    }
1943}
1944
1945static void ipcp_bring_down(struct pico_device_ppp *ppp)
1946{
1947    IGNORE_PARAMETER(ppp);
1948
1949    ppp_dbg("PPP: IPCP down.\n");
1950}
1951
1952static void ipcp_start_timer(struct pico_device_ppp *ppp)
1953{
1954    ppp->timer_on = ppp->timer_on | PPP_TIMER_ON_IPCP;
1955    ppp->timer_val = PICO_PPP_DEFAULT_TIMER * PICO_PPP_DEFAULT_MAX_FAILURE;
1956}
1957
1958static const struct pico_ppp_fsm ppp_ipcp_fsm[PPP_IPCP_STATE_MAX][PPP_IPCP_EVENT_MAX] = {
1959    [PPP_IPCP_STATE_INITIAL] = {
1960        [PPP_IPCP_EVENT_UP]      = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req, ipcp_start_timer} },
1961        [PPP_IPCP_EVENT_DOWN]    = { PPP_IPCP_STATE_INITIAL, {} },
1962        [PPP_IPCP_EVENT_RCR_POS] = { PPP_IPCP_STATE_INITIAL, {} },
1963        [PPP_IPCP_EVENT_RCR_NEG] = { PPP_IPCP_STATE_INITIAL, {} },
1964        [PPP_IPCP_EVENT_RCA]     = { PPP_IPCP_STATE_INITIAL, {} },
1965        [PPP_IPCP_EVENT_RCN]     = { PPP_IPCP_STATE_INITIAL, {} },
1966        [PPP_IPCP_EVENT_TO]      = { PPP_IPCP_STATE_INITIAL, {} }
1967    },
1968    [PPP_IPCP_STATE_REQ_SENT] = {
1969        [PPP_IPCP_EVENT_UP]      = { PPP_IPCP_STATE_REQ_SENT, {} },
1970        [PPP_IPCP_EVENT_DOWN]    = { PPP_IPCP_STATE_INITIAL, {} },
1971        [PPP_IPCP_EVENT_RCR_POS] = { PPP_IPCP_STATE_ACK_SENT, {ipcp_send_ack} },
1972        [PPP_IPCP_EVENT_RCR_NEG] = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_nack} },
1973        [PPP_IPCP_EVENT_RCA]     = { PPP_IPCP_STATE_ACK_RCVD, {} },
1974        [PPP_IPCP_EVENT_RCN]     = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req, ipcp_start_timer} },
1975        [PPP_IPCP_EVENT_TO]      = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req, ipcp_start_timer} }
1976    },
1977    [PPP_IPCP_STATE_ACK_RCVD] = {
1978        [PPP_IPCP_EVENT_UP]      = { PPP_IPCP_STATE_ACK_RCVD, {} },
1979        [PPP_IPCP_EVENT_DOWN]    = { PPP_IPCP_STATE_INITIAL, {} },
1980        [PPP_IPCP_EVENT_RCR_POS] = { PPP_IPCP_STATE_OPENED, {ipcp_send_ack, ipcp_bring_up} },
1981        [PPP_IPCP_EVENT_RCR_NEG] = { PPP_IPCP_STATE_ACK_RCVD, {ipcp_send_nack} },
1982        [PPP_IPCP_EVENT_RCA]     = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req, ipcp_start_timer} },
1983        [PPP_IPCP_EVENT_RCN]     = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req, ipcp_start_timer} },
1984        [PPP_IPCP_EVENT_TO]      = { PPP_IPCP_STATE_ACK_RCVD, {ipcp_send_req, ipcp_start_timer} }
1985    },
1986    [PPP_IPCP_STATE_ACK_SENT] = {
1987        [PPP_IPCP_EVENT_UP]      = { PPP_IPCP_STATE_ACK_SENT, {} },
1988        [PPP_IPCP_EVENT_DOWN]    = { PPP_IPCP_STATE_INITIAL, {} },
1989        [PPP_IPCP_EVENT_RCR_POS] = { PPP_IPCP_STATE_ACK_SENT, {ipcp_send_ack} },
1990        [PPP_IPCP_EVENT_RCR_NEG] = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_nack} },
1991        [PPP_IPCP_EVENT_RCA]     = { PPP_IPCP_STATE_OPENED, {ipcp_bring_up} },
1992        [PPP_IPCP_EVENT_RCN]     = { PPP_IPCP_STATE_ACK_SENT, {ipcp_send_req, ipcp_start_timer} },
1993        [PPP_IPCP_EVENT_TO]      = { PPP_IPCP_STATE_ACK_SENT, {ipcp_send_req, ipcp_start_timer} }
1994    },
1995    [PPP_IPCP_STATE_OPENED] = {
1996        [PPP_IPCP_EVENT_UP]      = { PPP_IPCP_STATE_OPENED, {} },
1997        [PPP_IPCP_EVENT_DOWN]    = { PPP_IPCP_STATE_INITIAL, {ipcp_bring_down} },
1998        [PPP_IPCP_EVENT_RCR_POS] = { PPP_IPCP_STATE_ACK_SENT, {ipcp_bring_down, ipcp_send_req, ipcp_send_ack} },
1999        [PPP_IPCP_EVENT_RCR_NEG] = { PPP_IPCP_STATE_REQ_SENT, {ipcp_bring_down, ipcp_send_req, ipcp_send_nack} },
2000        [PPP_IPCP_EVENT_RCA]     = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req} },
2001        [PPP_IPCP_EVENT_RCN]     = { PPP_IPCP_STATE_REQ_SENT, {ipcp_send_req} },
2002        [PPP_IPCP_EVENT_TO]      = { PPP_IPCP_STATE_OPENED, {} }
2003    }
2004};
2005
2006static void evaluate_ipcp_state(struct pico_device_ppp *ppp, enum ppp_ipcp_event event)
2007{
2008    const struct pico_ppp_fsm *fsm;
2009    int i;
2010    if (mock_ipcp_state) {
2011        mock_ipcp_state(ppp, event);
2012        return;
2013    }
2014
2015    fsm = &ppp_ipcp_fsm[ppp->ipcp_state][event];
2016
2017    ppp->ipcp_state = (enum ppp_ipcp_state)fsm->next_state;
2018    for (i = 0; i < PPP_FSM_MAX_ACTIONS; i++) {
2019        if (fsm->event_handler[i])
2020            fsm->event_handler[i](ppp);
2021    }
2022}
2023
2024static int pico_ppp_poll(struct pico_device *dev, int loop_score)
2025{
2026    struct pico_device_ppp *ppp = (struct pico_device_ppp *) dev;
2027    static uint32_t len = 0;
2028    int r;
2029    if (ppp->serial_recv) {
2030        do {
2031            r = ppp->serial_recv(&ppp->dev, &ppp_recv_buf[len], 1);
2032            if (r <= 0)
2033                break;
2034
2035            if (ppp->modem_state == PPP_MODEM_STATE_CONNECTED) {
2036                static int control_escape = 0;
2037
2038                if (ppp_recv_buf[len] == PPPF_FLAG_SEQ) {
2039                    if (control_escape) {
2040                        /* Illegal sequence, discard frame */
2041                        ppp_dbg("Illegal sequence, ppp_recv_buf[%d] = %d\n", len, ppp_recv_buf[len]);
2042                        control_escape = 0;
2043                        len = 0;
2044                    }
2045
2046                    if (len > 1) {
2047                        ppp_recv_data(ppp, ppp_recv_buf, len);
2048                        loop_score--;
2049                        len = 0;
2050                    }
2051                } else if (control_escape) {
2052                    ppp_recv_buf[len] ^= 0x20;
2053                    control_escape = 0;
2054                    len++;
2055                } else if (ppp_recv_buf[len] == PPPF_CTRL_ESC) {
2056                    control_escape = 1;
2057                } else {
2058                    len++;
2059                }
2060            } else {
2061                static int s3 = 0;
2062
2063                if (ppp_recv_buf[len] == AT_S3) {
2064                    s3 = 1;
2065                    if (len > 0) {
2066                        ppp_recv_buf[len] = '\0';
2067                        ppp_modem_recv(ppp, ppp_recv_buf, len);
2068                        len = 0;
2069                    }
2070                } else if (ppp_recv_buf[len] == AT_S4) {
2071                    if (!s3) {
2072                        len++;
2073                    }
2074
2075                    s3 = 0;
2076                } else {
2077                    s3 = 0;
2078                    len++;
2079                }
2080            }
2081        } while ((r > 0) && (len < ARRAY_SIZE(ppp_recv_buf)) && (loop_score > 0));
2082    }
2083
2084    return loop_score;
2085}
2086
2087/* Public interface: create/destroy. */
2088
2089static int pico_ppp_link_state(struct pico_device *dev)
2090{
2091    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2092    if (ppp->ipcp_state == PPP_IPCP_STATE_OPENED)
2093        return 1;
2094
2095    return 0;
2096}
2097
2098void pico_ppp_destroy(struct pico_device *ppp)
2099{
2100    if (!ppp)
2101        return;
2102
2103    /* Perform custom cleanup here before calling 'pico_device_destroy'
2104     * or register a custom cleanup function during initialization
2105     * by setting 'ppp->dev.destroy'. */
2106
2107    pico_device_destroy(ppp);
2108}
2109
2110static void check_to_modem(struct pico_device_ppp *ppp)
2111{
2112    if (ppp->timer_on & PPP_TIMER_ON_MODEM) {
2113        if (ppp->timer_val == 0) {
2114            ppp->timer_on = (uint8_t) (ppp->timer_on & (~PPP_TIMER_ON_MODEM));
2115            evaluate_modem_state(ppp, PPP_MODEM_EVENT_TIMEOUT);
2116        }
2117    }
2118}
2119
2120static void check_to_lcp(struct pico_device_ppp *ppp)
2121{
2122    if (ppp->timer_on & (PPP_TIMER_ON_LCPREQ | PPP_TIMER_ON_LCPTERM)) {
2123        if (ppp->timer_val == 0) {
2124            if (ppp->timer_count == 0)
2125                evaluate_lcp_state(ppp, PPP_LCP_EVENT_TO_NEG);
2126            else{
2127                evaluate_lcp_state(ppp, PPP_LCP_EVENT_TO_POS);
2128                ppp->timer_count--;
2129            }
2130        }
2131    }
2132}
2133
2134static void check_to_auth(struct pico_device_ppp *ppp)
2135{
2136    if (ppp->timer_on & PPP_TIMER_ON_AUTH) {
2137        if (ppp->timer_val == 0) {
2138            ppp->timer_on = (uint8_t) (ppp->timer_on & (~PPP_TIMER_ON_AUTH));
2139            evaluate_auth_state(ppp, PPP_AUTH_EVENT_TO);
2140        }
2141    }
2142}
2143
2144static void check_to_ipcp(struct pico_device_ppp *ppp)
2145{
2146    if (ppp->timer_on & PPP_TIMER_ON_IPCP) {
2147        if (ppp->timer_val == 0) {
2148            ppp->timer_on = (uint8_t) (ppp->timer_on & (~PPP_TIMER_ON_IPCP));
2149            evaluate_ipcp_state(ppp, PPP_IPCP_EVENT_TO);
2150        }
2151    }
2152}
2153
2154static void pico_ppp_tick(pico_time t, void *arg)
2155{
2156    struct pico_device_ppp *ppp = (struct pico_device_ppp *) arg;
2157    (void)t;
2158    if (ppp->timer_val > 0)
2159        ppp->timer_val--;
2160
2161    check_to_modem(ppp);
2162    check_to_lcp(ppp);
2163    check_to_auth(ppp);
2164    check_to_ipcp(ppp);
2165
2166    if (ppp->autoreconnect && ppp->lcp_state == PPP_LCP_STATE_INITIAL) {
2167        ppp_dbg("(Re)connecting...\n");
2168        evaluate_lcp_state(ppp, PPP_LCP_EVENT_OPEN);
2169    }
2170
2171    if (!pico_timer_add(1000, pico_ppp_tick, arg)) {
2172        ppp_dbg("PPP: Failed to start tick timer\n");
2173        /* TODO No more PPP ticks now */
2174    }
2175}
2176
2177struct pico_device *pico_ppp_create(void)
2178{
2179    struct pico_device_ppp *ppp = PICO_ZALLOC(sizeof(struct pico_device_ppp));
2180    char devname[MAX_DEVICE_NAME];
2181
2182    if (!ppp)
2183        return NULL;
2184
2185    snprintf(devname, MAX_DEVICE_NAME, "ppp%d", ppp_devnum++);
2186
2187    if( 0 != pico_device_init((struct pico_device *)ppp, devname, NULL)) {
2188        return NULL;
2189    }
2190
2191    ppp->dev.overhead = PPP_HDR_SIZE;
2192    ppp->dev.mtu = PICO_PPP_MTU;
2193    ppp->dev.send = pico_ppp_send;
2194    ppp->dev.poll = pico_ppp_poll;
2195    ppp->dev.link_state  = pico_ppp_link_state;
2196    ppp->frame_id = (uint8_t)(pico_rand() % 0xFF);
2197
2198    ppp->modem_state = PPP_MODEM_STATE_INITIAL;
2199    ppp->lcp_state = PPP_LCP_STATE_INITIAL;
2200    ppp->auth_state = PPP_AUTH_STATE_INITIAL;
2201    ppp->ipcp_state = PPP_IPCP_STATE_INITIAL;
2202
2203    ppp->timer = pico_timer_add(1000, pico_ppp_tick, ppp);
2204    if (!ppp->timer) {
2205        ppp_dbg("PPP: Failed to start tick timer\n");
2206        pico_device_destroy((struct pico_device*) ppp);
2207        return NULL;
2208    }
2209    ppp->mru = PICO_PPP_MRU;
2210
2211    LCPOPT_SET_LOCAL(ppp, LCPOPT_MRU);
2212    LCPOPT_SET_LOCAL(ppp, LCPOPT_AUTH); /* We support authentication, even if it's not part of the req */
2213    LCPOPT_SET_LOCAL(ppp, LCPOPT_PROTO_COMP);
2214    LCPOPT_SET_LOCAL(ppp, LCPOPT_ADDRCTL_COMP);
2215
2216
2217    ppp_dbg("Device %s created.\n", ppp->dev.name);
2218    return (struct pico_device *)ppp;
2219}
2220
2221int pico_ppp_connect(struct pico_device *dev)
2222{
2223    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2224    ppp->autoreconnect = 1;
2225    return 0;
2226}
2227
2228int pico_ppp_disconnect(struct pico_device *dev)
2229{
2230    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2231    ppp->autoreconnect = 0;
2232    evaluate_lcp_state(ppp, PPP_LCP_EVENT_CLOSE);
2233
2234    pico_ipv4_cleanup_links(dev);
2235
2236    return 0;
2237}
2238
2239int pico_ppp_set_serial_read(struct pico_device *dev, int (*sread)(struct pico_device *, void *, int))
2240{
2241    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2242
2243    if (!dev)
2244        return -1;
2245
2246    ppp->serial_recv = sread;
2247    return 0;
2248}
2249
2250int pico_ppp_set_serial_write(struct pico_device *dev, int (*swrite)(struct pico_device *, const void *, int))
2251{
2252    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2253
2254    if (!dev)
2255        return -1;
2256
2257    ppp->serial_send = swrite;
2258    return 0;
2259}
2260
2261int pico_ppp_set_serial_set_speed(struct pico_device *dev, int (*sspeed)(struct pico_device *, uint32_t))
2262{
2263    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2264
2265    if (!dev)
2266        return -1;
2267
2268    ppp->serial_set_speed = sspeed;
2269    return 0;
2270}
2271
2272int pico_ppp_set_apn(struct pico_device *dev, const char *apn)
2273{
2274    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2275
2276    if (!dev)
2277        return -1;
2278
2279    if (!apn)
2280        return -1;
2281
2282    strncpy(ppp->apn, apn, sizeof(ppp->apn) - 1);
2283    return 0;
2284}
2285
2286int pico_ppp_set_username(struct pico_device *dev, const char *username)
2287{
2288    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2289
2290    if (!dev)
2291        return -1;
2292
2293    if (!username)
2294        return -1;
2295
2296    strncpy(ppp->username, username, sizeof(ppp->username) - 1);
2297    return 0;
2298}
2299
2300int pico_ppp_set_password(struct pico_device *dev, const char *password)
2301{
2302    struct pico_device_ppp *ppp = (struct pico_device_ppp *)dev;
2303
2304    if (!dev)
2305        return -1;
2306
2307    if (!password)
2308        return -1;
2309
2310    strncpy(ppp->password, password, sizeof(ppp->password) - 1);
2311    return 0;
2312}
2313