Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:f782d9c66c49 1 /**
dkato 0:f782d9c66c49 2 * @file
dkato 0:f782d9c66c49 3 * Network Point to Point Protocol over Serial file.
dkato 0:f782d9c66c49 4 *
dkato 0:f782d9c66c49 5 */
dkato 0:f782d9c66c49 6
dkato 0:f782d9c66c49 7 /*
dkato 0:f782d9c66c49 8 * Redistribution and use in source and binary forms, with or without modification,
dkato 0:f782d9c66c49 9 * are permitted provided that the following conditions are met:
dkato 0:f782d9c66c49 10 *
dkato 0:f782d9c66c49 11 * 1. Redistributions of source code must retain the above copyright notice,
dkato 0:f782d9c66c49 12 * this list of conditions and the following disclaimer.
dkato 0:f782d9c66c49 13 * 2. Redistributions in binary form must reproduce the above copyright notice,
dkato 0:f782d9c66c49 14 * this list of conditions and the following disclaimer in the documentation
dkato 0:f782d9c66c49 15 * and/or other materials provided with the distribution.
dkato 0:f782d9c66c49 16 * 3. The name of the author may not be used to endorse or promote products
dkato 0:f782d9c66c49 17 * derived from this software without specific prior written permission.
dkato 0:f782d9c66c49 18 *
dkato 0:f782d9c66c49 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
dkato 0:f782d9c66c49 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
dkato 0:f782d9c66c49 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
dkato 0:f782d9c66c49 22 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
dkato 0:f782d9c66c49 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
dkato 0:f782d9c66c49 24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
dkato 0:f782d9c66c49 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
dkato 0:f782d9c66c49 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
dkato 0:f782d9c66c49 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
dkato 0:f782d9c66c49 28 * OF SUCH DAMAGE.
dkato 0:f782d9c66c49 29 *
dkato 0:f782d9c66c49 30 * This file is part of the lwIP TCP/IP stack.
dkato 0:f782d9c66c49 31 *
dkato 0:f782d9c66c49 32 */
dkato 0:f782d9c66c49 33
dkato 0:f782d9c66c49 34 #include "netif/ppp/ppp_opts.h"
dkato 0:f782d9c66c49 35 #if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */
dkato 0:f782d9c66c49 36
dkato 0:f782d9c66c49 37 #include <string.h>
dkato 0:f782d9c66c49 38
dkato 0:f782d9c66c49 39 #include "lwip/arch.h"
dkato 0:f782d9c66c49 40 #include "lwip/err.h"
dkato 0:f782d9c66c49 41 #include "lwip/pbuf.h"
dkato 0:f782d9c66c49 42 #include "lwip/sys.h"
dkato 0:f782d9c66c49 43 #include "lwip/memp.h"
dkato 0:f782d9c66c49 44 #include "lwip/netif.h"
dkato 0:f782d9c66c49 45 #include "lwip/snmp.h"
dkato 0:f782d9c66c49 46 #include "lwip/priv/tcpip_priv.h"
dkato 0:f782d9c66c49 47 #include "lwip/api.h"
dkato 0:f782d9c66c49 48 #include "lwip/ip4.h" /* for ip4_input() */
dkato 0:f782d9c66c49 49
dkato 0:f782d9c66c49 50 #include "netif/ppp/ppp_impl.h"
dkato 0:f782d9c66c49 51 #include "netif/ppp/pppos.h"
dkato 0:f782d9c66c49 52 #include "netif/ppp/vj.h"
dkato 0:f782d9c66c49 53
dkato 0:f782d9c66c49 54 /* Memory pool */
dkato 0:f782d9c66c49 55 LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB")
dkato 0:f782d9c66c49 56
dkato 0:f782d9c66c49 57 /* callbacks called from PPP core */
dkato 0:f782d9c66c49 58 static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
dkato 0:f782d9c66c49 59 static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol);
dkato 0:f782d9c66c49 60 static err_t pppos_connect(ppp_pcb *ppp, void *ctx);
dkato 0:f782d9c66c49 61 #if PPP_SERVER
dkato 0:f782d9c66c49 62 static err_t pppos_listen(ppp_pcb *ppp, void *ctx);
dkato 0:f782d9c66c49 63 #endif /* PPP_SERVER */
dkato 0:f782d9c66c49 64 static void pppos_disconnect(ppp_pcb *ppp, void *ctx);
dkato 0:f782d9c66c49 65 static err_t pppos_destroy(ppp_pcb *ppp, void *ctx);
dkato 0:f782d9c66c49 66 static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp);
dkato 0:f782d9c66c49 67 static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp);
dkato 0:f782d9c66c49 68
dkato 0:f782d9c66c49 69 /* Prototypes for procedures local to this file. */
dkato 0:f782d9c66c49 70 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 71 static void pppos_input_callback(void *arg);
dkato 0:f782d9c66c49 72 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 73 static void pppos_input_free_current_packet(pppos_pcb *pppos);
dkato 0:f782d9c66c49 74 static void pppos_input_drop(pppos_pcb *pppos);
dkato 0:f782d9c66c49 75 static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs);
dkato 0:f782d9c66c49 76 static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs);
dkato 0:f782d9c66c49 77
dkato 0:f782d9c66c49 78 /* Callbacks structure for PPP core */
dkato 0:f782d9c66c49 79 static const struct link_callbacks pppos_callbacks = {
dkato 0:f782d9c66c49 80 pppos_connect,
dkato 0:f782d9c66c49 81 #if PPP_SERVER
dkato 0:f782d9c66c49 82 pppos_listen,
dkato 0:f782d9c66c49 83 #endif /* PPP_SERVER */
dkato 0:f782d9c66c49 84 pppos_disconnect,
dkato 0:f782d9c66c49 85 pppos_destroy,
dkato 0:f782d9c66c49 86 pppos_write,
dkato 0:f782d9c66c49 87 pppos_netif_output,
dkato 0:f782d9c66c49 88 pppos_send_config,
dkato 0:f782d9c66c49 89 pppos_recv_config
dkato 0:f782d9c66c49 90 };
dkato 0:f782d9c66c49 91
dkato 0:f782d9c66c49 92 /* PPP's Asynchronous-Control-Character-Map. The mask array is used
dkato 0:f782d9c66c49 93 * to select the specific bit for a character. */
dkato 0:f782d9c66c49 94 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07))
dkato 0:f782d9c66c49 95
dkato 0:f782d9c66c49 96 #if PPP_FCS_TABLE
dkato 0:f782d9c66c49 97 /*
dkato 0:f782d9c66c49 98 * FCS lookup table as calculated by genfcstab.
dkato 0:f782d9c66c49 99 */
dkato 0:f782d9c66c49 100 static const u16_t fcstab[256] = {
dkato 0:f782d9c66c49 101 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
dkato 0:f782d9c66c49 102 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
dkato 0:f782d9c66c49 103 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
dkato 0:f782d9c66c49 104 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
dkato 0:f782d9c66c49 105 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
dkato 0:f782d9c66c49 106 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
dkato 0:f782d9c66c49 107 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
dkato 0:f782d9c66c49 108 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
dkato 0:f782d9c66c49 109 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
dkato 0:f782d9c66c49 110 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
dkato 0:f782d9c66c49 111 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
dkato 0:f782d9c66c49 112 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
dkato 0:f782d9c66c49 113 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
dkato 0:f782d9c66c49 114 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
dkato 0:f782d9c66c49 115 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
dkato 0:f782d9c66c49 116 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
dkato 0:f782d9c66c49 117 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
dkato 0:f782d9c66c49 118 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
dkato 0:f782d9c66c49 119 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
dkato 0:f782d9c66c49 120 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
dkato 0:f782d9c66c49 121 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
dkato 0:f782d9c66c49 122 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
dkato 0:f782d9c66c49 123 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
dkato 0:f782d9c66c49 124 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
dkato 0:f782d9c66c49 125 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
dkato 0:f782d9c66c49 126 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
dkato 0:f782d9c66c49 127 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
dkato 0:f782d9c66c49 128 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
dkato 0:f782d9c66c49 129 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
dkato 0:f782d9c66c49 130 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
dkato 0:f782d9c66c49 131 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
dkato 0:f782d9c66c49 132 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
dkato 0:f782d9c66c49 133 };
dkato 0:f782d9c66c49 134 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
dkato 0:f782d9c66c49 135 #else /* PPP_FCS_TABLE */
dkato 0:f782d9c66c49 136 /* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */
dkato 0:f782d9c66c49 137 #define PPP_FCS_POLYNOMIAL 0x8408
dkato 0:f782d9c66c49 138 static u16_t
dkato 0:f782d9c66c49 139 ppp_get_fcs(u8_t byte)
dkato 0:f782d9c66c49 140 {
dkato 0:f782d9c66c49 141 unsigned int octet;
dkato 0:f782d9c66c49 142 int bit;
dkato 0:f782d9c66c49 143 octet = byte;
dkato 0:f782d9c66c49 144 for (bit = 8; bit-- > 0; ) {
dkato 0:f782d9c66c49 145 octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1);
dkato 0:f782d9c66c49 146 }
dkato 0:f782d9c66c49 147 return octet & 0xffff;
dkato 0:f782d9c66c49 148 }
dkato 0:f782d9c66c49 149 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff))
dkato 0:f782d9c66c49 150 #endif /* PPP_FCS_TABLE */
dkato 0:f782d9c66c49 151
dkato 0:f782d9c66c49 152 /*
dkato 0:f782d9c66c49 153 * Values for FCS calculations.
dkato 0:f782d9c66c49 154 */
dkato 0:f782d9c66c49 155 #define PPP_INITFCS 0xffff /* Initial FCS value */
dkato 0:f782d9c66c49 156 #define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
dkato 0:f782d9c66c49 157
dkato 0:f782d9c66c49 158 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 159 #define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev)
dkato 0:f782d9c66c49 160 #define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev)
dkato 0:f782d9c66c49 161 #define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev)
dkato 0:f782d9c66c49 162 #else
dkato 0:f782d9c66c49 163 #define PPPOS_DECL_PROTECT(lev)
dkato 0:f782d9c66c49 164 #define PPPOS_PROTECT(lev)
dkato 0:f782d9c66c49 165 #define PPPOS_UNPROTECT(lev)
dkato 0:f782d9c66c49 166 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 167
dkato 0:f782d9c66c49 168
dkato 0:f782d9c66c49 169 /*
dkato 0:f782d9c66c49 170 * Create a new PPP connection using the given serial I/O device.
dkato 0:f782d9c66c49 171 *
dkato 0:f782d9c66c49 172 * Return 0 on success, an error code on failure.
dkato 0:f782d9c66c49 173 */
dkato 0:f782d9c66c49 174 ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb,
dkato 0:f782d9c66c49 175 ppp_link_status_cb_fn link_status_cb, void *ctx_cb)
dkato 0:f782d9c66c49 176 {
dkato 0:f782d9c66c49 177 pppos_pcb *pppos;
dkato 0:f782d9c66c49 178 ppp_pcb *ppp;
dkato 0:f782d9c66c49 179
dkato 0:f782d9c66c49 180 pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB);
dkato 0:f782d9c66c49 181 if (pppos == NULL) {
dkato 0:f782d9c66c49 182 return NULL;
dkato 0:f782d9c66c49 183 }
dkato 0:f782d9c66c49 184
dkato 0:f782d9c66c49 185 ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb);
dkato 0:f782d9c66c49 186 if (ppp == NULL) {
dkato 0:f782d9c66c49 187 LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos);
dkato 0:f782d9c66c49 188 return NULL;
dkato 0:f782d9c66c49 189 }
dkato 0:f782d9c66c49 190
dkato 0:f782d9c66c49 191 memset(pppos, 0, sizeof(pppos_pcb));
dkato 0:f782d9c66c49 192 pppos->ppp = ppp;
dkato 0:f782d9c66c49 193 pppos->output_cb = output_cb;
dkato 0:f782d9c66c49 194 return ppp;
dkato 0:f782d9c66c49 195 }
dkato 0:f782d9c66c49 196
dkato 0:f782d9c66c49 197 /* Called by PPP core */
dkato 0:f782d9c66c49 198 static err_t
dkato 0:f782d9c66c49 199 pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p)
dkato 0:f782d9c66c49 200 {
dkato 0:f782d9c66c49 201 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 202 u8_t *s;
dkato 0:f782d9c66c49 203 struct pbuf *nb;
dkato 0:f782d9c66c49 204 u16_t n;
dkato 0:f782d9c66c49 205 u16_t fcs_out;
dkato 0:f782d9c66c49 206 err_t err;
dkato 0:f782d9c66c49 207 LWIP_UNUSED_ARG(ppp);
dkato 0:f782d9c66c49 208
dkato 0:f782d9c66c49 209 /* Grab an output buffer. */
dkato 0:f782d9c66c49 210 nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
dkato 0:f782d9c66c49 211 if (nb == NULL) {
dkato 0:f782d9c66c49 212 PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num));
dkato 0:f782d9c66c49 213 LINK_STATS_INC(link.memerr);
dkato 0:f782d9c66c49 214 LINK_STATS_INC(link.drop);
dkato 0:f782d9c66c49 215 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
dkato 0:f782d9c66c49 216 pbuf_free(p);
dkato 0:f782d9c66c49 217 return ERR_MEM;
dkato 0:f782d9c66c49 218 }
dkato 0:f782d9c66c49 219
dkato 0:f782d9c66c49 220 /* If the link has been idle, we'll send a fresh flag character to
dkato 0:f782d9c66c49 221 * flush any noise. */
dkato 0:f782d9c66c49 222 err = ERR_OK;
dkato 0:f782d9c66c49 223 if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) {
dkato 0:f782d9c66c49 224 err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL);
dkato 0:f782d9c66c49 225 }
dkato 0:f782d9c66c49 226
dkato 0:f782d9c66c49 227 /* Load output buffer. */
dkato 0:f782d9c66c49 228 fcs_out = PPP_INITFCS;
dkato 0:f782d9c66c49 229 s = (u8_t*)p->payload;
dkato 0:f782d9c66c49 230 n = p->len;
dkato 0:f782d9c66c49 231 while (n-- > 0) {
dkato 0:f782d9c66c49 232 err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out);
dkato 0:f782d9c66c49 233 }
dkato 0:f782d9c66c49 234
dkato 0:f782d9c66c49 235 err = pppos_output_last(pppos, err, nb, &fcs_out);
dkato 0:f782d9c66c49 236 if (err == ERR_OK) {
dkato 0:f782d9c66c49 237 PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len));
dkato 0:f782d9c66c49 238 } else {
dkato 0:f782d9c66c49 239 PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len));
dkato 0:f782d9c66c49 240 }
dkato 0:f782d9c66c49 241 pbuf_free(p);
dkato 0:f782d9c66c49 242 return err;
dkato 0:f782d9c66c49 243 }
dkato 0:f782d9c66c49 244
dkato 0:f782d9c66c49 245 /* Called by PPP core */
dkato 0:f782d9c66c49 246 static err_t
dkato 0:f782d9c66c49 247 pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol)
dkato 0:f782d9c66c49 248 {
dkato 0:f782d9c66c49 249 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 250 struct pbuf *nb, *p;
dkato 0:f782d9c66c49 251 u16_t fcs_out;
dkato 0:f782d9c66c49 252 err_t err;
dkato 0:f782d9c66c49 253 LWIP_UNUSED_ARG(ppp);
dkato 0:f782d9c66c49 254
dkato 0:f782d9c66c49 255 /* Grab an output buffer. */
dkato 0:f782d9c66c49 256 nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
dkato 0:f782d9c66c49 257 if (nb == NULL) {
dkato 0:f782d9c66c49 258 PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num));
dkato 0:f782d9c66c49 259 LINK_STATS_INC(link.memerr);
dkato 0:f782d9c66c49 260 LINK_STATS_INC(link.drop);
dkato 0:f782d9c66c49 261 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
dkato 0:f782d9c66c49 262 return ERR_MEM;
dkato 0:f782d9c66c49 263 }
dkato 0:f782d9c66c49 264
dkato 0:f782d9c66c49 265 /* If the link has been idle, we'll send a fresh flag character to
dkato 0:f782d9c66c49 266 * flush any noise. */
dkato 0:f782d9c66c49 267 err = ERR_OK;
dkato 0:f782d9c66c49 268 if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) {
dkato 0:f782d9c66c49 269 err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL);
dkato 0:f782d9c66c49 270 }
dkato 0:f782d9c66c49 271
dkato 0:f782d9c66c49 272 fcs_out = PPP_INITFCS;
dkato 0:f782d9c66c49 273 if (!pppos->accomp) {
dkato 0:f782d9c66c49 274 err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out);
dkato 0:f782d9c66c49 275 err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out);
dkato 0:f782d9c66c49 276 }
dkato 0:f782d9c66c49 277 if (!pppos->pcomp || protocol > 0xFF) {
dkato 0:f782d9c66c49 278 err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out);
dkato 0:f782d9c66c49 279 }
dkato 0:f782d9c66c49 280 err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out);
dkato 0:f782d9c66c49 281
dkato 0:f782d9c66c49 282 /* Load packet. */
dkato 0:f782d9c66c49 283 for(p = pb; p; p = p->next) {
dkato 0:f782d9c66c49 284 u16_t n = p->len;
dkato 0:f782d9c66c49 285 u8_t *s = (u8_t*)p->payload;
dkato 0:f782d9c66c49 286
dkato 0:f782d9c66c49 287 while (n-- > 0) {
dkato 0:f782d9c66c49 288 err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out);
dkato 0:f782d9c66c49 289 }
dkato 0:f782d9c66c49 290 }
dkato 0:f782d9c66c49 291
dkato 0:f782d9c66c49 292 err = pppos_output_last(pppos, err, nb, &fcs_out);
dkato 0:f782d9c66c49 293 if (err == ERR_OK) {
dkato 0:f782d9c66c49 294 PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len));
dkato 0:f782d9c66c49 295 } else {
dkato 0:f782d9c66c49 296 PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len));
dkato 0:f782d9c66c49 297 }
dkato 0:f782d9c66c49 298 return err;
dkato 0:f782d9c66c49 299 }
dkato 0:f782d9c66c49 300
dkato 0:f782d9c66c49 301 static err_t
dkato 0:f782d9c66c49 302 pppos_connect(ppp_pcb *ppp, void *ctx)
dkato 0:f782d9c66c49 303 {
dkato 0:f782d9c66c49 304 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 305 PPPOS_DECL_PROTECT(lev);
dkato 0:f782d9c66c49 306
dkato 0:f782d9c66c49 307 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 308 /* input pbuf left over from last session? */
dkato 0:f782d9c66c49 309 pppos_input_free_current_packet(pppos);
dkato 0:f782d9c66c49 310 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 311
dkato 0:f782d9c66c49 312 /* reset PPPoS control block to its initial state */
dkato 0:f782d9c66c49 313 memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit));
dkato 0:f782d9c66c49 314
dkato 0:f782d9c66c49 315 /*
dkato 0:f782d9c66c49 316 * Default the in and out accm so that escape and flag characters
dkato 0:f782d9c66c49 317 * are always escaped.
dkato 0:f782d9c66c49 318 */
dkato 0:f782d9c66c49 319 pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */
dkato 0:f782d9c66c49 320 pppos->out_accm[15] = 0x60;
dkato 0:f782d9c66c49 321 PPPOS_PROTECT(lev);
dkato 0:f782d9c66c49 322 pppos->open = 1;
dkato 0:f782d9c66c49 323 PPPOS_UNPROTECT(lev);
dkato 0:f782d9c66c49 324
dkato 0:f782d9c66c49 325 /*
dkato 0:f782d9c66c49 326 * Start the connection and handle incoming events (packet or timeout).
dkato 0:f782d9c66c49 327 */
dkato 0:f782d9c66c49 328 PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num));
dkato 0:f782d9c66c49 329 ppp_start(ppp); /* notify upper layers */
dkato 0:f782d9c66c49 330 return ERR_OK;
dkato 0:f782d9c66c49 331 }
dkato 0:f782d9c66c49 332
dkato 0:f782d9c66c49 333 #if PPP_SERVER
dkato 0:f782d9c66c49 334 static err_t
dkato 0:f782d9c66c49 335 pppos_listen(ppp_pcb *ppp, void *ctx)
dkato 0:f782d9c66c49 336 {
dkato 0:f782d9c66c49 337 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 338 PPPOS_DECL_PROTECT(lev);
dkato 0:f782d9c66c49 339
dkato 0:f782d9c66c49 340 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 341 /* input pbuf left over from last session? */
dkato 0:f782d9c66c49 342 pppos_input_free_current_packet(pppos);
dkato 0:f782d9c66c49 343 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 344
dkato 0:f782d9c66c49 345 /* reset PPPoS control block to its initial state */
dkato 0:f782d9c66c49 346 memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit));
dkato 0:f782d9c66c49 347
dkato 0:f782d9c66c49 348 /*
dkato 0:f782d9c66c49 349 * Default the in and out accm so that escape and flag characters
dkato 0:f782d9c66c49 350 * are always escaped.
dkato 0:f782d9c66c49 351 */
dkato 0:f782d9c66c49 352 pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */
dkato 0:f782d9c66c49 353 pppos->out_accm[15] = 0x60;
dkato 0:f782d9c66c49 354 PPPOS_PROTECT(lev);
dkato 0:f782d9c66c49 355 pppos->open = 1;
dkato 0:f782d9c66c49 356 PPPOS_UNPROTECT(lev);
dkato 0:f782d9c66c49 357
dkato 0:f782d9c66c49 358 /*
dkato 0:f782d9c66c49 359 * Wait for something to happen.
dkato 0:f782d9c66c49 360 */
dkato 0:f782d9c66c49 361 PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num));
dkato 0:f782d9c66c49 362 ppp_start(ppp); /* notify upper layers */
dkato 0:f782d9c66c49 363 return ERR_OK;
dkato 0:f782d9c66c49 364 }
dkato 0:f782d9c66c49 365 #endif /* PPP_SERVER */
dkato 0:f782d9c66c49 366
dkato 0:f782d9c66c49 367 static void
dkato 0:f782d9c66c49 368 pppos_disconnect(ppp_pcb *ppp, void *ctx)
dkato 0:f782d9c66c49 369 {
dkato 0:f782d9c66c49 370 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 371 PPPOS_DECL_PROTECT(lev);
dkato 0:f782d9c66c49 372
dkato 0:f782d9c66c49 373 PPPOS_PROTECT(lev);
dkato 0:f782d9c66c49 374 pppos->open = 0;
dkato 0:f782d9c66c49 375 PPPOS_UNPROTECT(lev);
dkato 0:f782d9c66c49 376
dkato 0:f782d9c66c49 377 /* If PPP_INPROC_IRQ_SAFE is used we cannot call
dkato 0:f782d9c66c49 378 * pppos_input_free_current_packet() here because
dkato 0:f782d9c66c49 379 * rx IRQ might still call pppos_input().
dkato 0:f782d9c66c49 380 */
dkato 0:f782d9c66c49 381 #if !PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 382 /* input pbuf left ? */
dkato 0:f782d9c66c49 383 pppos_input_free_current_packet(pppos);
dkato 0:f782d9c66c49 384 #endif /* !PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 385
dkato 0:f782d9c66c49 386 ppp_link_end(ppp); /* notify upper layers */
dkato 0:f782d9c66c49 387 }
dkato 0:f782d9c66c49 388
dkato 0:f782d9c66c49 389 static err_t
dkato 0:f782d9c66c49 390 pppos_destroy(ppp_pcb *ppp, void *ctx)
dkato 0:f782d9c66c49 391 {
dkato 0:f782d9c66c49 392 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 393 LWIP_UNUSED_ARG(ppp);
dkato 0:f782d9c66c49 394
dkato 0:f782d9c66c49 395 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 396 /* input pbuf left ? */
dkato 0:f782d9c66c49 397 pppos_input_free_current_packet(pppos);
dkato 0:f782d9c66c49 398 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 399
dkato 0:f782d9c66c49 400 LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos);
dkato 0:f782d9c66c49 401 return ERR_OK;
dkato 0:f782d9c66c49 402 }
dkato 0:f782d9c66c49 403
dkato 0:f782d9c66c49 404 #if !NO_SYS && !PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 405 /** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread.
dkato 0:f782d9c66c49 406 *
dkato 0:f782d9c66c49 407 * @param ppp PPP descriptor index, returned by pppos_create()
dkato 0:f782d9c66c49 408 * @param s received data
dkato 0:f782d9c66c49 409 * @param l length of received data
dkato 0:f782d9c66c49 410 */
dkato 0:f782d9c66c49 411 err_t
dkato 0:f782d9c66c49 412 pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l)
dkato 0:f782d9c66c49 413 {
dkato 0:f782d9c66c49 414 struct pbuf *p;
dkato 0:f782d9c66c49 415 err_t err;
dkato 0:f782d9c66c49 416
dkato 0:f782d9c66c49 417 p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL);
dkato 0:f782d9c66c49 418 if (!p) {
dkato 0:f782d9c66c49 419 return ERR_MEM;
dkato 0:f782d9c66c49 420 }
dkato 0:f782d9c66c49 421 pbuf_take(p, s, l);
dkato 0:f782d9c66c49 422
dkato 0:f782d9c66c49 423 err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys);
dkato 0:f782d9c66c49 424 if (err != ERR_OK) {
dkato 0:f782d9c66c49 425 pbuf_free(p);
dkato 0:f782d9c66c49 426 }
dkato 0:f782d9c66c49 427 return err;
dkato 0:f782d9c66c49 428 }
dkato 0:f782d9c66c49 429
dkato 0:f782d9c66c49 430 /* called from TCPIP thread */
dkato 0:f782d9c66c49 431 err_t pppos_input_sys(struct pbuf *p, struct netif *inp) {
dkato 0:f782d9c66c49 432 ppp_pcb *ppp = (ppp_pcb*)inp->state;
dkato 0:f782d9c66c49 433 struct pbuf *n;
dkato 0:f782d9c66c49 434
dkato 0:f782d9c66c49 435 for (n = p; n; n = n->next) {
dkato 0:f782d9c66c49 436 pppos_input(ppp, (u8_t*)n->payload, n->len);
dkato 0:f782d9c66c49 437 }
dkato 0:f782d9c66c49 438 pbuf_free(p);
dkato 0:f782d9c66c49 439 return ERR_OK;
dkato 0:f782d9c66c49 440 }
dkato 0:f782d9c66c49 441 #endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 442
dkato 0:f782d9c66c49 443 /** PPPoS input helper struct, must be packed since it is stored
dkato 0:f782d9c66c49 444 * to pbuf->payload, which might be unaligned. */
dkato 0:f782d9c66c49 445 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 446 #ifdef PACK_STRUCT_USE_INCLUDES
dkato 0:f782d9c66c49 447 # include "arch/bpstruct.h"
dkato 0:f782d9c66c49 448 #endif
dkato 0:f782d9c66c49 449 PACK_STRUCT_BEGIN
dkato 0:f782d9c66c49 450 struct pppos_input_header {
dkato 0:f782d9c66c49 451 PACK_STRUCT_FIELD(ppp_pcb *ppp);
dkato 0:f782d9c66c49 452 } PACK_STRUCT_STRUCT;
dkato 0:f782d9c66c49 453 PACK_STRUCT_END
dkato 0:f782d9c66c49 454 #ifdef PACK_STRUCT_USE_INCLUDES
dkato 0:f782d9c66c49 455 # include "arch/epstruct.h"
dkato 0:f782d9c66c49 456 #endif
dkato 0:f782d9c66c49 457 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 458
dkato 0:f782d9c66c49 459 /** Pass received raw characters to PPPoS to be decoded.
dkato 0:f782d9c66c49 460 *
dkato 0:f782d9c66c49 461 * @param ppp PPP descriptor index, returned by pppos_create()
dkato 0:f782d9c66c49 462 * @param s received data
dkato 0:f782d9c66c49 463 * @param l length of received data
dkato 0:f782d9c66c49 464 */
dkato 0:f782d9c66c49 465 void
dkato 0:f782d9c66c49 466 pppos_input(ppp_pcb *ppp, u8_t *s, int l)
dkato 0:f782d9c66c49 467 {
dkato 0:f782d9c66c49 468 pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb;
dkato 0:f782d9c66c49 469 struct pbuf *next_pbuf;
dkato 0:f782d9c66c49 470 u8_t cur_char;
dkato 0:f782d9c66c49 471 u8_t escaped;
dkato 0:f782d9c66c49 472 PPPOS_DECL_PROTECT(lev);
dkato 0:f782d9c66c49 473
dkato 0:f782d9c66c49 474 PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l));
dkato 0:f782d9c66c49 475 while (l-- > 0) {
dkato 0:f782d9c66c49 476 cur_char = *s++;
dkato 0:f782d9c66c49 477
dkato 0:f782d9c66c49 478 PPPOS_PROTECT(lev);
dkato 0:f782d9c66c49 479 /* ppp_input can disconnect the interface, we need to abort to prevent a memory
dkato 0:f782d9c66c49 480 * leak if there are remaining bytes because pppos_connect and pppos_listen
dkato 0:f782d9c66c49 481 * functions expect input buffer to be free. Furthermore there are no real
dkato 0:f782d9c66c49 482 * reason to continue reading bytes if we are disconnected.
dkato 0:f782d9c66c49 483 */
dkato 0:f782d9c66c49 484 if (!pppos->open) {
dkato 0:f782d9c66c49 485 PPPOS_UNPROTECT(lev);
dkato 0:f782d9c66c49 486 return;
dkato 0:f782d9c66c49 487 }
dkato 0:f782d9c66c49 488 escaped = ESCAPE_P(pppos->in_accm, cur_char);
dkato 0:f782d9c66c49 489 PPPOS_UNPROTECT(lev);
dkato 0:f782d9c66c49 490 /* Handle special characters. */
dkato 0:f782d9c66c49 491 if (escaped) {
dkato 0:f782d9c66c49 492 /* Check for escape sequences. */
dkato 0:f782d9c66c49 493 /* XXX Note that this does not handle an escaped 0x5d character which
dkato 0:f782d9c66c49 494 * would appear as an escape character. Since this is an ASCII ']'
dkato 0:f782d9c66c49 495 * and there is no reason that I know of to escape it, I won't complicate
dkato 0:f782d9c66c49 496 * the code to handle this case. GLL */
dkato 0:f782d9c66c49 497 if (cur_char == PPP_ESCAPE) {
dkato 0:f782d9c66c49 498 pppos->in_escaped = 1;
dkato 0:f782d9c66c49 499 /* Check for the flag character. */
dkato 0:f782d9c66c49 500 } else if (cur_char == PPP_FLAG) {
dkato 0:f782d9c66c49 501 /* If this is just an extra flag character, ignore it. */
dkato 0:f782d9c66c49 502 if (pppos->in_state <= PDADDRESS) {
dkato 0:f782d9c66c49 503 /* ignore it */;
dkato 0:f782d9c66c49 504 /* If we haven't received the packet header, drop what has come in. */
dkato 0:f782d9c66c49 505 } else if (pppos->in_state < PDDATA) {
dkato 0:f782d9c66c49 506 PPPDEBUG(LOG_WARNING,
dkato 0:f782d9c66c49 507 ("pppos_input[%d]: Dropping incomplete packet %d\n",
dkato 0:f782d9c66c49 508 ppp->netif->num, pppos->in_state));
dkato 0:f782d9c66c49 509 LINK_STATS_INC(link.lenerr);
dkato 0:f782d9c66c49 510 pppos_input_drop(pppos);
dkato 0:f782d9c66c49 511 /* If the fcs is invalid, drop the packet. */
dkato 0:f782d9c66c49 512 } else if (pppos->in_fcs != PPP_GOODFCS) {
dkato 0:f782d9c66c49 513 PPPDEBUG(LOG_INFO,
dkato 0:f782d9c66c49 514 ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n",
dkato 0:f782d9c66c49 515 ppp->netif->num, pppos->in_fcs, pppos->in_protocol));
dkato 0:f782d9c66c49 516 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */
dkato 0:f782d9c66c49 517 LINK_STATS_INC(link.chkerr);
dkato 0:f782d9c66c49 518 pppos_input_drop(pppos);
dkato 0:f782d9c66c49 519 /* Otherwise it's a good packet so pass it on. */
dkato 0:f782d9c66c49 520 } else {
dkato 0:f782d9c66c49 521 struct pbuf *inp;
dkato 0:f782d9c66c49 522 /* Trim off the checksum. */
dkato 0:f782d9c66c49 523 if(pppos->in_tail->len > 2) {
dkato 0:f782d9c66c49 524 pppos->in_tail->len -= 2;
dkato 0:f782d9c66c49 525
dkato 0:f782d9c66c49 526 pppos->in_tail->tot_len = pppos->in_tail->len;
dkato 0:f782d9c66c49 527 if (pppos->in_tail != pppos->in_head) {
dkato 0:f782d9c66c49 528 pbuf_cat(pppos->in_head, pppos->in_tail);
dkato 0:f782d9c66c49 529 }
dkato 0:f782d9c66c49 530 } else {
dkato 0:f782d9c66c49 531 pppos->in_tail->tot_len = pppos->in_tail->len;
dkato 0:f782d9c66c49 532 if (pppos->in_tail != pppos->in_head) {
dkato 0:f782d9c66c49 533 pbuf_cat(pppos->in_head, pppos->in_tail);
dkato 0:f782d9c66c49 534 }
dkato 0:f782d9c66c49 535
dkato 0:f782d9c66c49 536 pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2);
dkato 0:f782d9c66c49 537 }
dkato 0:f782d9c66c49 538
dkato 0:f782d9c66c49 539 /* Dispatch the packet thereby consuming it. */
dkato 0:f782d9c66c49 540 inp = pppos->in_head;
dkato 0:f782d9c66c49 541 /* Packet consumed, release our references. */
dkato 0:f782d9c66c49 542 pppos->in_head = NULL;
dkato 0:f782d9c66c49 543 pppos->in_tail = NULL;
dkato 0:f782d9c66c49 544 #if IP_FORWARD || LWIP_IPV6_FORWARD
dkato 0:f782d9c66c49 545 /* hide the room for Ethernet forwarding header */
dkato 0:f782d9c66c49 546 pbuf_header(inp, -(s16_t)(PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN));
dkato 0:f782d9c66c49 547 #endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
dkato 0:f782d9c66c49 548 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 549 if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) {
dkato 0:f782d9c66c49 550 PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num));
dkato 0:f782d9c66c49 551 pbuf_free(inp);
dkato 0:f782d9c66c49 552 LINK_STATS_INC(link.drop);
dkato 0:f782d9c66c49 553 MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards);
dkato 0:f782d9c66c49 554 }
dkato 0:f782d9c66c49 555 #else /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 556 ppp_input(ppp, inp);
dkato 0:f782d9c66c49 557 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 558 }
dkato 0:f782d9c66c49 559
dkato 0:f782d9c66c49 560 /* Prepare for a new packet. */
dkato 0:f782d9c66c49 561 pppos->in_fcs = PPP_INITFCS;
dkato 0:f782d9c66c49 562 pppos->in_state = PDADDRESS;
dkato 0:f782d9c66c49 563 pppos->in_escaped = 0;
dkato 0:f782d9c66c49 564 /* Other characters are usually control characters that may have
dkato 0:f782d9c66c49 565 * been inserted by the physical layer so here we just drop them. */
dkato 0:f782d9c66c49 566 } else {
dkato 0:f782d9c66c49 567 PPPDEBUG(LOG_WARNING,
dkato 0:f782d9c66c49 568 ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char));
dkato 0:f782d9c66c49 569 }
dkato 0:f782d9c66c49 570 /* Process other characters. */
dkato 0:f782d9c66c49 571 } else {
dkato 0:f782d9c66c49 572 /* Unencode escaped characters. */
dkato 0:f782d9c66c49 573 if (pppos->in_escaped) {
dkato 0:f782d9c66c49 574 pppos->in_escaped = 0;
dkato 0:f782d9c66c49 575 cur_char ^= PPP_TRANS;
dkato 0:f782d9c66c49 576 }
dkato 0:f782d9c66c49 577
dkato 0:f782d9c66c49 578 /* Process character relative to current state. */
dkato 0:f782d9c66c49 579 switch(pppos->in_state) {
dkato 0:f782d9c66c49 580 case PDIDLE: /* Idle state - waiting. */
dkato 0:f782d9c66c49 581 /* Drop the character if it's not 0xff
dkato 0:f782d9c66c49 582 * we would have processed a flag character above. */
dkato 0:f782d9c66c49 583 if (cur_char != PPP_ALLSTATIONS) {
dkato 0:f782d9c66c49 584 break;
dkato 0:f782d9c66c49 585 }
dkato 0:f782d9c66c49 586 /* no break */
dkato 0:f782d9c66c49 587 /* Fall through */
dkato 0:f782d9c66c49 588
dkato 0:f782d9c66c49 589 case PDSTART: /* Process start flag. */
dkato 0:f782d9c66c49 590 /* Prepare for a new packet. */
dkato 0:f782d9c66c49 591 pppos->in_fcs = PPP_INITFCS;
dkato 0:f782d9c66c49 592 /* no break */
dkato 0:f782d9c66c49 593 /* Fall through */
dkato 0:f782d9c66c49 594
dkato 0:f782d9c66c49 595 case PDADDRESS: /* Process address field. */
dkato 0:f782d9c66c49 596 if (cur_char == PPP_ALLSTATIONS) {
dkato 0:f782d9c66c49 597 pppos->in_state = PDCONTROL;
dkato 0:f782d9c66c49 598 break;
dkato 0:f782d9c66c49 599 }
dkato 0:f782d9c66c49 600 /* no break */
dkato 0:f782d9c66c49 601
dkato 0:f782d9c66c49 602 /* Else assume compressed address and control fields so
dkato 0:f782d9c66c49 603 * fall through to get the protocol... */
dkato 0:f782d9c66c49 604 case PDCONTROL: /* Process control field. */
dkato 0:f782d9c66c49 605 /* If we don't get a valid control code, restart. */
dkato 0:f782d9c66c49 606 if (cur_char == PPP_UI) {
dkato 0:f782d9c66c49 607 pppos->in_state = PDPROTOCOL1;
dkato 0:f782d9c66c49 608 break;
dkato 0:f782d9c66c49 609 }
dkato 0:f782d9c66c49 610 /* no break */
dkato 0:f782d9c66c49 611
dkato 0:f782d9c66c49 612 #if 0
dkato 0:f782d9c66c49 613 else {
dkato 0:f782d9c66c49 614 PPPDEBUG(LOG_WARNING,
dkato 0:f782d9c66c49 615 ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char));
dkato 0:f782d9c66c49 616 pppos->in_state = PDSTART;
dkato 0:f782d9c66c49 617 }
dkato 0:f782d9c66c49 618 #endif
dkato 0:f782d9c66c49 619 case PDPROTOCOL1: /* Process protocol field 1. */
dkato 0:f782d9c66c49 620 /* If the lower bit is set, this is the end of the protocol
dkato 0:f782d9c66c49 621 * field. */
dkato 0:f782d9c66c49 622 if (cur_char & 1) {
dkato 0:f782d9c66c49 623 pppos->in_protocol = cur_char;
dkato 0:f782d9c66c49 624 pppos->in_state = PDDATA;
dkato 0:f782d9c66c49 625 } else {
dkato 0:f782d9c66c49 626 pppos->in_protocol = (u16_t)cur_char << 8;
dkato 0:f782d9c66c49 627 pppos->in_state = PDPROTOCOL2;
dkato 0:f782d9c66c49 628 }
dkato 0:f782d9c66c49 629 break;
dkato 0:f782d9c66c49 630 case PDPROTOCOL2: /* Process protocol field 2. */
dkato 0:f782d9c66c49 631 pppos->in_protocol |= cur_char;
dkato 0:f782d9c66c49 632 pppos->in_state = PDDATA;
dkato 0:f782d9c66c49 633 break;
dkato 0:f782d9c66c49 634 case PDDATA: /* Process data byte. */
dkato 0:f782d9c66c49 635 /* Make space to receive processed data. */
dkato 0:f782d9c66c49 636 if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) {
dkato 0:f782d9c66c49 637 u16_t pbuf_alloc_len;
dkato 0:f782d9c66c49 638 if (pppos->in_tail != NULL) {
dkato 0:f782d9c66c49 639 pppos->in_tail->tot_len = pppos->in_tail->len;
dkato 0:f782d9c66c49 640 if (pppos->in_tail != pppos->in_head) {
dkato 0:f782d9c66c49 641 pbuf_cat(pppos->in_head, pppos->in_tail);
dkato 0:f782d9c66c49 642 /* give up the in_tail reference now */
dkato 0:f782d9c66c49 643 pppos->in_tail = NULL;
dkato 0:f782d9c66c49 644 }
dkato 0:f782d9c66c49 645 }
dkato 0:f782d9c66c49 646 /* If we haven't started a packet, we need a packet header. */
dkato 0:f782d9c66c49 647 pbuf_alloc_len = 0;
dkato 0:f782d9c66c49 648 #if IP_FORWARD || LWIP_IPV6_FORWARD
dkato 0:f782d9c66c49 649 /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN
dkato 0:f782d9c66c49 650 * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header
dkato 0:f782d9c66c49 651 * space to be forwarded (to Ethernet for example).
dkato 0:f782d9c66c49 652 */
dkato 0:f782d9c66c49 653 if (pppos->in_head == NULL) {
dkato 0:f782d9c66c49 654 pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN;
dkato 0:f782d9c66c49 655 }
dkato 0:f782d9c66c49 656 #endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
dkato 0:f782d9c66c49 657 next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL);
dkato 0:f782d9c66c49 658 if (next_pbuf == NULL) {
dkato 0:f782d9c66c49 659 /* No free buffers. Drop the input packet and let the
dkato 0:f782d9c66c49 660 * higher layers deal with it. Continue processing
dkato 0:f782d9c66c49 661 * the received pbuf chain in case a new packet starts. */
dkato 0:f782d9c66c49 662 PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num));
dkato 0:f782d9c66c49 663 LINK_STATS_INC(link.memerr);
dkato 0:f782d9c66c49 664 pppos_input_drop(pppos);
dkato 0:f782d9c66c49 665 pppos->in_state = PDSTART; /* Wait for flag sequence. */
dkato 0:f782d9c66c49 666 break;
dkato 0:f782d9c66c49 667 }
dkato 0:f782d9c66c49 668 if (pppos->in_head == NULL) {
dkato 0:f782d9c66c49 669 u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len;
dkato 0:f782d9c66c49 670 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 671 ((struct pppos_input_header*)payload)->ppp = ppp;
dkato 0:f782d9c66c49 672 payload += sizeof(struct pppos_input_header);
dkato 0:f782d9c66c49 673 next_pbuf->len += sizeof(struct pppos_input_header);
dkato 0:f782d9c66c49 674 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 675 next_pbuf->len += sizeof(pppos->in_protocol);
dkato 0:f782d9c66c49 676 *(payload++) = pppos->in_protocol >> 8;
dkato 0:f782d9c66c49 677 *(payload) = pppos->in_protocol & 0xFF;
dkato 0:f782d9c66c49 678 pppos->in_head = next_pbuf;
dkato 0:f782d9c66c49 679 }
dkato 0:f782d9c66c49 680 pppos->in_tail = next_pbuf;
dkato 0:f782d9c66c49 681 }
dkato 0:f782d9c66c49 682 /* Load character into buffer. */
dkato 0:f782d9c66c49 683 ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char;
dkato 0:f782d9c66c49 684 break;
dkato 0:f782d9c66c49 685 default:
dkato 0:f782d9c66c49 686 break;
dkato 0:f782d9c66c49 687 }
dkato 0:f782d9c66c49 688
dkato 0:f782d9c66c49 689 /* update the frame check sequence number. */
dkato 0:f782d9c66c49 690 pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char);
dkato 0:f782d9c66c49 691 }
dkato 0:f782d9c66c49 692 } /* while (l-- > 0), all bytes processed */
dkato 0:f782d9c66c49 693 }
dkato 0:f782d9c66c49 694
dkato 0:f782d9c66c49 695 #if PPP_INPROC_IRQ_SAFE
dkato 0:f782d9c66c49 696 /* PPPoS input callback using one input pointer
dkato 0:f782d9c66c49 697 */
dkato 0:f782d9c66c49 698 static void pppos_input_callback(void *arg) {
dkato 0:f782d9c66c49 699 struct pbuf *pb = (struct pbuf*)arg;
dkato 0:f782d9c66c49 700 ppp_pcb *ppp;
dkato 0:f782d9c66c49 701
dkato 0:f782d9c66c49 702 ppp = ((struct pppos_input_header*)pb->payload)->ppp;
dkato 0:f782d9c66c49 703 if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) {
dkato 0:f782d9c66c49 704 LWIP_ASSERT("pbuf_header failed\n", 0);
dkato 0:f782d9c66c49 705 goto drop;
dkato 0:f782d9c66c49 706 }
dkato 0:f782d9c66c49 707
dkato 0:f782d9c66c49 708 /* Dispatch the packet thereby consuming it. */
dkato 0:f782d9c66c49 709 ppp_input(ppp, pb);
dkato 0:f782d9c66c49 710 return;
dkato 0:f782d9c66c49 711
dkato 0:f782d9c66c49 712 drop:
dkato 0:f782d9c66c49 713 LINK_STATS_INC(link.drop);
dkato 0:f782d9c66c49 714 MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards);
dkato 0:f782d9c66c49 715 pbuf_free(pb);
dkato 0:f782d9c66c49 716 }
dkato 0:f782d9c66c49 717 #endif /* PPP_INPROC_IRQ_SAFE */
dkato 0:f782d9c66c49 718
dkato 0:f782d9c66c49 719 static void
dkato 0:f782d9c66c49 720 pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp)
dkato 0:f782d9c66c49 721 {
dkato 0:f782d9c66c49 722 int i;
dkato 0:f782d9c66c49 723 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 724 LWIP_UNUSED_ARG(ppp);
dkato 0:f782d9c66c49 725
dkato 0:f782d9c66c49 726 pppos->pcomp = pcomp;
dkato 0:f782d9c66c49 727 pppos->accomp = accomp;
dkato 0:f782d9c66c49 728
dkato 0:f782d9c66c49 729 /* Load the ACCM bits for the 32 control codes. */
dkato 0:f782d9c66c49 730 for (i = 0; i < 32/8; i++) {
dkato 0:f782d9c66c49 731 pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF);
dkato 0:f782d9c66c49 732 }
dkato 0:f782d9c66c49 733
dkato 0:f782d9c66c49 734 PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n",
dkato 0:f782d9c66c49 735 pppos->ppp->netif->num,
dkato 0:f782d9c66c49 736 pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3]));
dkato 0:f782d9c66c49 737 }
dkato 0:f782d9c66c49 738
dkato 0:f782d9c66c49 739 static void
dkato 0:f782d9c66c49 740 pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp)
dkato 0:f782d9c66c49 741 {
dkato 0:f782d9c66c49 742 int i;
dkato 0:f782d9c66c49 743 pppos_pcb *pppos = (pppos_pcb *)ctx;
dkato 0:f782d9c66c49 744 PPPOS_DECL_PROTECT(lev);
dkato 0:f782d9c66c49 745 LWIP_UNUSED_ARG(ppp);
dkato 0:f782d9c66c49 746 LWIP_UNUSED_ARG(pcomp);
dkato 0:f782d9c66c49 747 LWIP_UNUSED_ARG(accomp);
dkato 0:f782d9c66c49 748
dkato 0:f782d9c66c49 749 /* Load the ACCM bits for the 32 control codes. */
dkato 0:f782d9c66c49 750 PPPOS_PROTECT(lev);
dkato 0:f782d9c66c49 751 for (i = 0; i < 32 / 8; i++) {
dkato 0:f782d9c66c49 752 pppos->in_accm[i] = (u8_t)(accm >> (i * 8));
dkato 0:f782d9c66c49 753 }
dkato 0:f782d9c66c49 754 PPPOS_UNPROTECT(lev);
dkato 0:f782d9c66c49 755
dkato 0:f782d9c66c49 756 PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n",
dkato 0:f782d9c66c49 757 pppos->ppp->netif->num,
dkato 0:f782d9c66c49 758 pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3]));
dkato 0:f782d9c66c49 759 }
dkato 0:f782d9c66c49 760
dkato 0:f782d9c66c49 761 /*
dkato 0:f782d9c66c49 762 * Drop the input packet.
dkato 0:f782d9c66c49 763 */
dkato 0:f782d9c66c49 764 static void
dkato 0:f782d9c66c49 765 pppos_input_free_current_packet(pppos_pcb *pppos)
dkato 0:f782d9c66c49 766 {
dkato 0:f782d9c66c49 767 if (pppos->in_head != NULL) {
dkato 0:f782d9c66c49 768 if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) {
dkato 0:f782d9c66c49 769 pbuf_free(pppos->in_tail);
dkato 0:f782d9c66c49 770 }
dkato 0:f782d9c66c49 771 pbuf_free(pppos->in_head);
dkato 0:f782d9c66c49 772 pppos->in_head = NULL;
dkato 0:f782d9c66c49 773 }
dkato 0:f782d9c66c49 774 pppos->in_tail = NULL;
dkato 0:f782d9c66c49 775 }
dkato 0:f782d9c66c49 776
dkato 0:f782d9c66c49 777 /*
dkato 0:f782d9c66c49 778 * Drop the input packet and increase error counters.
dkato 0:f782d9c66c49 779 */
dkato 0:f782d9c66c49 780 static void
dkato 0:f782d9c66c49 781 pppos_input_drop(pppos_pcb *pppos)
dkato 0:f782d9c66c49 782 {
dkato 0:f782d9c66c49 783 if (pppos->in_head != NULL) {
dkato 0:f782d9c66c49 784 #if 0
dkato 0:f782d9c66c49 785 PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload));
dkato 0:f782d9c66c49 786 #endif
dkato 0:f782d9c66c49 787 PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head));
dkato 0:f782d9c66c49 788 }
dkato 0:f782d9c66c49 789 pppos_input_free_current_packet(pppos);
dkato 0:f782d9c66c49 790 #if VJ_SUPPORT
dkato 0:f782d9c66c49 791 vj_uncompress_err(&pppos->ppp->vj_comp);
dkato 0:f782d9c66c49 792 #endif /* VJ_SUPPORT */
dkato 0:f782d9c66c49 793
dkato 0:f782d9c66c49 794 LINK_STATS_INC(link.drop);
dkato 0:f782d9c66c49 795 MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards);
dkato 0:f782d9c66c49 796 }
dkato 0:f782d9c66c49 797
dkato 0:f782d9c66c49 798 /*
dkato 0:f782d9c66c49 799 * pppos_output_append - append given character to end of given pbuf.
dkato 0:f782d9c66c49 800 * If out_accm is not 0 and the character needs to be escaped, do so.
dkato 0:f782d9c66c49 801 * If pbuf is full, send the pbuf and reuse it.
dkato 0:f782d9c66c49 802 * Return the current pbuf.
dkato 0:f782d9c66c49 803 */
dkato 0:f782d9c66c49 804 static err_t
dkato 0:f782d9c66c49 805 pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs)
dkato 0:f782d9c66c49 806 {
dkato 0:f782d9c66c49 807 if (err != ERR_OK) {
dkato 0:f782d9c66c49 808 return err;
dkato 0:f782d9c66c49 809 }
dkato 0:f782d9c66c49 810
dkato 0:f782d9c66c49 811 /* Make sure there is room for the character and an escape code.
dkato 0:f782d9c66c49 812 * Sure we don't quite fill the buffer if the character doesn't
dkato 0:f782d9c66c49 813 * get escaped but is one character worth complicating this? */
dkato 0:f782d9c66c49 814 if ((PBUF_POOL_BUFSIZE - nb->len) < 2) {
dkato 0:f782d9c66c49 815 u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb);
dkato 0:f782d9c66c49 816 if (l != nb->len) {
dkato 0:f782d9c66c49 817 return ERR_IF;
dkato 0:f782d9c66c49 818 }
dkato 0:f782d9c66c49 819 nb->len = 0;
dkato 0:f782d9c66c49 820 }
dkato 0:f782d9c66c49 821
dkato 0:f782d9c66c49 822 /* Update FCS before checking for special characters. */
dkato 0:f782d9c66c49 823 if (fcs) {
dkato 0:f782d9c66c49 824 *fcs = PPP_FCS(*fcs, c);
dkato 0:f782d9c66c49 825 }
dkato 0:f782d9c66c49 826
dkato 0:f782d9c66c49 827 /* Copy to output buffer escaping special characters. */
dkato 0:f782d9c66c49 828 if (accm && ESCAPE_P(pppos->out_accm, c)) {
dkato 0:f782d9c66c49 829 *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE;
dkato 0:f782d9c66c49 830 *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS;
dkato 0:f782d9c66c49 831 } else {
dkato 0:f782d9c66c49 832 *((u8_t*)nb->payload + nb->len++) = c;
dkato 0:f782d9c66c49 833 }
dkato 0:f782d9c66c49 834
dkato 0:f782d9c66c49 835 return ERR_OK;
dkato 0:f782d9c66c49 836 }
dkato 0:f782d9c66c49 837
dkato 0:f782d9c66c49 838 static err_t
dkato 0:f782d9c66c49 839 pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs)
dkato 0:f782d9c66c49 840 {
dkato 0:f782d9c66c49 841 ppp_pcb *ppp = pppos->ppp;
dkato 0:f782d9c66c49 842
dkato 0:f782d9c66c49 843 /* Add FCS and trailing flag. */
dkato 0:f782d9c66c49 844 err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL);
dkato 0:f782d9c66c49 845 err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL);
dkato 0:f782d9c66c49 846 err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL);
dkato 0:f782d9c66c49 847
dkato 0:f782d9c66c49 848 if (err != ERR_OK) {
dkato 0:f782d9c66c49 849 goto failed;
dkato 0:f782d9c66c49 850 }
dkato 0:f782d9c66c49 851
dkato 0:f782d9c66c49 852 /* Send remaining buffer if not empty */
dkato 0:f782d9c66c49 853 if (nb->len > 0) {
dkato 0:f782d9c66c49 854 u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb);
dkato 0:f782d9c66c49 855 if (l != nb->len) {
dkato 0:f782d9c66c49 856 err = ERR_IF;
dkato 0:f782d9c66c49 857 goto failed;
dkato 0:f782d9c66c49 858 }
dkato 0:f782d9c66c49 859 }
dkato 0:f782d9c66c49 860
dkato 0:f782d9c66c49 861 pppos->last_xmit = sys_now();
dkato 0:f782d9c66c49 862 MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len);
dkato 0:f782d9c66c49 863 MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts);
dkato 0:f782d9c66c49 864 LINK_STATS_INC(link.xmit);
dkato 0:f782d9c66c49 865 pbuf_free(nb);
dkato 0:f782d9c66c49 866 return ERR_OK;
dkato 0:f782d9c66c49 867
dkato 0:f782d9c66c49 868 failed:
dkato 0:f782d9c66c49 869 pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */
dkato 0:f782d9c66c49 870 LINK_STATS_INC(link.err);
dkato 0:f782d9c66c49 871 LINK_STATS_INC(link.drop);
dkato 0:f782d9c66c49 872 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
dkato 0:f782d9c66c49 873 pbuf_free(nb);
dkato 0:f782d9c66c49 874 return err;
dkato 0:f782d9c66c49 875 }
dkato 0:f782d9c66c49 876
dkato 0:f782d9c66c49 877 #endif /* PPP_SUPPORT && PPPOS_SUPPORT */