00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include "lwip/opt.h"
00053
00054 #if PPP_SUPPORT
00055
00056 #include "ppp.h"
00057 #include "pppdebug.h"
00058
00059 #include "auth.h"
00060 #include "fsm.h"
00061 #include "vj.h"
00062 #include "ipcp.h"
00063
00064 #include <string.h>
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #define CILEN_VOID 2
00075 #define CILEN_COMPRESS 4
00076 #define CILEN_VJ 6
00077 #define CILEN_ADDR 6
00078 #define CILEN_ADDRS 10
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static void ipcp_resetci (fsm *);
00089 static int ipcp_cilen (fsm *);
00090 static void ipcp_addci (fsm *, u_char *, int *);
00091 static int ipcp_ackci (fsm *, u_char *, int);
00092 static int ipcp_nakci (fsm *, u_char *, int);
00093 static int ipcp_rejci (fsm *, u_char *, int);
00094 static int ipcp_reqci (fsm *, u_char *, int *, int);
00095 static void ipcp_up (fsm *);
00096 static void ipcp_down (fsm *);
00097 #if 0
00098 static void ipcp_script (fsm *, char *);
00099 #endif
00100 static void ipcp_finished (fsm *);
00101
00102
00103
00104
00105 static void ipcp_init (int);
00106 static void ipcp_open (int);
00107 static void ipcp_close (int, char *);
00108 static void ipcp_lowerup (int);
00109 static void ipcp_lowerdown (int);
00110 static void ipcp_input (int, u_char *, int);
00111 static void ipcp_protrej (int);
00112
00113 static void ipcp_clear_addrs (int);
00114
00115 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
00116 (x) == CONFNAK ? "NAK" : "REJ")
00117
00118
00119
00120
00121
00122
00123
00124 ipcp_options ipcp_wantoptions[NUM_PPP];
00125 ipcp_options ipcp_gotoptions[NUM_PPP];
00126 ipcp_options ipcp_allowoptions[NUM_PPP];
00127 ipcp_options ipcp_hisoptions[NUM_PPP];
00128
00129 fsm ipcp_fsm[NUM_PPP];
00130
00131 struct protent ipcp_protent = {
00132 PPP_IPCP,
00133 ipcp_init,
00134 ipcp_input,
00135 ipcp_protrej,
00136 ipcp_lowerup,
00137 ipcp_lowerdown,
00138 ipcp_open,
00139 ipcp_close,
00140 #if 0
00141 ipcp_printpkt,
00142 NULL,
00143 #endif
00144 1,
00145 "IPCP",
00146 #if 0
00147 ip_check_options,
00148 NULL,
00149 ip_active_pkt
00150 #endif
00151 };
00152
00153
00154
00155
00156
00157
00158
00159 static int cis_received[NUM_PPP];
00160 static int default_route_set[NUM_PPP];
00161
00162 static fsm_callbacks ipcp_callbacks = {
00163 ipcp_resetci,
00164 ipcp_cilen,
00165 ipcp_addci,
00166 ipcp_ackci,
00167 ipcp_nakci,
00168 ipcp_rejci,
00169 ipcp_reqci,
00170 ipcp_up,
00171 ipcp_down,
00172 NULL,
00173 ipcp_finished,
00174 NULL,
00175 NULL,
00176 NULL,
00177 "IPCP"
00178 };
00179
00180
00181
00182
00183
00184
00185
00186 #define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr)))
00187
00188
00189
00190
00191 static void
00192 ipcp_init(int unit)
00193 {
00194 fsm *f = &ipcp_fsm[unit];
00195 ipcp_options *wo = &ipcp_wantoptions[unit];
00196 ipcp_options *ao = &ipcp_allowoptions[unit];
00197
00198 f->unit = unit;
00199 f->protocol = PPP_IPCP;
00200 f->callbacks = &ipcp_callbacks;
00201 fsm_init(&ipcp_fsm[unit]);
00202
00203 memset(wo, 0, sizeof(*wo));
00204 memset(ao, 0, sizeof(*ao));
00205
00206 wo->neg_addr = 1;
00207 wo->ouraddr = 0;
00208 #if VJ_SUPPORT
00209 wo->neg_vj = 1;
00210 #else
00211 wo->neg_vj = 0;
00212 #endif
00213 wo->vj_protocol = IPCP_VJ_COMP;
00214 wo->maxslotindex = MAX_SLOTS - 1;
00215 wo->cflag = 0;
00216 wo->default_route = 1;
00217
00218 ao->neg_addr = 1;
00219 #if VJ_SUPPORT
00220 ao->neg_vj = 1;
00221 #else
00222 ao->neg_vj = 0;
00223 #endif
00224 ao->maxslotindex = MAX_SLOTS - 1;
00225 ao->cflag = 1;
00226 ao->default_route = 1;
00227 }
00228
00229
00230
00231
00232
00233 static void
00234 ipcp_open(int unit)
00235 {
00236 fsm_open(&ipcp_fsm[unit]);
00237 }
00238
00239
00240
00241
00242
00243 static void
00244 ipcp_close(int unit, char *reason)
00245 {
00246 fsm_close(&ipcp_fsm[unit], reason);
00247 }
00248
00249
00250
00251
00252
00253 static void
00254 ipcp_lowerup(int unit)
00255 {
00256 fsm_lowerup(&ipcp_fsm[unit]);
00257 }
00258
00259
00260
00261
00262
00263 static void
00264 ipcp_lowerdown(int unit)
00265 {
00266 fsm_lowerdown(&ipcp_fsm[unit]);
00267 }
00268
00269
00270
00271
00272
00273 static void
00274 ipcp_input(int unit, u_char *p, int len)
00275 {
00276 fsm_input(&ipcp_fsm[unit], p, len);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 static void
00286 ipcp_protrej(int unit)
00287 {
00288 fsm_lowerdown(&ipcp_fsm[unit]);
00289 }
00290
00291
00292
00293
00294
00295 static void
00296 ipcp_resetci(fsm *f)
00297 {
00298 ipcp_options *wo = &ipcp_wantoptions[f->unit];
00299
00300 wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
00301 if (wo->ouraddr == 0) {
00302 wo->accept_local = 1;
00303 }
00304 if (wo->hisaddr == 0) {
00305 wo->accept_remote = 1;
00306 }
00307
00308 wo->req_dns1 = ppp_settings.usepeerdns;
00309 wo->req_dns2 = ppp_settings.usepeerdns;
00310 ipcp_gotoptions[f->unit] = *wo;
00311 cis_received[f->unit] = 0;
00312 }
00313
00314
00315
00316
00317
00318 static int
00319 ipcp_cilen(fsm *f)
00320 {
00321 ipcp_options *go = &ipcp_gotoptions[f->unit];
00322 ipcp_options *wo = &ipcp_wantoptions[f->unit];
00323 ipcp_options *ho = &ipcp_hisoptions[f->unit];
00324
00325 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
00326 #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
00327 #define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0)
00328
00329
00330
00331
00332
00333 if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
00334
00335 go->neg_addr = 1;
00336 go->old_addrs = 1;
00337 }
00338 if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
00339
00340 if (cis_received[f->unit] == 0) {
00341
00342 go->neg_vj = 1;
00343 } else {
00344
00345 if (ho->neg_vj && ho->old_vj) {
00346 go->neg_vj = 1;
00347 go->old_vj = 1;
00348 go->vj_protocol = ho->vj_protocol;
00349 }
00350 }
00351 }
00352
00353 return (LENCIADDR(go->neg_addr, go->old_addrs) +
00354 LENCIVJ(go->neg_vj, go->old_vj) +
00355 LENCIDNS(go->req_dns1) +
00356 LENCIDNS(go->req_dns2));
00357 }
00358
00359
00360
00361
00362
00363 static void
00364 ipcp_addci(fsm *f, u_char *ucp, int *lenp)
00365 {
00366 ipcp_options *go = &ipcp_gotoptions[f->unit];
00367 int len = *lenp;
00368
00369 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
00370 if (neg) { \
00371 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
00372 if (len >= vjlen) { \
00373 PUTCHAR(opt, ucp); \
00374 PUTCHAR(vjlen, ucp); \
00375 PUTSHORT(val, ucp); \
00376 if (!old) { \
00377 PUTCHAR(maxslotindex, ucp); \
00378 PUTCHAR(cflag, ucp); \
00379 } \
00380 len -= vjlen; \
00381 } else { \
00382 neg = 0; \
00383 } \
00384 }
00385
00386 #define ADDCIADDR(opt, neg, old, val1, val2) \
00387 if (neg) { \
00388 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
00389 if (len >= addrlen) { \
00390 u32_t l; \
00391 PUTCHAR(opt, ucp); \
00392 PUTCHAR(addrlen, ucp); \
00393 l = ntohl(val1); \
00394 PUTLONG(l, ucp); \
00395 if (old) { \
00396 l = ntohl(val2); \
00397 PUTLONG(l, ucp); \
00398 } \
00399 len -= addrlen; \
00400 } else { \
00401 neg = 0; \
00402 } \
00403 }
00404
00405 #define ADDCIDNS(opt, neg, addr) \
00406 if (neg) { \
00407 if (len >= CILEN_ADDR) { \
00408 u32_t l; \
00409 PUTCHAR(opt, ucp); \
00410 PUTCHAR(CILEN_ADDR, ucp); \
00411 l = ntohl(addr); \
00412 PUTLONG(l, ucp); \
00413 len -= CILEN_ADDR; \
00414 } else { \
00415 neg = 0; \
00416 } \
00417 }
00418
00419 ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
00420 go->old_addrs, go->ouraddr, go->hisaddr);
00421
00422 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
00423 go->maxslotindex, go->cflag);
00424
00425 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
00426
00427 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
00428
00429 *lenp -= len;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 static int
00441 ipcp_ackci(fsm *f, u_char *p, int len)
00442 {
00443 ipcp_options *go = &ipcp_gotoptions[f->unit];
00444 u_short cilen, citype, cishort;
00445 u32_t cilong;
00446 u_char cimaxslotindex, cicflag;
00447
00448
00449
00450
00451
00452
00453
00454 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
00455 if (neg) { \
00456 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
00457 if ((len -= vjlen) < 0) { \
00458 goto bad; \
00459 } \
00460 GETCHAR(citype, p); \
00461 GETCHAR(cilen, p); \
00462 if (cilen != vjlen || \
00463 citype != opt) { \
00464 goto bad; \
00465 } \
00466 GETSHORT(cishort, p); \
00467 if (cishort != val) { \
00468 goto bad; \
00469 } \
00470 if (!old) { \
00471 GETCHAR(cimaxslotindex, p); \
00472 if (cimaxslotindex != maxslotindex) { \
00473 goto bad; \
00474 } \
00475 GETCHAR(cicflag, p); \
00476 if (cicflag != cflag) { \
00477 goto bad; \
00478 } \
00479 } \
00480 }
00481
00482 #define ACKCIADDR(opt, neg, old, val1, val2) \
00483 if (neg) { \
00484 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
00485 u32_t l; \
00486 if ((len -= addrlen) < 0) { \
00487 goto bad; \
00488 } \
00489 GETCHAR(citype, p); \
00490 GETCHAR(cilen, p); \
00491 if (cilen != addrlen || \
00492 citype != opt) { \
00493 goto bad; \
00494 } \
00495 GETLONG(l, p); \
00496 cilong = htonl(l); \
00497 if (val1 != cilong) { \
00498 goto bad; \
00499 } \
00500 if (old) { \
00501 GETLONG(l, p); \
00502 cilong = htonl(l); \
00503 if (val2 != cilong) { \
00504 goto bad; \
00505 } \
00506 } \
00507 }
00508
00509 #define ACKCIDNS(opt, neg, addr) \
00510 if (neg) { \
00511 u32_t l; \
00512 if ((len -= CILEN_ADDR) < 0) { \
00513 goto bad; \
00514 } \
00515 GETCHAR(citype, p); \
00516 GETCHAR(cilen, p); \
00517 if (cilen != CILEN_ADDR || \
00518 citype != opt) { \
00519 goto bad; \
00520 } \
00521 GETLONG(l, p); \
00522 cilong = htonl(l); \
00523 if (addr != cilong) { \
00524 goto bad; \
00525 } \
00526 }
00527
00528 ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
00529 go->old_addrs, go->ouraddr, go->hisaddr);
00530
00531 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
00532 go->maxslotindex, go->cflag);
00533
00534 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
00535
00536 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
00537
00538
00539
00540
00541 if (len != 0) {
00542 goto bad;
00543 }
00544 return (1);
00545
00546 bad:
00547 IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n"));
00548 return (0);
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 static int
00561 ipcp_nakci(fsm *f, u_char *p, int len)
00562 {
00563 ipcp_options *go = &ipcp_gotoptions[f->unit];
00564 u_char cimaxslotindex, cicflag;
00565 u_char citype, cilen, *next;
00566 u_short cishort;
00567 u32_t ciaddr1, ciaddr2, l, cidnsaddr;
00568 ipcp_options no;
00569 ipcp_options try;
00570
00571 BZERO(&no, sizeof(no));
00572 try = *go;
00573
00574
00575
00576
00577
00578
00579 #define NAKCIADDR(opt, neg, old, code) \
00580 if (go->neg && \
00581 len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
00582 p[1] == cilen && \
00583 p[0] == opt) { \
00584 len -= cilen; \
00585 INCPTR(2, p); \
00586 GETLONG(l, p); \
00587 ciaddr1 = htonl(l); \
00588 if (old) { \
00589 GETLONG(l, p); \
00590 ciaddr2 = htonl(l); \
00591 no.old_addrs = 1; \
00592 } else { \
00593 ciaddr2 = 0; \
00594 } \
00595 no.neg = 1; \
00596 code \
00597 }
00598
00599 #define NAKCIVJ(opt, neg, code) \
00600 if (go->neg && \
00601 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
00602 len >= cilen && \
00603 p[0] == opt) { \
00604 len -= cilen; \
00605 INCPTR(2, p); \
00606 GETSHORT(cishort, p); \
00607 no.neg = 1; \
00608 code \
00609 }
00610
00611 #define NAKCIDNS(opt, neg, code) \
00612 if (go->neg && \
00613 ((cilen = p[1]) == CILEN_ADDR) && \
00614 len >= cilen && \
00615 p[0] == opt) { \
00616 len -= cilen; \
00617 INCPTR(2, p); \
00618 GETLONG(l, p); \
00619 cidnsaddr = htonl(l); \
00620 no.neg = 1; \
00621 code \
00622 }
00623
00624
00625
00626
00627
00628 NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
00629 if (go->accept_local && ciaddr1) {
00630 try.ouraddr = ciaddr1;
00631 IPCPDEBUG((LOG_INFO, "local IP address %s\n",
00632 inet_ntoa(ciaddr1)));
00633 }
00634 if (go->accept_remote && ciaddr2) {
00635 try.hisaddr = ciaddr2;
00636 IPCPDEBUG((LOG_INFO, "remote IP address %s\n",
00637 inet_ntoa(ciaddr2)));
00638 }
00639 );
00640
00641
00642
00643
00644
00645
00646
00647 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
00648 if (cilen == CILEN_VJ) {
00649 GETCHAR(cimaxslotindex, p);
00650 GETCHAR(cicflag, p);
00651 if (cishort == IPCP_VJ_COMP) {
00652 try.old_vj = 0;
00653 if (cimaxslotindex < go->maxslotindex) {
00654 try.maxslotindex = cimaxslotindex;
00655 }
00656 if (!cicflag) {
00657 try.cflag = 0;
00658 }
00659 } else {
00660 try.neg_vj = 0;
00661 }
00662 } else {
00663 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
00664 try.old_vj = 1;
00665 try.vj_protocol = cishort;
00666 } else {
00667 try.neg_vj = 0;
00668 }
00669 }
00670 );
00671
00672 NAKCIDNS(CI_MS_DNS1, req_dns1,
00673 try.dnsaddr[0] = cidnsaddr;
00674 IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr)));
00675 );
00676
00677 NAKCIDNS(CI_MS_DNS2, req_dns2,
00678 try.dnsaddr[1] = cidnsaddr;
00679 IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
00680 );
00681
00682
00683
00684
00685
00686
00687
00688 while (len > CILEN_VOID) {
00689 GETCHAR(citype, p);
00690 GETCHAR(cilen, p);
00691 if( (len -= cilen) < 0 ) {
00692 goto bad;
00693 }
00694 next = p + cilen - 2;
00695
00696 switch (citype) {
00697 case CI_COMPRESSTYPE:
00698 if (go->neg_vj || no.neg_vj ||
00699 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
00700 goto bad;
00701 }
00702 no.neg_vj = 1;
00703 break;
00704 case CI_ADDRS:
00705 if ((go->neg_addr && go->old_addrs) || no.old_addrs
00706 || cilen != CILEN_ADDRS) {
00707 goto bad;
00708 }
00709 try.neg_addr = 1;
00710 try.old_addrs = 1;
00711 GETLONG(l, p);
00712 ciaddr1 = htonl(l);
00713 if (ciaddr1 && go->accept_local) {
00714 try.ouraddr = ciaddr1;
00715 }
00716 GETLONG(l, p);
00717 ciaddr2 = htonl(l);
00718 if (ciaddr2 && go->accept_remote) {
00719 try.hisaddr = ciaddr2;
00720 }
00721 no.old_addrs = 1;
00722 break;
00723 case CI_ADDR:
00724 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) {
00725 goto bad;
00726 }
00727 try.old_addrs = 0;
00728 GETLONG(l, p);
00729 ciaddr1 = htonl(l);
00730 if (ciaddr1 && go->accept_local) {
00731 try.ouraddr = ciaddr1;
00732 }
00733 if (try.ouraddr != 0) {
00734 try.neg_addr = 1;
00735 }
00736 no.neg_addr = 1;
00737 break;
00738 }
00739 p = next;
00740 }
00741
00742
00743 if (len != 0) {
00744 goto bad;
00745 }
00746
00747
00748
00749
00750 if (f->state != LS_OPENED) {
00751 *go = try;
00752 }
00753
00754 return 1;
00755
00756 bad:
00757 IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n"));
00758 return 0;
00759 }
00760
00761
00762
00763
00764
00765 static int
00766 ipcp_rejci(fsm *f, u_char *p, int len)
00767 {
00768 ipcp_options *go = &ipcp_gotoptions[f->unit];
00769 u_char cimaxslotindex, ciflag, cilen;
00770 u_short cishort;
00771 u32_t cilong;
00772 ipcp_options try;
00773
00774 try = *go;
00775
00776
00777
00778
00779
00780 #define REJCIADDR(opt, neg, old, val1, val2) \
00781 if (go->neg && \
00782 len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
00783 p[1] == cilen && \
00784 p[0] == opt) { \
00785 u32_t l; \
00786 len -= cilen; \
00787 INCPTR(2, p); \
00788 GETLONG(l, p); \
00789 cilong = htonl(l); \
00790 \
00791 if (cilong != val1) { \
00792 goto bad; \
00793 } \
00794 if (old) { \
00795 GETLONG(l, p); \
00796 cilong = htonl(l); \
00797 \
00798 if (cilong != val2) { \
00799 goto bad; \
00800 } \
00801 } \
00802 try.neg = 0; \
00803 }
00804
00805 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
00806 if (go->neg && \
00807 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
00808 len >= p[1] && \
00809 p[0] == opt) { \
00810 len -= p[1]; \
00811 INCPTR(2, p); \
00812 GETSHORT(cishort, p); \
00813 \
00814 if (cishort != val) { \
00815 goto bad; \
00816 } \
00817 if (!old) { \
00818 GETCHAR(cimaxslotindex, p); \
00819 if (cimaxslotindex != maxslot) { \
00820 goto bad; \
00821 } \
00822 GETCHAR(ciflag, p); \
00823 if (ciflag != cflag) { \
00824 goto bad; \
00825 } \
00826 } \
00827 try.neg = 0; \
00828 }
00829
00830 #define REJCIDNS(opt, neg, dnsaddr) \
00831 if (go->neg && \
00832 ((cilen = p[1]) == CILEN_ADDR) && \
00833 len >= cilen && \
00834 p[0] == opt) { \
00835 u32_t l; \
00836 len -= cilen; \
00837 INCPTR(2, p); \
00838 GETLONG(l, p); \
00839 cilong = htonl(l); \
00840 \
00841 if (cilong != dnsaddr) { \
00842 goto bad; \
00843 } \
00844 try.neg = 0; \
00845 }
00846
00847 REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
00848 go->old_addrs, go->ouraddr, go->hisaddr);
00849
00850 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
00851 go->maxslotindex, go->cflag);
00852
00853 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
00854
00855 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
00856
00857
00858
00859
00860 if (len != 0) {
00861 goto bad;
00862 }
00863
00864
00865
00866 if (f->state != LS_OPENED) {
00867 *go = try;
00868 }
00869 return 1;
00870
00871 bad:
00872 IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n"));
00873 return 0;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 static int
00885 ipcp_reqci(fsm *f, u_char *inp,int *len,int reject_if_disagree)
00886 {
00887 ipcp_options *wo = &ipcp_wantoptions[f->unit];
00888 ipcp_options *ho = &ipcp_hisoptions[f->unit];
00889 ipcp_options *ao = &ipcp_allowoptions[f->unit];
00890 #ifdef OLD_CI_ADDRS
00891 ipcp_options *go = &ipcp_gotoptions[f->unit];
00892 #endif
00893 u_char *cip, *next;
00894 u_short cilen, citype;
00895 u_short cishort;
00896 u32_t tl, ciaddr1;
00897 #ifdef OLD_CI_ADDRS
00898 u32_t ciaddr2;
00899 #endif
00900 int rc = CONFACK;
00901 int orc;
00902 u_char *p;
00903 u_char *ucp = inp;
00904 int l = *len;
00905 u_char maxslotindex, cflag;
00906 int d;
00907
00908 cis_received[f->unit] = 1;
00909
00910
00911
00912
00913 BZERO(ho, sizeof(*ho));
00914
00915
00916
00917
00918 next = inp;
00919 while (l) {
00920 orc = CONFACK;
00921 cip = p = next;
00922 if (l < 2 ||
00923 p[1] < 2 ||
00924 p[1] > l) {
00925 IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n"));
00926 orc = CONFREJ;
00927 cilen = l;
00928 l = 0;
00929 goto endswitch;
00930 }
00931 GETCHAR(citype, p);
00932 GETCHAR(cilen, p);
00933 l -= cilen;
00934 next += cilen;
00935
00936 switch (citype) {
00937 #ifdef OLD_CI_ADDRS
00938 case CI_ADDRS:
00939 IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n"));
00940 if (!ao->neg_addr ||
00941 cilen != CILEN_ADDRS) {
00942 orc = CONFREJ;
00943 break;
00944 }
00945
00946
00947
00948
00949
00950
00951
00952 GETLONG(tl, p);
00953 ciaddr1 = htonl(tl);
00954 IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1)));
00955 if (ciaddr1 != wo->hisaddr
00956 && (ciaddr1 == 0 || !wo->accept_remote)) {
00957 orc = CONFNAK;
00958 if (!reject_if_disagree) {
00959 DECPTR(sizeof(u32_t), p);
00960 tl = ntohl(wo->hisaddr);
00961 PUTLONG(tl, p);
00962 }
00963 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
00964
00965
00966
00967 orc = CONFREJ;
00968 wo->req_addr = 0;
00969 break;
00970 }
00971
00972
00973
00974
00975
00976 GETLONG(tl, p);
00977 ciaddr2 = htonl(tl);
00978 IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2)));
00979 if (ciaddr2 != wo->ouraddr) {
00980 if (ciaddr2 == 0 || !wo->accept_local) {
00981 orc = CONFNAK;
00982 if (!reject_if_disagree) {
00983 DECPTR(sizeof(u32_t), p);
00984 tl = ntohl(wo->ouraddr);
00985 PUTLONG(tl, p);
00986 }
00987 } else {
00988 go->ouraddr = ciaddr2;
00989 }
00990 }
00991
00992 ho->neg_addr = 1;
00993 ho->old_addrs = 1;
00994 ho->hisaddr = ciaddr1;
00995 ho->ouraddr = ciaddr2;
00996 break;
00997 #endif
00998
00999 case CI_ADDR:
01000 if (!ao->neg_addr) {
01001 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n"));
01002 orc = CONFREJ;
01003 break;
01004 } else if (cilen != CILEN_ADDR) {
01005 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));
01006 orc = CONFREJ;
01007 break;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016 GETLONG(tl, p);
01017 ciaddr1 = htonl(tl);
01018 if (ciaddr1 != wo->hisaddr
01019 && (ciaddr1 == 0 || !wo->accept_remote)) {
01020 orc = CONFNAK;
01021 if (!reject_if_disagree) {
01022 DECPTR(sizeof(u32_t), p);
01023 tl = ntohl(wo->hisaddr);
01024 PUTLONG(tl, p);
01025 }
01026 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
01027 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
01028
01029
01030
01031 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
01032 orc = CONFREJ;
01033 wo->req_addr = 0;
01034 break;
01035 }
01036
01037 ho->neg_addr = 1;
01038 ho->hisaddr = ciaddr1;
01039 IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
01040 break;
01041
01042 case CI_MS_DNS1:
01043 case CI_MS_DNS2:
01044
01045 d = citype == CI_MS_DNS2;
01046
01047
01048 if (ao->dnsaddr[d] == 0 ||
01049 cilen != CILEN_ADDR) {
01050 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));
01051 orc = CONFREJ;
01052 break;
01053 }
01054 GETLONG(tl, p);
01055 if (htonl(tl) != ao->dnsaddr[d]) {
01056 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",
01057 d+1, inet_ntoa(tl)));
01058 DECPTR(sizeof(u32_t), p);
01059 tl = ntohl(ao->dnsaddr[d]);
01060 PUTLONG(tl, p);
01061 orc = CONFNAK;
01062 }
01063 IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));
01064 break;
01065
01066 case CI_MS_WINS1:
01067 case CI_MS_WINS2:
01068
01069 d = citype == CI_MS_WINS2;
01070 IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));
01071
01072
01073 if (ao->winsaddr[d] == 0 ||
01074 cilen != CILEN_ADDR) {
01075 orc = CONFREJ;
01076 break;
01077 }
01078 GETLONG(tl, p);
01079 if (htonl(tl) != ao->winsaddr[d]) {
01080 DECPTR(sizeof(u32_t), p);
01081 tl = ntohl(ao->winsaddr[d]);
01082 PUTLONG(tl, p);
01083 orc = CONFNAK;
01084 }
01085 break;
01086
01087 case CI_COMPRESSTYPE:
01088 if (!ao->neg_vj) {
01089 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
01090 orc = CONFREJ;
01091 break;
01092 } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
01093 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
01094 orc = CONFREJ;
01095 break;
01096 }
01097 GETSHORT(cishort, p);
01098
01099 if (!(cishort == IPCP_VJ_COMP ||
01100 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
01101 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
01102 orc = CONFREJ;
01103 break;
01104 }
01105
01106 ho->neg_vj = 1;
01107 ho->vj_protocol = cishort;
01108 if (cilen == CILEN_VJ) {
01109 GETCHAR(maxslotindex, p);
01110 if (maxslotindex > ao->maxslotindex) {
01111 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
01112 orc = CONFNAK;
01113 if (!reject_if_disagree) {
01114 DECPTR(1, p);
01115 PUTCHAR(ao->maxslotindex, p);
01116 }
01117 }
01118 GETCHAR(cflag, p);
01119 if (cflag && !ao->cflag) {
01120 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));
01121 orc = CONFNAK;
01122 if (!reject_if_disagree) {
01123 DECPTR(1, p);
01124 PUTCHAR(wo->cflag, p);
01125 }
01126 }
01127 ho->maxslotindex = maxslotindex;
01128 ho->cflag = cflag;
01129 } else {
01130 ho->old_vj = 1;
01131 ho->maxslotindex = MAX_SLOTS - 1;
01132 ho->cflag = 1;
01133 }
01134 IPCPDEBUG((LOG_INFO,
01135 "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
01136 ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
01137 break;
01138
01139 default:
01140 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));
01141 orc = CONFREJ;
01142 break;
01143 }
01144
01145 endswitch:
01146 if (orc == CONFACK &&
01147 rc != CONFACK) {
01148 continue;
01149 }
01150
01151 if (orc == CONFNAK) {
01152 if (reject_if_disagree) {
01153 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));
01154 orc = CONFREJ;
01155 } else {
01156 if (rc == CONFREJ) {
01157 continue;
01158 }
01159 if (rc == CONFACK) {
01160 rc = CONFNAK;
01161 ucp = inp;
01162 }
01163 }
01164 }
01165
01166 if (orc == CONFREJ &&
01167 rc != CONFREJ) {
01168 rc = CONFREJ;
01169 ucp = inp;
01170 }
01171
01172
01173 if (ucp != cip) {
01174 BCOPY(cip, ucp, cilen);
01175 }
01176
01177
01178 INCPTR(cilen, ucp);
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188 if (rc != CONFREJ && !ho->neg_addr &&
01189 wo->req_addr && !reject_if_disagree) {
01190 IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));
01191 if (rc == CONFACK) {
01192 rc = CONFNAK;
01193 ucp = inp;
01194 wo->req_addr = 0;
01195 }
01196 PUTCHAR(CI_ADDR, ucp);
01197 PUTCHAR(CILEN_ADDR, ucp);
01198 tl = ntohl(wo->hisaddr);
01199 PUTLONG(tl, ucp);
01200 }
01201
01202 *len = (int)(ucp - inp);
01203 IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
01204 return (rc);
01205 }
01206
01207
01208 #if 0
01209
01210
01211
01212
01213 static void
01214 ip_check_options(u_long localAddr)
01215 {
01216 ipcp_options *wo = &ipcp_wantoptions[0];
01217
01218
01219
01220
01221
01222 if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) {
01223 wo->accept_local = 1;
01224 wo->ouraddr = htonl(localAddr);
01225 }
01226 }
01227 #endif
01228
01229
01230
01231
01232
01233
01234
01235 static void
01236 ipcp_up(fsm *f)
01237 {
01238 u32_t mask;
01239 ipcp_options *ho = &ipcp_hisoptions[f->unit];
01240 ipcp_options *go = &ipcp_gotoptions[f->unit];
01241 ipcp_options *wo = &ipcp_wantoptions[f->unit];
01242
01243 np_up(f->unit, PPP_IP);
01244 IPCPDEBUG((LOG_INFO, "ipcp: up\n"));
01245
01246
01247
01248
01249 if (!ho->neg_addr) {
01250 ho->hisaddr = wo->hisaddr;
01251 }
01252
01253 if (ho->hisaddr == 0) {
01254 IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
01255 ipcp_close(f->unit, "Could not determine remote IP address");
01256 return;
01257 }
01258 if (go->ouraddr == 0) {
01259 IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
01260 ipcp_close(f->unit, "Could not determine local IP address");
01261 return;
01262 }
01263
01264 if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
01265
01266 }
01267
01268
01269
01270
01271 if (!auth_ip_addr(f->unit, ho->hisaddr)) {
01272 IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
01273 inet_ntoa(ho->hisaddr)));
01274 ipcp_close(f->unit, "Unauthorized remote IP address");
01275 return;
01276 }
01277
01278
01279 sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
01280
01281
01282
01283
01284 mask = GetMask(go->ouraddr);
01285
01286 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
01287 IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));
01288 ipcp_close(f->unit, "Interface configuration failed");
01289 return;
01290 }
01291
01292
01293 if (!sifup(f->unit)) {
01294 IPCPDEBUG((LOG_WARNING, "sifup failed\n"));
01295 ipcp_close(f->unit, "Interface configuration failed");
01296 return;
01297 }
01298
01299 sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
01300
01301
01302 if (ipcp_wantoptions[f->unit].default_route) {
01303 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) {
01304 default_route_set[f->unit] = 1;
01305 }
01306 }
01307
01308 IPCPDEBUG((LOG_NOTICE, "local IP address %s\n", inet_ntoa(go->ouraddr)));
01309 IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));
01310 if (go->dnsaddr[0]) {
01311 IPCPDEBUG((LOG_NOTICE, "primary DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
01312 }
01313 if (go->dnsaddr[1]) {
01314 IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
01315 }
01316 }
01317
01318
01319
01320
01321
01322
01323
01324
01325 static void
01326 ipcp_down(fsm *f)
01327 {
01328 IPCPDEBUG((LOG_INFO, "ipcp: down\n"));
01329 np_down(f->unit, PPP_IP);
01330 sifvjcomp(f->unit, 0, 0, 0);
01331
01332 sifdown(f->unit);
01333 ipcp_clear_addrs(f->unit);
01334 }
01335
01336
01337
01338
01339
01340 static void
01341 ipcp_clear_addrs(int unit)
01342 {
01343 u32_t ouraddr, hisaddr;
01344
01345 ouraddr = ipcp_gotoptions[unit].ouraddr;
01346 hisaddr = ipcp_hisoptions[unit].hisaddr;
01347 if (default_route_set[unit]) {
01348 cifdefaultroute(unit, ouraddr, hisaddr);
01349 default_route_set[unit] = 0;
01350 }
01351 cifaddr(unit, ouraddr, hisaddr);
01352 }
01353
01354
01355
01356
01357
01358 static void
01359 ipcp_finished(fsm *f)
01360 {
01361 np_finished(f->unit, PPP_IP);
01362 }
01363
01364 #if 0
01365 static int
01366 ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
01367 {
01368 LWIP_UNUSED_ARG(p);
01369 LWIP_UNUSED_ARG(plen);
01370 LWIP_UNUSED_ARG(printer);
01371 LWIP_UNUSED_ARG(arg);
01372 return 0;
01373 }
01374
01375
01376
01377
01378
01379
01380 #define IP_HDRLEN 20
01381 #define IP_OFFMASK 0x1fff
01382 #define IPPROTO_TCP 6
01383 #define TCP_HDRLEN 20
01384 #define TH_FIN 0x01
01385
01386
01387
01388
01389
01390
01391 #define net_short(x) (((x)[0] << 8) + (x)[1])
01392 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
01393 #define get_ipoff(x) net_short((unsigned char *)(x) + 6)
01394 #define get_ipproto(x) (((unsigned char *)(x))[9])
01395 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
01396 #define get_tcpflags(x) (((unsigned char *)(x))[13])
01397
01398 static int
01399 ip_active_pkt(u_char *pkt, int len)
01400 {
01401 u_char *tcp;
01402 int hlen;
01403
01404 len -= PPP_HDRLEN;
01405 pkt += PPP_HDRLEN;
01406 if (len < IP_HDRLEN) {
01407 return 0;
01408 }
01409 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
01410 return 0;
01411 }
01412 if (get_ipproto(pkt) != IPPROTO_TCP) {
01413 return 1;
01414 }
01415 hlen = get_iphl(pkt) * 4;
01416 if (len < hlen + TCP_HDRLEN) {
01417 return 0;
01418 }
01419 tcp = pkt + hlen;
01420 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) {
01421 return 0;
01422 }
01423 return 1;
01424 }
01425 #endif
01426
01427 #endif