BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 PPP interface for lwIP
2  
3 Author: Sylvain Rochet
4  
5 Table of Contents:
6  
7 1 - Supported PPP protocols and features
8 2 - Raw API PPP example for all protocols
9 3 - PPPoS input path (raw API, IRQ safe API, TCPIP API)
10 4 - Thread safe PPP API (PPPAPI)
11 5 - Notify phase callback (PPP_NOTIFY_PHASE)
12 6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
13  
14  
15  
16 1 Supported PPP protocols and features
17 ======================================
18  
19 Supported Low level protocols:
20 * PPP over serial using HDLC-like framing, such as wired dialup modems
21 or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems
22 * PPP over Ethernet, such as xDSL modems
23 * PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),
24 IP tunnel over UDP, such as VPN access
25  
26 Supported auth protocols:
27 * PAP, Password Authentication Protocol
28 * CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5
29 * MSCHAPv1, Microsoft version of CHAP, version 1
30 * MSCHAPv2, Microsoft version of CHAP, version 2
31 * EAP, Extensible Authentication Protocol
32  
33 Supported address protocols:
34 * IPCP, IP Control Protocol, IPv4 addresses negotiation
35 * IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation
36  
37 Supported encryption protocols:
38 * MPPE, Microsoft Point-to-Point Encryption
39  
40 Supported compression or miscellaneous protocols, for serial links only:
41 * PFC, Protocol Field Compression
42 * ACFC, Address-and-Control-Field-Compression
43 * ACCM, Asynchronous-Control-Character-Map
44 * VJ, Van Jacobson TCP/IP Header Compression
45  
46  
47  
48 2 Raw API PPP example for all protocols
49 =======================================
50  
51 As usual, raw API for lwIP means the lightweight API which *MUST* only be used
52 for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.
53  
54 /*
55 * Globals
56 * =======
57 */
58  
59 /* The PPP control block */
60 ppp_pcb *ppp;
61  
62 /* The PPP IP interface */
63 struct netif ppp_netif;
64  
65  
66 /*
67 * PPP status callback
68 * ===================
69 *
70 * PPP status callback is called on PPP status change (up, down, …) from lwIP
71 * core thread
72 */
73  
74 /* PPP status callback example */
75 static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
76 struct netif *pppif = ppp_netif(pcb);
77 LWIP_UNUSED_ARG(ctx);
78  
79 switch(err_code) {
80 case PPPERR_NONE: {
81 #if LWIP_DNS
82 const ip_addr_t *ns;
83 #endif /* LWIP_DNS */
84 printf("status_cb: Connected\n");
85 #if PPP_IPV4_SUPPORT
86 printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));
87 printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));
88 printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
89 #if LWIP_DNS
90 ns = dns_getserver(0);
91 printf(" dns1 = %s\n", ipaddr_ntoa(ns));
92 ns = dns_getserver(1);
93 printf(" dns2 = %s\n", ipaddr_ntoa(ns));
94 #endif /* LWIP_DNS */
95 #endif /* PPP_IPV4_SUPPORT */
96 #if PPP_IPV6_SUPPORT
97 printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
98 #endif /* PPP_IPV6_SUPPORT */
99 break;
100 }
101 case PPPERR_PARAM: {
102 printf("status_cb: Invalid parameter\n");
103 break;
104 }
105 case PPPERR_OPEN: {
106 printf("status_cb: Unable to open PPP session\n");
107 break;
108 }
109 case PPPERR_DEVICE: {
110 printf("status_cb: Invalid I/O device for PPP\n");
111 break;
112 }
113 case PPPERR_ALLOC: {
114 printf("status_cb: Unable to allocate resources\n");
115 break;
116 }
117 case PPPERR_USER: {
118 printf("status_cb: User interrupt\n");
119 break;
120 }
121 case PPPERR_CONNECT: {
122 printf("status_cb: Connection lost\n");
123 break;
124 }
125 case PPPERR_AUTHFAIL: {
126 printf("status_cb: Failed authentication challenge\n");
127 break;
128 }
129 case PPPERR_PROTOCOL: {
130 printf("status_cb: Failed to meet protocol\n");
131 break;
132 }
133 case PPPERR_PEERDEAD: {
134 printf("status_cb: Connection timeout\n");
135 break;
136 }
137 case PPPERR_IDLETIMEOUT: {
138 printf("status_cb: Idle Timeout\n");
139 break;
140 }
141 case PPPERR_CONNECTTIME: {
142 printf("status_cb: Max connect time reached\n");
143 break;
144 }
145 case PPPERR_LOOPBACK: {
146 printf("status_cb: Loopback detected\n");
147 break;
148 }
149 default: {
150 printf("status_cb: Unknown error code %d\n", err_code);
151 break;
152 }
153 }
154  
155 /*
156 * This should be in the switch case, this is put outside of the switch
157 * case for example readability.
158 */
159  
160 if (err_code == PPPERR_NONE) {
161 return;
162 }
163  
164 /* ppp_close() was previously called, don't reconnect */
165 if (err_code == PPPERR_USER) {
166 /* ppp_free(); -- can be called here */
167 return;
168 }
169  
170 /*
171 * Try to reconnect in 30 seconds, if you need a modem chatscript you have
172 * to do a much better signaling here ;-)
173 */
174 ppp_connect(pcb, 30);
175 /* OR ppp_listen(pcb); */
176 }
177  
178  
179 /*
180 * Creating a new PPPoS session
181 * ============================
182 *
183 * In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.
184 */
185  
186 #include "netif/ppp/pppos.h"
187  
188 /*
189 * PPPoS serial output callback
190 *
191 * ppp_pcb, PPP control block
192 * data, buffer to write to serial port
193 * len, length of the data buffer
194 * ctx, optional user-provided callback context pointer
195 *
196 * Return value: len if write succeed
197 */
198 static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
199 return uart_write(UART, data, len);
200 }
201  
202 /*
203 * Create a new PPPoS interface
204 *
205 * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
206 * output_cb, PPPoS serial output callback
207 * status_cb, PPP status callback, called on PPP status change (up, down, …)
208 * ctx_cb, optional user-provided callback context pointer
209 */
210 ppp = pppos_create(&ppp_netif,
211 output_cb, status_cb, ctx_cb);
212  
213  
214 /*
215 * Creating a new PPPoE session
216 * ============================
217 */
218  
219 #include "netif/ppp/pppoe.h"
220  
221 /*
222 * Create a new PPPoE interface
223 *
224 * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
225 * ethif, already existing and setup Ethernet interface to use
226 * service_name, PPPoE service name discriminator (not supported yet)
227 * concentrator_name, PPPoE concentrator name discriminator (not supported yet)
228 * status_cb, PPP status callback, called on PPP status change (up, down, …)
229 * ctx_cb, optional user-provided callback context pointer
230 */
231 ppp = pppoe_create(&ppp_netif,
232 &ethif,
233 service_name, concentrator_name,
234 status_cb, ctx_cb);
235  
236  
237 /*
238 * Creating a new PPPoL2TP session
239 * ===============================
240 */
241  
242 #include "netif/ppp/pppol2tp.h"
243  
244 /*
245 * Create a new PPPoL2TP interface
246 *
247 * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
248 * netif, optional already existing and setup output netif, necessary if you
249 * want to set this interface as default route to settle the chicken
250 * and egg problem with VPN links
251 * ipaddr, IP to connect to
252 * port, UDP port to connect to (usually 1701)
253 * secret, L2TP secret to use
254 * secret_len, size in bytes of the L2TP secret
255 * status_cb, PPP status callback, called on PPP status change (up, down, …)
256 * ctx_cb, optional user-provided callback context pointer
257 */
258 ppp = pppol2tp_create(&ppp_netif,
259 struct netif *netif, ip_addr_t *ipaddr, u16_t port,
260 u8_t *secret, u8_t secret_len,
261 ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
262  
263  
264 /*
265 * Initiate PPP client connection
266 * ==============================
267 */
268  
269 /* Set this interface as default route */
270 ppp_set_default(ppp);
271  
272 /*
273 * Basic PPP client configuration. Can only be set if PPP session is in the
274 * dead state (i.e. disconnected). We don't need to provide thread-safe
275 * equivalents through PPPAPI because those helpers are only changing
276 * structure members while session is inactive for lwIP core. Configuration
277 * only need to be done once.
278 */
279  
280 /* Ask the peer for up to 2 DNS server addresses. */
281 ppp_set_usepeerdns(ppp, 1);
282  
283 /* Auth configuration, this is pretty self-explanatory */
284 ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
285  
286 /*
287 * Initiate PPP negotiation, without waiting (holdoff=0), can only be called
288 * if PPP session is in the dead state (i.e. disconnected).
289 */
290 u16_t holdoff = 0;
291 ppp_connect(ppp, holdoff);
292  
293  
294 /*
295 * Initiate PPP server listener
296 * ============================
297 */
298  
299 /*
300 * Basic PPP server configuration. Can only be set if PPP session is in the
301 * dead state (i.e. disconnected). We don't need to provide thread-safe
302 * equivalents through PPPAPI because those helpers are only changing
303 * structure members while session is inactive for lwIP core. Configuration
304 * only need to be done once.
305 */
306 ip4_addr_t addr;
307  
308 /* Set our address */
309 IP4_ADDR(&addr, 192,168,0,1);
310 ppp_set_ipcp_ouraddr(ppp, &addr);
311  
312 /* Set peer(his) address */
313 IP4_ADDR(&addr, 192,168,0,2);
314 ppp_set_ipcp_hisaddr(ppp, &addr);
315  
316 /* Set primary DNS server */
317 IP4_ADDR(&addr, 192,168,10,20);
318 ppp_set_ipcp_dnsaddr(ppp, 0, &addr);
319  
320 /* Set secondary DNS server */
321 IP4_ADDR(&addr, 192,168,10,21);
322 ppp_set_ipcp_dnsaddr(ppp, 1, &addr);
323  
324 /* Auth configuration, this is pretty self-explanatory */
325 ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
326  
327 /* Require peer to authenticate */
328 ppp_set_auth_required(ppp, 1);
329  
330 /*
331 * Only for PPPoS, the PPP session should be up and waiting for input.
332 *
333 * Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.
334 * The listen call is meant for future support of PPPoE and PPPoL2TP server
335 * mode, where we will need to negotiate the incoming PPPoE session or L2TP
336 * session before initiating PPP itself. We need this call because there is
337 * two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.
338 */
339 ppp_set_silent(pppos, 1);
340  
341 /*
342 * Initiate PPP listener (i.e. wait for an incoming connection), can only
343 * be called if PPP session is in the dead state (i.e. disconnected).
344 */
345 ppp_listen(ppp);
346  
347  
348 /*
349 * Closing PPP connection
350 * ======================
351 */
352  
353 /*
354 * Initiate the end of the PPP session, without carrier lost signal
355 * (nocarrier=0), meaning a clean shutdown of PPP protocols.
356 * You can call this function at anytime.
357 */
358 u8_t nocarrier = 0;
359 ppp_close(ppp, nocarrier);
360 /*
361 * Then you must wait your status_cb() to be called, it may takes from a few
362 * seconds to several tens of seconds depending on the current PPP state.
363 */
364  
365 /*
366 * Freeing a PPP connection
367 * ========================
368 */
369  
370 /*
371 * Free the PPP control block, can only be called if PPP session is in the
372 * dead state (i.e. disconnected). You need to call ppp_close() before.
373 */
374 ppp_free(ppp);
375  
376  
377  
378 3 PPPoS input path (raw API, IRQ safe API, TCPIP API)
379 =====================================================
380  
381 Received data on serial port should be sent to lwIP using the pppos_input()
382 function or the pppos_input_tcpip() function.
383  
384 If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()
385 is not IRQ safe and then *MUST* only be called inside your main loop.
386  
387 Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
388 safe and can be safely called from an interrupt context, using that is going
389 to reduce your need of buffer if pppos_input() is called byte after byte in
390 your rx serial interrupt.
391  
392 if NO_SYS is 0, the thread safe way outside an interrupt context is to use
393 the pppos_input_tcpip() function to pass input data to the lwIP core thread
394 using the TCPIP API. This is thread safe in all cases but you should avoid
395 passing data byte after byte because it uses heavy locking (mailbox) and it
396 allocates pbuf, better fill them !
397  
398 if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()
399 from an RX thread, however pppos_input() is not thread safe by itself. You can
400 do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
401 ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
402 at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
403 really know what you are doing, your move ;-)
404  
405  
406 /*
407 * Fonction to call for received data
408 *
409 * ppp, PPP control block
410 * buffer, input buffer
411 * buffer_len, buffer length in bytes
412 */
413 void pppos_input(ppp, buffer, buffer_len);
414  
415 or
416  
417 void pppos_input_tcpip(ppp, buffer, buffer_len);
418  
419  
420  
421 4 Thread safe PPP API (PPPAPI)
422 ==============================
423  
424 There is a thread safe API for all corresponding ppp_* functions, you have to
425 enable LWIP_PPP_API in your lwipopts.h file, then see
426 include/netif/ppp/pppapi.h, this is actually pretty obvious.
427  
428  
429  
430 5 Notify phase callback (PPP_NOTIFY_PHASE)
431 ==========================================
432  
433 Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let
434 you configure a callback that is called on each PPP internal state change.
435 This is different from the status callback which only warns you about
436 up(running) and down(dead) events.
437  
438 Notify phase callback can be used, for example, to set a LED pattern depending
439 on the current phase of the PPP session. Here is a callback example which
440 tries to mimic what we usually see on xDSL modems while they are negotiating
441 the link, which should be self-explanatory:
442  
443 static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {
444 switch (phase) {
445  
446 /* Session is down (either permanently or briefly) */
447 case PPP_PHASE_DEAD:
448 led_set(PPP_LED, LED_OFF);
449 break;
450  
451 /* We are between two sessions */
452 case PPP_PHASE_HOLDOFF:
453 led_set(PPP_LED, LED_SLOW_BLINK);
454 break;
455  
456 /* Session just started */
457 case PPP_PHASE_INITIALIZE:
458 led_set(PPP_LED, LED_FAST_BLINK);
459 break;
460  
461 /* Session is running */
462 case PPP_PHASE_RUNNING:
463 led_set(PPP_LED, LED_ON);
464 break;
465  
466 default:
467 break;
468 }
469 }
470  
471  
472  
473 6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
474 ===============================================
475  
476 PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting
477 from previous lwIP version is pretty easy:
478  
479 * Previous PPP API used an integer to identify PPP sessions, we are now
480 using ppp_pcb* control block, therefore all functions changed from "int ppp"
481 to "ppp_pcb *ppp"
482  
483 * struct netif was moved outside the PPP structure, you have to provide a netif
484 for PPP interface in pppoX_create() functions
485  
486 * PPP session are not started automatically after you created them anymore,
487 you have to call ppp_connect(), this way you can configure the session before
488 starting it.
489  
490 * Previous PPP API used CamelCase, we are now using snake_case.
491  
492 * Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,
493 PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed
494 pppoe_, common functions are now prefixed ppp_.
495  
496 * New PPPERR_ error codes added, check you have all of them in your status
497 callback function
498  
499 * Only the following include files should now be used in user application:
500 #include "netif/ppp/pppapi.h"
501 #include "netif/ppp/pppos.h"
502 #include "netif/ppp/pppoe.h"
503 #include "netif/ppp/pppol2tp.h"
504  
505 Functions from ppp.h can be used, but you don't need to include this header
506 file as it is already included by above header files.
507  
508 * PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create
509 your own serial rx thread
510  
511 * PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed
512 PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above
513 because you might have been fooled by that
514  
515 * If you used tcpip_callback_with_block() on ppp_ functions you may wish to use
516 the PPPAPI API instead.
517  
518 * ppp_sighup and ppp_close functions were merged using an optional argument
519 "nocarrier" on ppp_close.
520  
521 * DNS servers are now only remotely asked if LWIP_DNS is set and if
522 ppp_set_usepeerdns() is set to true, they are now automatically registered
523 using the dns_setserver() function so you don't need to do that in the PPP
524 callback anymore.
525  
526 * PPPoS does not use the SIO API anymore, as such it now requires a serial
527 output callback in place of sio_write
528  
529 * PPP_MAXIDLEFLAG is now in ms instead of jiffies