1/** 2 * @file 3 * Point To Point Protocol Sequential API module 4 * 5 */ 6 7/* 8 * Redistribution and use in source and binary forms, with or without modification, 9 * are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 28 * OF SUCH DAMAGE. 29 * 30 * This file is part of the lwIP TCP/IP stack. 31 * 32 */ 33 34#include "netif/ppp/ppp_opts.h" 35 36#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ 37 38#include "netif/ppp/pppapi.h" 39#include "lwip/priv/tcpip_priv.h" 40#include "netif/ppp/pppoe.h" 41#include "netif/ppp/pppol2tp.h" 42#include "netif/ppp/pppos.h" 43 44#if LWIP_MPU_COMPATIBLE 45LWIP_MEMPOOL_DECLARE(PPPAPI_MSG, MEMP_NUM_PPP_API_MSG, sizeof(struct pppapi_msg), "PPPAPI_MSG") 46#endif 47 48#define PPPAPI_VAR_REF(name) API_VAR_REF(name) 49#define PPPAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct pppapi_msg, name) 50#define PPPAPI_VAR_ALLOC(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, ERR_MEM) 51#define PPPAPI_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, NULL) 52#define PPPAPI_VAR_FREE(name) API_VAR_FREE_POOL(PPPAPI_MSG, name) 53 54/** 55 * Call ppp_set_default() inside the tcpip_thread context. 56 */ 57static err_t 58pppapi_do_ppp_set_default(struct tcpip_api_call_data *m) 59{ 60 /* cast through void* to silence alignment warnings. 61 * We know it works because the structs have been instantiated as struct pppapi_msg */ 62 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 63 64 ppp_set_default(msg->msg.ppp); 65 return ERR_OK; 66} 67 68/** 69 * Call ppp_set_default() in a thread-safe way by running that function inside the 70 * tcpip_thread context. 71 */ 72err_t 73pppapi_set_default(ppp_pcb *pcb) 74{ 75 err_t err; 76 PPPAPI_VAR_DECLARE(msg); 77 PPPAPI_VAR_ALLOC(msg); 78 79 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 80 err = tcpip_api_call(pppapi_do_ppp_set_default, &PPPAPI_VAR_REF(msg).call); 81 PPPAPI_VAR_FREE(msg); 82 return err; 83} 84 85 86#if PPP_NOTIFY_PHASE 87/** 88 * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. 89 */ 90static err_t 91pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call_data *m) 92{ 93 /* cast through void* to silence alignment warnings. 94 * We know it works because the structs have been instantiated as struct pppapi_msg */ 95 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 96 97 ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); 98 return ERR_OK; 99} 100 101/** 102 * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the 103 * tcpip_thread context. 104 */ 105err_t 106pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) 107{ 108 err_t err; 109 PPPAPI_VAR_DECLARE(msg); 110 PPPAPI_VAR_ALLOC(msg); 111 112 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 113 PPPAPI_VAR_REF(msg).msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; 114 err = tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &PPPAPI_VAR_REF(msg).call); 115 PPPAPI_VAR_FREE(msg); 116 return err; 117} 118#endif /* PPP_NOTIFY_PHASE */ 119 120 121#if PPPOS_SUPPORT 122/** 123 * Call pppos_create() inside the tcpip_thread context. 124 */ 125static err_t 126pppapi_do_pppos_create(struct tcpip_api_call_data *m) 127{ 128 /* cast through void* to silence alignment warnings. 129 * We know it works because the structs have been instantiated as struct pppapi_msg */ 130 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 131 132 msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, 133 msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); 134 return ERR_OK; 135} 136 137/** 138 * Call pppos_create() in a thread-safe way by running that function inside the 139 * tcpip_thread context. 140 */ 141ppp_pcb* 142pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, 143 ppp_link_status_cb_fn link_status_cb, void *ctx_cb) 144{ 145 ppp_pcb* result; 146 PPPAPI_VAR_DECLARE(msg); 147 PPPAPI_VAR_ALLOC_RETURN_NULL(msg); 148 149 PPPAPI_VAR_REF(msg).msg.ppp = NULL; 150 PPPAPI_VAR_REF(msg).msg.msg.serialcreate.pppif = pppif; 151 PPPAPI_VAR_REF(msg).msg.msg.serialcreate.output_cb = output_cb; 152 PPPAPI_VAR_REF(msg).msg.msg.serialcreate.link_status_cb = link_status_cb; 153 PPPAPI_VAR_REF(msg).msg.msg.serialcreate.ctx_cb = ctx_cb; 154 tcpip_api_call(pppapi_do_pppos_create, &PPPAPI_VAR_REF(msg).call); 155 result = PPPAPI_VAR_REF(msg).msg.ppp; 156 PPPAPI_VAR_FREE(msg); 157 return result; 158} 159#endif /* PPPOS_SUPPORT */ 160 161 162#if PPPOE_SUPPORT 163/** 164 * Call pppoe_create() inside the tcpip_thread context. 165 */ 166static err_t 167pppapi_do_pppoe_create(struct tcpip_api_call_data *m) 168{ 169 /* cast through void* to silence alignment warnings. 170 * We know it works because the structs have been instantiated as struct pppapi_msg */ 171 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 172 173 msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, 174 msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, 175 msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); 176 return ERR_OK; 177} 178 179/** 180 * Call pppoe_create() in a thread-safe way by running that function inside the 181 * tcpip_thread context. 182 */ 183ppp_pcb* 184pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, 185 const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, 186 void *ctx_cb) 187{ 188 ppp_pcb* result; 189 PPPAPI_VAR_DECLARE(msg); 190 PPPAPI_VAR_ALLOC_RETURN_NULL(msg); 191 192 PPPAPI_VAR_REF(msg).msg.ppp = NULL; 193 PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.pppif = pppif; 194 PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ethif = ethif; 195 PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.service_name = service_name; 196 PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.concentrator_name = concentrator_name; 197 PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.link_status_cb = link_status_cb; 198 PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ctx_cb = ctx_cb; 199 tcpip_api_call(pppapi_do_pppoe_create, &PPPAPI_VAR_REF(msg).call); 200 result = PPPAPI_VAR_REF(msg).msg.ppp; 201 PPPAPI_VAR_FREE(msg); 202 return result; 203} 204#endif /* PPPOE_SUPPORT */ 205 206 207#if PPPOL2TP_SUPPORT 208/** 209 * Call pppol2tp_create() inside the tcpip_thread context. 210 */ 211static err_t 212pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m) 213{ 214 /* cast through void* to silence alignment warnings. 215 * We know it works because the structs have been instantiated as struct pppapi_msg */ 216 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 217 218 msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, 219 msg->msg.msg.l2tpcreate.netif, API_EXPR_REF(msg->msg.msg.l2tpcreate.ipaddr), msg->msg.msg.l2tpcreate.port, 220#if PPPOL2TP_AUTH_SUPPORT 221 msg->msg.msg.l2tpcreate.secret, 222 msg->msg.msg.l2tpcreate.secret_len, 223#else /* PPPOL2TP_AUTH_SUPPORT */ 224 NULL, 225 0, 226#endif /* PPPOL2TP_AUTH_SUPPORT */ 227 msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); 228 return ERR_OK; 229} 230 231/** 232 * Call pppol2tp_create() in a thread-safe way by running that function inside the 233 * tcpip_thread context. 234 */ 235ppp_pcb* 236pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, 237 const u8_t *secret, u8_t secret_len, 238 ppp_link_status_cb_fn link_status_cb, void *ctx_cb) 239{ 240 ppp_pcb* result; 241 PPPAPI_VAR_DECLARE(msg); 242 PPPAPI_VAR_ALLOC_RETURN_NULL(msg); 243#if !PPPOL2TP_AUTH_SUPPORT 244 LWIP_UNUSED_ARG(secret); 245 LWIP_UNUSED_ARG(secret_len); 246#endif /* !PPPOL2TP_AUTH_SUPPORT */ 247 248 PPPAPI_VAR_REF(msg).msg.ppp = NULL; 249 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif; 250 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.netif = netif; 251 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ipaddr = PPPAPI_VAR_REF(ipaddr); 252 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.port = port; 253#if PPPOL2TP_AUTH_SUPPORT 254 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret = secret; 255 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret_len = secret_len; 256#endif /* PPPOL2TP_AUTH_SUPPORT */ 257 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.link_status_cb = link_status_cb; 258 PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ctx_cb = ctx_cb; 259 tcpip_api_call(pppapi_do_pppol2tp_create, &PPPAPI_VAR_REF(msg).call); 260 result = PPPAPI_VAR_REF(msg).msg.ppp; 261 PPPAPI_VAR_FREE(msg); 262 return result; 263} 264#endif /* PPPOL2TP_SUPPORT */ 265 266 267/** 268 * Call ppp_connect() inside the tcpip_thread context. 269 */ 270static err_t 271pppapi_do_ppp_connect(struct tcpip_api_call_data *m) 272{ 273 /* cast through void* to silence alignment warnings. 274 * We know it works because the structs have been instantiated as struct pppapi_msg */ 275 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 276 277 return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); 278} 279 280/** 281 * Call ppp_connect() in a thread-safe way by running that function inside the 282 * tcpip_thread context. 283 */ 284err_t 285pppapi_connect(ppp_pcb *pcb, u16_t holdoff) 286{ 287 err_t err; 288 PPPAPI_VAR_DECLARE(msg); 289 PPPAPI_VAR_ALLOC(msg); 290 291 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 292 PPPAPI_VAR_REF(msg).msg.msg.connect.holdoff = holdoff; 293 err = tcpip_api_call(pppapi_do_ppp_connect, &PPPAPI_VAR_REF(msg).call); 294 PPPAPI_VAR_FREE(msg); 295 return err; 296} 297 298 299#if PPP_SERVER 300/** 301 * Call ppp_listen() inside the tcpip_thread context. 302 */ 303static err_t 304pppapi_do_ppp_listen(struct tcpip_api_call_data *m) 305{ 306 /* cast through void* to silence alignment warnings. 307 * We know it works because the structs have been instantiated as struct pppapi_msg */ 308 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 309 310 return ppp_listen(msg->msg.ppp); 311} 312 313/** 314 * Call ppp_listen() in a thread-safe way by running that function inside the 315 * tcpip_thread context. 316 */ 317err_t 318pppapi_listen(ppp_pcb *pcb) 319{ 320 err_t err; 321 PPPAPI_VAR_DECLARE(msg); 322 PPPAPI_VAR_ALLOC(msg); 323 324 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 325 err = tcpip_api_call(pppapi_do_ppp_listen, &PPPAPI_VAR_REF(msg).call); 326 PPPAPI_VAR_FREE(msg); 327 return err; 328} 329#endif /* PPP_SERVER */ 330 331 332/** 333 * Call ppp_close() inside the tcpip_thread context. 334 */ 335static err_t 336pppapi_do_ppp_close(struct tcpip_api_call_data *m) 337{ 338 /* cast through void* to silence alignment warnings. 339 * We know it works because the structs have been instantiated as struct pppapi_msg */ 340 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 341 342 return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); 343} 344 345/** 346 * Call ppp_close() in a thread-safe way by running that function inside the 347 * tcpip_thread context. 348 */ 349err_t 350pppapi_close(ppp_pcb *pcb, u8_t nocarrier) 351{ 352 err_t err; 353 PPPAPI_VAR_DECLARE(msg); 354 PPPAPI_VAR_ALLOC(msg); 355 356 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 357 PPPAPI_VAR_REF(msg).msg.msg.close.nocarrier = nocarrier; 358 err = tcpip_api_call(pppapi_do_ppp_close, &PPPAPI_VAR_REF(msg).call); 359 PPPAPI_VAR_FREE(msg); 360 return err; 361} 362 363 364/** 365 * Call ppp_free() inside the tcpip_thread context. 366 */ 367static err_t 368pppapi_do_ppp_free(struct tcpip_api_call_data *m) 369{ 370 /* cast through void* to silence alignment warnings. 371 * We know it works because the structs have been instantiated as struct pppapi_msg */ 372 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 373 374 return ppp_free(msg->msg.ppp); 375} 376 377/** 378 * Call ppp_free() in a thread-safe way by running that function inside the 379 * tcpip_thread context. 380 */ 381err_t 382pppapi_free(ppp_pcb *pcb) 383{ 384 err_t err; 385 PPPAPI_VAR_DECLARE(msg); 386 PPPAPI_VAR_ALLOC(msg); 387 388 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 389 err = tcpip_api_call(pppapi_do_ppp_free, &PPPAPI_VAR_REF(msg).call); 390 PPPAPI_VAR_FREE(msg); 391 return err; 392} 393 394 395/** 396 * Call ppp_ioctl() inside the tcpip_thread context. 397 */ 398static err_t 399pppapi_do_ppp_ioctl(struct tcpip_api_call_data *m) 400{ 401 /* cast through void* to silence alignment warnings. 402 * We know it works because the structs have been instantiated as struct pppapi_msg */ 403 struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; 404 405 return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); 406} 407 408/** 409 * Call ppp_ioctl() in a thread-safe way by running that function inside the 410 * tcpip_thread context. 411 */ 412err_t 413pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) 414{ 415 err_t err; 416 PPPAPI_VAR_DECLARE(msg); 417 PPPAPI_VAR_ALLOC(msg); 418 419 PPPAPI_VAR_REF(msg).msg.ppp = pcb; 420 PPPAPI_VAR_REF(msg).msg.msg.ioctl.cmd = cmd; 421 PPPAPI_VAR_REF(msg).msg.msg.ioctl.arg = arg; 422 err = tcpip_api_call(pppapi_do_ppp_ioctl, &PPPAPI_VAR_REF(msg).call); 423 PPPAPI_VAR_FREE(msg); 424 return err; 425} 426 427#endif /* LWIP_PPP_API */ 428