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 45 LWIP_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 */ 57 static err_t 58 pppapi_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 */ 72 err_t 73 pppapi_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 */ 90 static err_t 91 pppapi_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 */ 105 err_t 106 pppapi_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 */ 125 static err_t 126 pppapi_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 */ 141 ppp_pcb* 142 pppapi_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 */ 166 static err_t 167 pppapi_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 */ 183 ppp_pcb* 184 pppapi_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 */ 211 static err_t 212 pppapi_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 */ 235 ppp_pcb* 236 pppapi_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 */ 270 static err_t 271 pppapi_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 */ 284 err_t 285 pppapi_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 */ 303 static err_t 304 pppapi_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 */ 317 err_t 318 pppapi_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 */ 335 static err_t 336 pppapi_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 */ 349 err_t 350 pppapi_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 */ 367 static err_t 368 pppapi_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 */ 381 err_t 382 pppapi_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 */ 398 static err_t 399 pppapi_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 */ 412 err_t 413 pppapi_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