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