Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / lwip / repo / lwip / src / netif / ppp / upap.c
1 /*
2  * upap.c - User/Password Authentication Protocol.
3  *
4  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. The name "Carnegie Mellon University" must not be used to
19  *    endorse or promote products derived from this software without
20  *    prior written permission. For permission or any legal
21  *    details, please contact
22  *      Office of Technology Transfer
23  *      Carnegie Mellon University
24  *      5000 Forbes Avenue
25  *      Pittsburgh, PA  15213-3890
26  *      (412) 268-4387, fax: (412) 268-7395
27  *      tech-transfer@andrew.cmu.edu
28  *
29  * 4. Redistributions of any form whatsoever must retain the following
30  *    acknowledgment:
31  *    "This product includes software developed by Computing Services
32  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33  *
34  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41  */
42
43 #include "netif/ppp/ppp_opts.h"
44 #if PPP_SUPPORT && PAP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
45
46 /*
47  * @todo:
48  */
49
50 #if 0 /* UNUSED */
51 #include <stdio.h>
52 #include <string.h>
53 #endif /* UNUSED */
54
55 #include "netif/ppp/ppp_impl.h"
56
57 #include "netif/ppp/upap.h"
58
59 #if PPP_OPTIONS
60 /*
61  * Command-line options.
62  */
63 static option_t pap_option_list[] = {
64     { "hide-password", o_bool, &hide_password,
65       "Don't output passwords to log", OPT_PRIO | 1 },
66     { "show-password", o_bool, &hide_password,
67       "Show password string in debug log messages", OPT_PRIOSUB | 0 },
68
69     { "pap-restart", o_int, &upap[0].us_timeouttime,
70       "Set retransmit timeout for PAP", OPT_PRIO },
71     { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
72       "Set max number of transmissions for auth-reqs", OPT_PRIO },
73     { "pap-timeout", o_int, &upap[0].us_reqtimeout,
74       "Set time limit for peer PAP authentication", OPT_PRIO },
75
76     { NULL }
77 };
78 #endif /* PPP_OPTIONS */
79
80 /*
81  * Protocol entry points.
82  */
83 static void upap_init(ppp_pcb *pcb);
84 static void upap_lowerup(ppp_pcb *pcb);
85 static void upap_lowerdown(ppp_pcb *pcb);
86 static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l);
87 static void upap_protrej(ppp_pcb *pcb);
88 #if PRINTPKT_SUPPORT
89 static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
90 #endif /* PRINTPKT_SUPPORT */
91
92 const struct protent pap_protent = {
93     PPP_PAP,
94     upap_init,
95     upap_input,
96     upap_protrej,
97     upap_lowerup,
98     upap_lowerdown,
99     NULL,
100     NULL,
101 #if PRINTPKT_SUPPORT
102     upap_printpkt,
103 #endif /* PRINTPKT_SUPPORT */
104 #if PPP_DATAINPUT
105     NULL,
106 #endif /* PPP_DATAINPUT */
107 #if PRINTPKT_SUPPORT
108     "PAP",
109     NULL,
110 #endif /* PRINTPKT_SUPPORT */
111 #if PPP_OPTIONS
112     pap_option_list,
113     NULL,
114 #endif /* PPP_OPTIONS */
115 #if DEMAND_SUPPORT
116     NULL,
117     NULL
118 #endif /* DEMAND_SUPPORT */
119 };
120
121 static void upap_timeout(void *arg);
122 #if PPP_SERVER
123 static void upap_reqtimeout(void *arg);
124 static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len);
125 #endif /* PPP_SERVER */
126 static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len);
127 static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len);
128 static void upap_sauthreq(ppp_pcb *pcb);
129 #if PPP_SERVER
130 static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen);
131 #endif /* PPP_SERVER */
132
133
134 /*
135  * upap_init - Initialize a UPAP unit.
136  */
137 static void upap_init(ppp_pcb *pcb) {
138     pcb->upap.us_user = NULL;
139     pcb->upap.us_userlen = 0;
140     pcb->upap.us_passwd = NULL;
141     pcb->upap.us_passwdlen = 0;
142     pcb->upap.us_clientstate = UPAPCS_INITIAL;
143 #if PPP_SERVER
144     pcb->upap.us_serverstate = UPAPSS_INITIAL;
145 #endif /* PPP_SERVER */
146     pcb->upap.us_id = 0;
147 }
148
149
150 /*
151  * upap_authwithpeer - Authenticate us with our peer (start client).
152  *
153  * Set new state and send authenticate's.
154  */
155 void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) {
156
157     if(!user || !password)
158         return;
159
160     /* Save the username and password we're given */
161     pcb->upap.us_user = user;
162     pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff);
163     pcb->upap.us_passwd = password;
164     pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff);
165     pcb->upap.us_transmits = 0;
166
167     /* Lower layer up yet? */
168     if (pcb->upap.us_clientstate == UPAPCS_INITIAL ||
169         pcb->upap.us_clientstate == UPAPCS_PENDING) {
170         pcb->upap.us_clientstate = UPAPCS_PENDING;
171         return;
172     }
173
174     upap_sauthreq(pcb);         /* Start protocol */
175 }
176
177 #if PPP_SERVER
178 /*
179  * upap_authpeer - Authenticate our peer (start server).
180  *
181  * Set new state.
182  */
183 void upap_authpeer(ppp_pcb *pcb) {
184
185     /* Lower layer up yet? */
186     if (pcb->upap.us_serverstate == UPAPSS_INITIAL ||
187         pcb->upap.us_serverstate == UPAPSS_PENDING) {
188         pcb->upap.us_serverstate = UPAPSS_PENDING;
189         return;
190     }
191
192     pcb->upap.us_serverstate = UPAPSS_LISTEN;
193     if (pcb->settings.pap_req_timeout > 0)
194         TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
195 }
196 #endif /* PPP_SERVER */
197
198 /*
199  * upap_timeout - Retransmission timer for sending auth-reqs expired.
200  */
201 static void upap_timeout(void *arg) {
202     ppp_pcb *pcb = (ppp_pcb*)arg;
203
204     if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ)
205         return;
206
207     if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) {
208         /* give up in disgust */
209         ppp_error("No response to PAP authenticate-requests");
210         pcb->upap.us_clientstate = UPAPCS_BADAUTH;
211         auth_withpeer_fail(pcb, PPP_PAP);
212         return;
213     }
214
215     upap_sauthreq(pcb);         /* Send Authenticate-Request */
216 }
217
218
219 #if PPP_SERVER
220 /*
221  * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
222  */
223 static void upap_reqtimeout(void *arg) {
224     ppp_pcb *pcb = (ppp_pcb*)arg;
225
226     if (pcb->upap.us_serverstate != UPAPSS_LISTEN)
227         return;                 /* huh?? */
228
229     auth_peer_fail(pcb, PPP_PAP);
230     pcb->upap.us_serverstate = UPAPSS_BADAUTH;
231 }
232 #endif /* PPP_SERVER */
233
234
235 /*
236  * upap_lowerup - The lower layer is up.
237  *
238  * Start authenticating if pending.
239  */
240 static void upap_lowerup(ppp_pcb *pcb) {
241
242     if (pcb->upap.us_clientstate == UPAPCS_INITIAL)
243         pcb->upap.us_clientstate = UPAPCS_CLOSED;
244     else if (pcb->upap.us_clientstate == UPAPCS_PENDING) {
245         upap_sauthreq(pcb);     /* send an auth-request */
246     }
247
248 #if PPP_SERVER
249     if (pcb->upap.us_serverstate == UPAPSS_INITIAL)
250         pcb->upap.us_serverstate = UPAPSS_CLOSED;
251     else if (pcb->upap.us_serverstate == UPAPSS_PENDING) {
252         pcb->upap.us_serverstate = UPAPSS_LISTEN;
253         if (pcb->settings.pap_req_timeout > 0)
254             TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
255     }
256 #endif /* PPP_SERVER */
257 }
258
259
260 /*
261  * upap_lowerdown - The lower layer is down.
262  *
263  * Cancel all timeouts.
264  */
265 static void upap_lowerdown(ppp_pcb *pcb) {
266
267     if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ)     /* Timeout pending? */
268         UNTIMEOUT(upap_timeout, pcb);           /* Cancel timeout */
269 #if PPP_SERVER
270     if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0)
271         UNTIMEOUT(upap_reqtimeout, pcb);
272 #endif /* PPP_SERVER */
273
274     pcb->upap.us_clientstate = UPAPCS_INITIAL;
275 #if PPP_SERVER
276     pcb->upap.us_serverstate = UPAPSS_INITIAL;
277 #endif /* PPP_SERVER */
278 }
279
280
281 /*
282  * upap_protrej - Peer doesn't speak this protocol.
283  *
284  * This shouldn't happen.  In any case, pretend lower layer went down.
285  */
286 static void upap_protrej(ppp_pcb *pcb) {
287
288     if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) {
289         ppp_error("PAP authentication failed due to protocol-reject");
290         auth_withpeer_fail(pcb, PPP_PAP);
291     }
292 #if PPP_SERVER
293     if (pcb->upap.us_serverstate == UPAPSS_LISTEN) {
294         ppp_error("PAP authentication of peer failed (protocol-reject)");
295         auth_peer_fail(pcb, PPP_PAP);
296     }
297 #endif /* PPP_SERVER */
298     upap_lowerdown(pcb);
299 }
300
301
302 /*
303  * upap_input - Input UPAP packet.
304  */
305 static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) {
306     u_char *inp;
307     u_char code, id;
308     int len;
309
310     /*
311      * Parse header (code, id and length).
312      * If packet too short, drop it.
313      */
314     inp = inpacket;
315     if (l < UPAP_HEADERLEN) {
316         UPAPDEBUG(("pap_input: rcvd short header."));
317         return;
318     }
319     GETCHAR(code, inp);
320     GETCHAR(id, inp);
321     GETSHORT(len, inp);
322     if (len < UPAP_HEADERLEN) {
323         UPAPDEBUG(("pap_input: rcvd illegal length."));
324         return;
325     }
326     if (len > l) {
327         UPAPDEBUG(("pap_input: rcvd short packet."));
328         return;
329     }
330     len -= UPAP_HEADERLEN;
331
332     /*
333      * Action depends on code.
334      */
335     switch (code) {
336     case UPAP_AUTHREQ:
337 #if PPP_SERVER
338         upap_rauthreq(pcb, inp, id, len);
339 #endif /* PPP_SERVER */
340         break;
341
342     case UPAP_AUTHACK:
343         upap_rauthack(pcb, inp, id, len);
344         break;
345
346     case UPAP_AUTHNAK:
347         upap_rauthnak(pcb, inp, id, len);
348         break;
349
350     default:                            /* XXX Need code reject */
351         break;
352     }
353 }
354
355 #if PPP_SERVER
356 /*
357  * upap_rauth - Receive Authenticate.
358  */
359 static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) {
360     u_char ruserlen, rpasswdlen;
361     char *ruser;
362     char *rpasswd;
363     char rhostname[256];
364     int retcode;
365     const char *msg;
366     int msglen;
367
368     if (pcb->upap.us_serverstate < UPAPSS_LISTEN)
369         return;
370
371     /*
372      * If we receive a duplicate authenticate-request, we are
373      * supposed to return the same status as for the first request.
374      */
375     if (pcb->upap.us_serverstate == UPAPSS_OPEN) {
376         upap_sresp(pcb, UPAP_AUTHACK, id, "", 0);       /* return auth-ack */
377         return;
378     }
379     if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) {
380         upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0);       /* return auth-nak */
381         return;
382     }
383
384     /*
385      * Parse user/passwd.
386      */
387     if (len < 1) {
388         UPAPDEBUG(("pap_rauth: rcvd short packet."));
389         return;
390     }
391     GETCHAR(ruserlen, inp);
392     len -= sizeof (u_char) + ruserlen + sizeof (u_char);
393     if (len < 0) {
394         UPAPDEBUG(("pap_rauth: rcvd short packet."));
395         return;
396     }
397     ruser = (char *) inp;
398     INCPTR(ruserlen, inp);
399     GETCHAR(rpasswdlen, inp);
400     if (len < rpasswdlen) {
401         UPAPDEBUG(("pap_rauth: rcvd short packet."));
402         return;
403     }
404
405     rpasswd = (char *) inp;
406
407     /*
408      * Check the username and password given.
409      */
410     retcode = UPAP_AUTHNAK;
411     if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) {
412       retcode = UPAP_AUTHACK;
413     }
414     BZERO(rpasswd, rpasswdlen);
415
416 #if 0 /* UNUSED */
417     /*
418      * Check remote number authorization.  A plugin may have filled in
419      * the remote number or added an allowed number, and rather than
420      * return an authenticate failure, is leaving it for us to verify.
421      */
422     if (retcode == UPAP_AUTHACK) {
423         if (!auth_number()) {
424             /* We do not want to leak info about the pap result. */
425             retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */
426             warn("calling number %q is not authorized", remote_number);
427         }
428     }
429
430     msglen = strlen(msg);
431     if (msglen > 255)
432         msglen = 255;
433 #endif /* UNUSED */
434
435     upap_sresp(pcb, retcode, id, msg, msglen);
436
437     /* Null terminate and clean remote name. */
438     ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser);
439
440     if (retcode == UPAP_AUTHACK) {
441         pcb->upap.us_serverstate = UPAPSS_OPEN;
442         ppp_notice("PAP peer authentication succeeded for %q", rhostname);
443         auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen);
444     } else {
445         pcb->upap.us_serverstate = UPAPSS_BADAUTH;
446         ppp_warn("PAP peer authentication failed for %q", rhostname);
447         auth_peer_fail(pcb, PPP_PAP);
448     }
449
450     if (pcb->settings.pap_req_timeout > 0)
451         UNTIMEOUT(upap_reqtimeout, pcb);
452 }
453 #endif /* PPP_SERVER */
454
455 /*
456  * upap_rauthack - Receive Authenticate-Ack.
457  */
458 static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) {
459     u_char msglen;
460     char *msg;
461     LWIP_UNUSED_ARG(id);
462
463     if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
464         return;
465
466     /*
467      * Parse message.
468      */
469     if (len < 1) {
470         UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
471     } else {
472         GETCHAR(msglen, inp);
473         if (msglen > 0) {
474             len -= sizeof (u_char);
475             if (len < msglen) {
476                 UPAPDEBUG(("pap_rauthack: rcvd short packet."));
477                 return;
478             }
479             msg = (char *) inp;
480             PRINTMSG(msg, msglen);
481         }
482     }
483
484     pcb->upap.us_clientstate = UPAPCS_OPEN;
485
486     auth_withpeer_success(pcb, PPP_PAP, 0);
487 }
488
489
490 /*
491  * upap_rauthnak - Receive Authenticate-Nak.
492  */
493 static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) {
494     u_char msglen;
495     char *msg;
496     LWIP_UNUSED_ARG(id);
497
498     if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
499         return;
500
501     /*
502      * Parse message.
503      */
504     if (len < 1) {
505         UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
506     } else {
507         GETCHAR(msglen, inp);
508         if (msglen > 0) {
509             len -= sizeof (u_char);
510             if (len < msglen) {
511                 UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
512                 return;
513             }
514             msg = (char *) inp;
515             PRINTMSG(msg, msglen);
516         }
517     }
518
519     pcb->upap.us_clientstate = UPAPCS_BADAUTH;
520
521     ppp_error("PAP authentication failed");
522     auth_withpeer_fail(pcb, PPP_PAP);
523 }
524
525
526 /*
527  * upap_sauthreq - Send an Authenticate-Request.
528  */
529 static void upap_sauthreq(ppp_pcb *pcb) {
530     struct pbuf *p;
531     u_char *outp;
532     int outlen;
533
534     outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
535         pcb->upap.us_userlen + pcb->upap.us_passwdlen;
536     p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
537     if(NULL == p)
538         return;
539     if(p->tot_len != p->len) {
540         pbuf_free(p);
541         return;
542     }
543
544     outp = (u_char*)p->payload;
545     MAKEHEADER(outp, PPP_PAP);
546
547     PUTCHAR(UPAP_AUTHREQ, outp);
548     PUTCHAR(++pcb->upap.us_id, outp);
549     PUTSHORT(outlen, outp);
550     PUTCHAR(pcb->upap.us_userlen, outp);
551     MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
552     INCPTR(pcb->upap.us_userlen, outp);
553     PUTCHAR(pcb->upap.us_passwdlen, outp);
554     MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);
555
556     ppp_write(pcb, p);
557
558     TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
559     ++pcb->upap.us_transmits;
560     pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
561 }
562
563 #if PPP_SERVER
564 /*
565  * upap_sresp - Send a response (ack or nak).
566  */
567 static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
568     struct pbuf *p;
569     u_char *outp;
570     int outlen;
571
572     outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
573     p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
574     if(NULL == p)
575         return;
576     if(p->tot_len != p->len) {
577         pbuf_free(p);
578         return;
579     }
580
581     outp = (u_char*)p->payload;
582     MAKEHEADER(outp, PPP_PAP);
583
584     PUTCHAR(code, outp);
585     PUTCHAR(id, outp);
586     PUTSHORT(outlen, outp);
587     PUTCHAR(msglen, outp);
588     MEMCPY(outp, msg, msglen);
589
590     ppp_write(pcb, p);
591 }
592 #endif /* PPP_SERVER */
593
594 #if PRINTPKT_SUPPORT
595 /*
596  * upap_printpkt - print the contents of a PAP packet.
597  */
598 static const char* const upap_codenames[] = {
599     "AuthReq", "AuthAck", "AuthNak"
600 };
601
602 static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
603     int code, id, len;
604     int mlen, ulen, wlen;
605     const u_char *user, *pwd, *msg;
606     const u_char *pstart;
607
608     if (plen < UPAP_HEADERLEN)
609         return 0;
610     pstart = p;
611     GETCHAR(code, p);
612     GETCHAR(id, p);
613     GETSHORT(len, p);
614     if (len < UPAP_HEADERLEN || len > plen)
615         return 0;
616
617     if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames))
618         printer(arg, " %s", upap_codenames[code-1]);
619     else
620         printer(arg, " code=0x%x", code);
621     printer(arg, " id=0x%x", id);
622     len -= UPAP_HEADERLEN;
623     switch (code) {
624     case UPAP_AUTHREQ:
625         if (len < 1)
626             break;
627         ulen = p[0];
628         if (len < ulen + 2)
629             break;
630         wlen = p[ulen + 1];
631         if (len < ulen + wlen + 2)
632             break;
633         user = (const u_char *) (p + 1);
634         pwd = (const u_char *) (p + ulen + 2);
635         p += ulen + wlen + 2;
636         len -= ulen + wlen + 2;
637         printer(arg, " user=");
638         ppp_print_string(user, ulen, printer, arg);
639         printer(arg, " password=");
640 /* FIXME: require ppp_pcb struct as printpkt() argument */
641 #if 0
642         if (!pcb->settings.hide_password)
643 #endif
644             ppp_print_string(pwd, wlen, printer, arg);
645 #if 0
646         else
647             printer(arg, "<hidden>");
648 #endif
649         break;
650     case UPAP_AUTHACK:
651     case UPAP_AUTHNAK:
652         if (len < 1)
653             break;
654         mlen = p[0];
655         if (len < mlen + 1)
656             break;
657         msg = (const u_char *) (p + 1);
658         p += mlen + 1;
659         len -= mlen + 1;
660         printer(arg, " ");
661         ppp_print_string(msg, mlen, printer, arg);
662         break;
663     default:
664         break;
665     }
666
667     /* print the rest of the bytes in the packet */
668     for (; len > 0; --len) {
669         GETCHAR(code, p);
670         printer(arg, " %.2x", code);
671     }
672
673     return p - pstart;
674 }
675 #endif /* PRINTPKT_SUPPORT */
676
677 #endif /* PPP_SUPPORT && PAP_SUPPORT */