ESP8266-based WiFi serial modem emulator ROM
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

PPP: Add PPP support with "ATDT PPP"

Static server and client IPs can be configured with AT$PPPS= and
AT$PPPC=, defaulting to 10.10.10.10 and 10.10.10.20.

+300 -26
+195
ppp.cpp
··· 1 + /* 2 + * WiFiPPP 3 + * Copyright (c) 2021 joshua stein <jcs@jcs.org> 4 + * 5 + * Permission to use, copy, modify, and distribute this software for any 6 + * purpose with or without fee is hereby granted, provided that the above 7 + * copyright notice and this permission notice appear in all copies. 8 + * 9 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 + */ 17 + 18 + #include <lwip/napt.h> 19 + #include <lwip/netif.h> 20 + #include <netif/ppp/ppp.h> 21 + #include <netif/ppp/pppos.h> 22 + 23 + #include "wifippp.h" 24 + 25 + #define PPP_BUF_SIZE 128 26 + static uint8_t ppp_buf[PPP_BUF_SIZE]; 27 + static struct netif ppp_netif; 28 + static ppp_pcb *_ppp = NULL; 29 + 30 + u32_t ppp_output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); 31 + void ppp_status_cb(ppp_pcb* pcb, int err_code, void *ctx); 32 + void ppp_setup_nat(struct netif *nif); 33 + 34 + bool 35 + ppp_start(void) 36 + { 37 + ip4_addr_t s_addr, c_addr; 38 + 39 + _ppp = pppos_create(&ppp_netif, ppp_output_cb, ppp_status_cb, nullptr); 40 + if (!_ppp) { 41 + syslog.log(LOG_ERR, "pppos_create failed"); 42 + return false; 43 + } 44 + 45 + ip_addr_copy(s_addr, settings->ppp_server_ip); 46 + ip_addr_copy(c_addr, settings->ppp_client_ip); 47 + 48 + ppp_set_ipcp_ouraddr(_ppp, &s_addr); 49 + ppp_set_ipcp_hisaddr(_ppp, &c_addr); /* or hers! */ 50 + 51 + outputf("CONNECT %d %s:PPP\r\n", settings->baud, ipaddr_ntoa(&s_addr)); 52 + 53 + ppp_listen(_ppp); 54 + 55 + syslog.log(LOG_INFO, "starting PPP negotiation"); 56 + 57 + return true; 58 + } 59 + 60 + u32_t 61 + ppp_output_cb(__attribute__((unused)) ppp_pcb *pcb, u8_t *data, u32_t len, 62 + __attribute__((unused)) void *ctx) 63 + { 64 + return Serial.write(data, len); 65 + } 66 + 67 + void 68 + ppp_process(void) 69 + { 70 + size_t bytes; 71 + 72 + if (state != STATE_PPP) { 73 + syslog.logf(LOG_ERR, "%s but state is %d!", __func__, state); 74 + return; 75 + } 76 + 77 + bytes = Serial.available(); 78 + if (!bytes) 79 + return; 80 + 81 + if (bytes > PPP_BUF_SIZE) 82 + bytes = PPP_BUF_SIZE; 83 + 84 + bytes = Serial.readBytes(ppp_buf, bytes); 85 + pppos_input(_ppp, ppp_buf, bytes); 86 + } 87 + 88 + void 89 + ppp_status_cb(ppp_pcb *pcb, int err, __attribute__((unused)) void *ctx) 90 + { 91 + struct netif *nif = ppp_netif(pcb); 92 + 93 + switch (err) { 94 + case PPPERR_NONE: 95 + syslog.log(LOG_DEBUG, "PPP session established"); 96 + ppp_setup_nat(nif); 97 + break; 98 + case PPPERR_PARAM: 99 + /* Invalid parameter. */ 100 + syslog.logf(LOG_ERR, "%s: PPPERR_PARAM", __func__); 101 + break; 102 + case PPPERR_OPEN: 103 + /* Unable to open PPP session. */ 104 + syslog.logf(LOG_ERR, "%s: PPPERR_OPEN", __func__); 105 + break; 106 + case PPPERR_DEVICE: 107 + /* Invalid I/O device for PPP. */ 108 + syslog.logf(LOG_ERR, "%s: PPPERR_DEVICE", __func__); 109 + break; 110 + case PPPERR_ALLOC: 111 + /* Unable to allocate resources. */ 112 + syslog.logf(LOG_ERR, "%s: PPPERR_ALLOC", __func__); 113 + break; 114 + case PPPERR_USER: 115 + /* User interrupt. */ 116 + syslog.logf(LOG_ERR, "%s: PPPERR_USER", __func__); 117 + break; 118 + case PPPERR_CONNECT: 119 + /* Connection lost. */ 120 + syslog.logf(LOG_ERR, "%s: PPPERR_CONNECT", __func__); 121 + break; 122 + case PPPERR_AUTHFAIL: 123 + /* Failed authentication challenge. */ 124 + syslog.logf(LOG_ERR, "%s: PPPERR_AUTHFAIL", __func__); 125 + break; 126 + case PPPERR_PROTOCOL: 127 + /* Failed to meet protocol. */ 128 + syslog.logf(LOG_ERR, "%s: PPPERR_PROTOCOL", __func__); 129 + break; 130 + case PPPERR_PEERDEAD: 131 + /* Connection timeout. */ 132 + syslog.logf(LOG_ERR, "%s: PPPERR_PEERDEAD", __func__); 133 + break; 134 + case PPPERR_IDLETIMEOUT: 135 + /* Idle Timeout. */ 136 + syslog.logf(LOG_ERR, "%s: PPPERR_IDLETIMEOUT", __func__); 137 + break; 138 + case PPPERR_CONNECTTIME: 139 + /* Max connect time reached. */ 140 + syslog.logf(LOG_ERR, "%s: PPPERR_CONNECTTIME", __func__); 141 + break; 142 + case PPPERR_LOOPBACK: 143 + /* Connection timeout. */ 144 + syslog.logf(LOG_ERR, "%s: PPPERR_LOOPBACK", __func__); 145 + break; 146 + default: 147 + syslog.logf(LOG_ERR, "%s: unknown error %d", __func__, err); 148 + break; 149 + } 150 + 151 + if (err == PPPERR_NONE) 152 + return; 153 + 154 + if (err == PPPERR_USER) { 155 + syslog.log(LOG_DEBUG, "ending PPP session, " 156 + "returning to AT mode"); 157 + ppp_free(_ppp); 158 + _ppp = NULL; 159 + state = STATE_AT; 160 + outputf("\r\nNO CARRIER\r\n"); 161 + return; 162 + } 163 + 164 + syslog.log(LOG_DEBUG, "closing PPP session"); 165 + ppp_close(_ppp, 0); 166 + } 167 + 168 + void 169 + ppp_setup_nat(struct netif *nif) 170 + { 171 + err_t ret = ip_napt_init(IP_NAPT_MAX, IP_PORTMAP_MAX); 172 + if (ret == ERR_BUF) { 173 + /* already initialized */ 174 + } else if (ret != ERR_OK) { 175 + syslog.logf(LOG_ERR, "NAPT initialization failed (%d)", 176 + (int)ret); 177 + return; 178 + } 179 + 180 + ret = ip_napt_enable_no(nif->num, 1); 181 + if (ret != ERR_OK) { 182 + syslog.logf(LOG_INFO, "ip_napt_enable(%d) failed: %d", 183 + nif->num, (int)ret); 184 + return; 185 + } 186 + 187 + /* forward port 22 on esp8266 to our client's PPP address */ 188 + ret = ip_portmap_add(IP_PROTO_TCP, WiFi.localIP(), 22, 189 + ip_2_ip4(&nif->gw)->addr, 22); 190 + if (ret != 1) { 191 + syslog.logf(LOG_ERR, "failed setting up NAPT portmap: %d", 192 + (int)ret); 193 + return; 194 + } 195 + }
+7 -1
util.cpp
··· 56 56 settings->telnet_tts_h = 15; 57 57 58 58 memset(settings->bookmarks, 0, BOOKMARK_SIZE * NUM_BOOKMARKS); 59 - strcpy(settings->bookmarks[0], "klud.ge"); 59 + strlcpy(settings->bookmarks[0], "klud.ge", 60 + sizeof(settings->bookmarks[0])); 61 + 62 + IP4_ADDR(&settings->ppp_server_ip, 10, 10, 10, 10); 63 + IP4_ADDR(&settings->ppp_client_ip, 10, 10, 10, 20); 60 64 61 65 EEPROM.commit(); 62 66 } ··· 85 89 syslog.server(settings->syslog_server, 514); 86 90 else 87 91 syslog.server(NULL, 514); 92 + 93 + syslog.appName("WiFiPPP"); 88 94 } 89 95 90 96 void
+26 -13
wifippp.h
··· 43 43 #define NUM_BOOKMARKS 3 44 44 char bookmarks[NUM_BOOKMARKS][BOOKMARK_SIZE]; 45 45 char syslog_server[64]; 46 + ip4_addr_t ppp_server_ip; 47 + ip4_addr_t ppp_client_ip; 46 48 }; 47 49 50 + enum { 51 + STATE_AT, 52 + STATE_TELNET, 53 + STATE_PPP, 54 + }; 55 + 56 + extern uint8_t state; 48 57 extern struct eeprom_data *settings; 49 58 extern Syslog syslog; 50 59 ··· 53 62 /* ESP8266 pins */ 54 63 const int pBlueLED = 16; 55 64 56 - /* wifippp.ino */ 57 - void exec_cmd(char *cmd, size_t len); 58 - extern bool serial_alive; 65 + /* ppp.cpp */ 66 + bool ppp_start(void); 67 + void ppp_process(void); 68 + 69 + /* telnet.cpp */ 70 + int telnet_connect(char *host, uint16_t port); 71 + bool telnet_connected(void); 72 + void telnet_disconnect(void); 73 + int telnet_read(void); 74 + int telnet_write(char b); 75 + int telnet_write(String s); 76 + 77 + /* update.cpp */ 78 + void update_process(bool do_update, bool force); 59 79 60 80 /* util.cpp */ 61 81 void syslog_setup(void); ··· 67 87 int output(const char *str); 68 88 int output(String str); 69 89 70 - /* telnet.cpp */ 71 - int telnet_connect(char *host, uint16_t port); 72 - bool telnet_connected(void); 73 - void telnet_disconnect(void); 74 - int telnet_read(void); 75 - int telnet_write(char b); 76 - int telnet_write(String s); 77 - 78 - /* update.cpp */ 79 - void update_process(bool do_update, bool force); 90 + /* wifippp.ino */ 91 + void exec_cmd(char *cmd, size_t len); 92 + extern bool serial_alive; 80 93 81 94 #endif
+72 -12
wifippp.ino
··· 17 17 18 18 #include "wifippp.h" 19 19 20 - enum { 21 - STATE_AT, 22 - STATE_TELNET, 23 - }; 20 + uint8_t state = STATE_AT; 24 21 25 22 static char curcmd[128] = { 0 }; 26 23 static char lastcmd[128] = { 0 }; 27 24 static unsigned int curcmdlen = 0; 28 25 static unsigned int lastcmdlen = 0; 29 - static uint8_t state = STATE_AT; 30 26 static int plusses = 0; 31 27 static unsigned long plus_wait = 0; 32 28 ··· 141 137 break; 142 138 } 143 139 break; 140 + case STATE_PPP: 141 + ppp_process(); 142 + break; 144 143 } 145 144 } 146 145 ··· 246 245 goto error; 247 246 } 248 247 249 - outputf("DIALING %s:%d\r\n", host, port); 248 + if (strcasecmp(host, "ppp") == 0) { 249 + ip4_addr_t t_addr; 250 + ip_addr_copy(t_addr, settings->ppp_server_ip); 251 + outputf("DIALING %s:PPP\r\n", ipaddr_ntoa(&t_addr)); 250 252 251 - if (telnet_connect(host, port) == 0) { 252 - outputf("CONNECT %d %s:%d\r\n", settings->baud, host, 253 - port); 254 - state = STATE_TELNET; 253 + telnet_disconnect(); 254 + if (ppp_start()) { 255 + /* ppp_start outputs CONNECT line, since it has 256 + * to do so before calling ppp_listen */ 257 + state = STATE_PPP; 258 + } else { 259 + output("NO ANSWER\r\n"); 260 + } 255 261 } else { 256 - output("NO ANSWER\r\n"); 262 + outputf("DIALING %s:%d\r\n", host, port); 263 + 264 + if (telnet_connect(host, port) == 0) { 265 + outputf("CONNECT %d %s:%d\r\n", settings->baud, 266 + host, port); 267 + state = STATE_TELNET; 268 + } else 269 + output("NO ANSWER\r\n"); 257 270 } 258 271 259 272 free(ohost); ··· 269 282 goto error; 270 283 271 284 switch (len == 3 ? '0' : cmd[3]) { 272 - case '0': 285 + case '0': { 273 286 /* ATI or ATI0: show settings */ 287 + ip4_addr_t t_addr; 288 + 274 289 outputf("Firmware version: %s\r\n", 275 290 WIFISTATION_VERSION); 291 + 276 292 outputf("Serial baud rate: %d\r\n", 277 293 settings->baud); 294 + 278 295 outputf("Default WiFi SSID: %s\r\n", 279 296 settings->wifi_ssid); 280 297 outputf("Current WiFi SSID: %s\r\n", WiFi.SSID()); ··· 288 305 outputf("DNS server IP: %s\r\n", 289 306 WiFi.dnsIP().toString().c_str()); 290 307 } 308 + 309 + ip_addr_copy(t_addr, settings->ppp_server_ip); 310 + outputf("PPP server: %s\r\n", 311 + ipaddr_ntoa(&t_addr)); 312 + ip_addr_copy(t_addr, settings->ppp_client_ip); 313 + outputf("PPP client: %s\r\n", 314 + ipaddr_ntoa(&t_addr)); 315 + 291 316 outputf("Syslog server: %s\r\n", 292 317 settings->syslog_server); 318 + 293 319 for (int i = 0; i < NUM_BOOKMARKS; i++) { 294 320 if (settings->bookmarks[i][0] != '\0') 295 321 outputf("ATDS bookmark %d: %s\r\n", 296 322 i + 1, settings->bookmarks[i]); 297 323 } 324 + 298 325 output("OK\r\n"); 299 326 break; 327 + } 300 328 case '1': { 301 329 /* ATI1: scan for wifi networks */ 302 330 int n = WiFi.scanNetworks(); ··· 381 409 } else if (strcmp(lcmd, "at$pass?") == 0) { 382 410 /* AT$PASS?: print wep/wpa passphrase */ 383 411 outputf("%s\r\nOK\r\n", settings->wifi_pass); 412 + } else if (strncmp(lcmd, "at$pppc=", 8) == 0) { 413 + /* AT$PPPC=...: store PPP client IP */ 414 + ip4_addr_t t_addr; 415 + 416 + if (!ipaddr_aton(cmd + 8, &t_addr)) { 417 + errstr = strdup("invalid IP"); 418 + goto error; 419 + } 420 + 421 + ip_addr_copy(settings->ppp_client_ip, t_addr); 422 + output("OK\r\n"); 423 + } else if (strcmp(lcmd, "at$pppc?") == 0) { 424 + /* AT$PPPC?: print PPP client IP */ 425 + ip4_addr_t t_addr; 426 + ip_addr_copy(t_addr, settings->ppp_client_ip); 427 + outputf("%s\r\nOK\r\n", ipaddr_ntoa(&t_addr)); 428 + } else if (strncmp(lcmd, "at$ppps=", 8) == 0) { 429 + /* AT$PPPS=...: store PPP server IP */ 430 + ip4_addr_t t_addr; 431 + 432 + if (!ipaddr_aton(cmd + 8, &t_addr)) { 433 + errstr = strdup("invalid IP"); 434 + goto error; 435 + } 436 + 437 + ip_addr_copy(settings->ppp_server_ip, t_addr); 438 + output("OK\r\n"); 439 + } else if (strcmp(lcmd, "at$ppps?") == 0) { 440 + /* AT$PPPS?: print PPP server IP */ 441 + ip4_addr_t t_addr; 442 + ip_addr_copy(t_addr, settings->ppp_server_ip); 443 + outputf("%s\r\nOK\r\n", ipaddr_ntoa(&t_addr)); 384 444 } else if (strncmp(lcmd, "at$sb=", 6) == 0) { 385 445 uint32_t baud = 0; 386 446 int chars = 0;