1 /* 2 * PPP IP Control Protocol (IPCP) Module 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id$ 21 * 22 * TODO: 23 * o More RFC1772 backwoard compatibility 24 */ 25 #include "fsm.h" 26 #include "lcpproto.h" 27 #include "lcp.h" 28 #include "ipcp.h" 29 #include <netdb.h> 30 #include <netinet/in_systm.h> 31 #include <netinet/ip.h> 32 #include <arpa/inet.h> 33 #include <sys/socket.h> 34 #include "slcompress.h" 35 #include "os.h" 36 #include "phase.h" 37 #include "vars.h" 38 #include "alias.h" 39 40 extern void PutConfValue(); 41 extern void Prompt(); 42 extern struct in_addr ifnetmask; 43 44 struct ipcpstate IpcpInfo; 45 struct in_range DefMyAddress, DefHisAddress, DefTriggerAddress; 46 47 #ifdef MSEXT 48 struct in_addr ns_entries[2], nbns_entries[2]; 49 #endif /* MSEXT */ 50 51 static void IpcpSendConfigReq __P((struct fsm *)); 52 static void IpcpSendTerminateAck __P((struct fsm *)); 53 static void IpcpSendTerminateReq __P((struct fsm *)); 54 static void IpcpDecodeConfig __P((u_char *, int, int)); 55 static void IpcpLayerStart __P((struct fsm *)); 56 static void IpcpLayerFinish __P((struct fsm *)); 57 static void IpcpLayerUp __P((struct fsm *)); 58 static void IpcpLayerDown __P((struct fsm *)); 59 static void IpcpInitRestartCounter __P((struct fsm *)); 60 61 struct pppTimer IpcpReportTimer; 62 63 static int lastInOctets, lastOutOctets; 64 65 #define REJECTED(p, x) (p->his_reject & (1<<x)) 66 67 struct fsm IpcpFsm = { 68 "IPCP", 69 PROTO_IPCP, 70 IPCP_MAXCODE, 71 OPEN_ACTIVE, 72 ST_INITIAL, 73 0, 0, 0, 74 75 0, 76 { 0, 0, 0, NULL, NULL, NULL }, 77 78 IpcpLayerUp, 79 IpcpLayerDown, 80 IpcpLayerStart, 81 IpcpLayerFinish, 82 IpcpInitRestartCounter, 83 IpcpSendConfigReq, 84 IpcpSendTerminateReq, 85 IpcpSendTerminateAck, 86 IpcpDecodeConfig, 87 }; 88 89 static char *cftypes[] = { 90 "???", "IPADDRS", "COMPPROTO", "IPADDR", 91 }; 92 93 /* 94 * Function called every second. Updates connection period and idle period, 95 * also update LQR information. 96 */ 97 static void 98 IpcpReportFunc() 99 { 100 ipConnectSecs++; 101 if (lastInOctets == ipInOctets && lastOutOctets == ipOutOctets) 102 ipIdleSecs++; 103 lastInOctets = ipInOctets; 104 lastOutOctets = ipOutOctets; 105 StopTimer(&IpcpReportTimer); 106 IpcpReportTimer.state = TIMER_STOPPED; 107 StartTimer(&IpcpReportTimer); 108 } 109 110 static void 111 IpcpStartReport() 112 { 113 ipIdleSecs = ipConnectSecs = 0; 114 StopTimer(&IpcpReportTimer); 115 IpcpReportTimer.state = TIMER_STOPPED; 116 IpcpReportTimer.load = SECTICKS; 117 IpcpReportTimer.func = IpcpReportFunc; 118 StartTimer(&IpcpReportTimer); 119 } 120 121 void 122 ReportIpcpStatus() 123 { 124 struct ipcpstate *icp = &IpcpInfo; 125 struct fsm *fp = &IpcpFsm; 126 127 printf("%s [%s]\n", fp->name, StateNames[fp->state]); 128 printf(" his side: %s, %lx\n", 129 inet_ntoa(icp->his_ipaddr), icp->his_compproto); 130 printf(" my side: %s, %lx\n", 131 inet_ntoa(icp->want_ipaddr), icp->want_compproto); 132 printf("connected: %d secs, idle: %d secs\n\n", ipConnectSecs, ipIdleSecs); 133 printf("Defaults:\n"); 134 printf(" My Address: %s/%d\n", 135 inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width); 136 printf(" His Address: %s/%d\n", 137 inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width); 138 printf(" Negotiation: %s/%d\n", 139 inet_ntoa(DefTriggerAddress.ipaddr), DefTriggerAddress.width); 140 } 141 142 void 143 IpcpDefAddress() 144 { 145 struct hostent *hp; 146 char name[200]; 147 148 bzero(&DefMyAddress, sizeof(DefMyAddress)); 149 bzero(&DefHisAddress, sizeof(DefHisAddress)); 150 bzero(&DefTriggerAddress, sizeof(DefTriggerAddress)); 151 if (gethostname(name, sizeof(name)) == 0) { 152 hp = gethostbyname(name); 153 if (hp && hp->h_addrtype == AF_INET) { 154 bcopy(hp->h_addr, (char *)&DefMyAddress.ipaddr.s_addr, hp->h_length); 155 } 156 } 157 } 158 159 void 160 IpcpInit() 161 { 162 struct ipcpstate *icp = &IpcpInfo; 163 164 FsmInit(&IpcpFsm); 165 bzero(icp, sizeof(struct ipcpstate)); 166 if ((mode & MODE_DEDICATED) && !dstsystem) { 167 icp->want_ipaddr.s_addr = icp->his_ipaddr.s_addr = 0; 168 } else { 169 icp->want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr; 170 icp->his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr; 171 } 172 173 /* 174 * Some implementation of PPP are: 175 * Starting a negotiaion by require sending *special* value as my address, 176 * even though standard of PPP is defined full negotiation based. 177 * (e.g. "0.0.0.0" or Not "0.0.0.0") 178 */ 179 if ( icp->want_ipaddr.s_addr == 0 ) { 180 icp->want_ipaddr.s_addr = DefTriggerAddress.ipaddr.s_addr; 181 } 182 183 if (Enabled(ConfVjcomp)) 184 icp->want_compproto = (PROTO_VJCOMP << 16) | ((MAX_STATES - 1) << 8); 185 else 186 icp->want_compproto = 0; 187 icp->heis1172 = 0; 188 IpcpFsm.maxconfig = 10; 189 } 190 191 static void 192 IpcpInitRestartCounter(fp) 193 struct fsm *fp; 194 { 195 fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 196 fp->restart = 5; 197 } 198 199 static void 200 IpcpSendConfigReq(fp) 201 struct fsm *fp; 202 { 203 u_char *cp; 204 struct ipcpstate *icp = &IpcpInfo; 205 206 cp = ReqBuff; 207 LogPrintf(LOG_LCP_BIT, "%s: SendConfigReq\n", fp->name); 208 if (!DEV_IS_SYNC || !REJECTED(icp, TY_IPADDR)) 209 PutConfValue(&cp, cftypes, TY_IPADDR, 6, ntohl(icp->want_ipaddr.s_addr)); 210 if (icp->want_compproto && !REJECTED(icp, TY_COMPPROTO)) { 211 if (icp->heis1172) 212 PutConfValue(&cp, cftypes, TY_COMPPROTO, 4, icp->want_compproto >> 16); 213 else 214 PutConfValue(&cp, cftypes, TY_COMPPROTO, 6, icp->want_compproto); 215 } 216 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 217 } 218 219 static void 220 IpcpSendTerminateReq(fp) 221 struct fsm *fp; 222 { 223 /* XXX: No code yet */ 224 } 225 226 static void 227 IpcpSendTerminateAck(fp) 228 struct fsm *fp; 229 { 230 LogPrintf(LOG_LCP_BIT, " %s: SendTerminateAck\n", fp->name); 231 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 232 } 233 234 static void 235 IpcpLayerStart(fp) 236 struct fsm *fp; 237 { 238 LogPrintf(LOG_LCP_BIT, "%s: LayerStart.\n", fp->name); 239 } 240 241 static void 242 IpcpLayerFinish(fp) 243 struct fsm *fp; 244 { 245 LogPrintf(LOG_LCP_BIT, "%s: LayerFinish.\n", fp->name); 246 LcpClose(); 247 NewPhase(PHASE_TERMINATE); 248 } 249 250 static void 251 IpcpLayerDown(fp) 252 struct fsm *fp; 253 { 254 LogPrintf(LOG_LCP_BIT, "%s: LayerDown.\n", fp->name); 255 StopTimer(&IpcpReportTimer); 256 } 257 258 /* 259 * Called when IPCP has reached to OPEN state 260 */ 261 static void 262 IpcpLayerUp(fp) 263 struct fsm *fp; 264 { 265 char tbuff[100]; 266 267 #ifdef VERBOSE 268 fprintf(stderr, "%s: LayerUp(%d).\r\n", fp->name, fp->state); 269 #endif 270 Prompt(1); 271 LogPrintf(LOG_LCP_BIT, "%s: LayerUp.\n", fp->name); 272 snprintf(tbuff, sizeof(tbuff), "myaddr = %s ", 273 inet_ntoa(IpcpInfo.want_ipaddr)); 274 LogPrintf(LOG_LCP_BIT|LOG_LINK_BIT, " %s hisaddr = %s\n", tbuff, inet_ntoa(IpcpInfo.his_ipaddr)); 275 OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 276 OsLinkup(); 277 IpcpStartReport(); 278 StartIdleTimer(); 279 if (mode & MODE_ALIAS) 280 SetAliasAddress(IpcpInfo.want_ipaddr); 281 } 282 283 void 284 IpcpUp() 285 { 286 FsmUp(&IpcpFsm); 287 LogPrintf(LOG_LCP_BIT, "IPCP Up event!!\n"); 288 } 289 290 void 291 IpcpOpen() 292 { 293 FsmOpen(&IpcpFsm); 294 } 295 296 static int 297 AcceptableAddr(prange, ipaddr) 298 struct in_range *prange; 299 struct in_addr ipaddr; 300 { 301 #ifdef DEBUG 302 logprintf("requested = %x ", htonl(ipaddr.s_addr)); 303 logprintf("range = %x", htonl(prange->ipaddr.s_addr)); 304 logprintf("/%x\n", htonl(prange->mask.s_addr)); 305 logprintf("%x, %x\n", htonl(prange->ipaddr.s_addr & prange->mask.s_addr), 306 htonl(ipaddr.s_addr & prange->mask.s_addr)); 307 #endif 308 return((prange->ipaddr.s_addr & prange->mask.s_addr) == 309 (ipaddr.s_addr & prange->mask.s_addr)); 310 } 311 312 static void 313 IpcpDecodeConfig(cp, plen, mode) 314 u_char *cp; 315 int plen; 316 int mode; 317 { 318 int type, length; 319 u_long *lp, compproto; 320 struct compreq *pcomp; 321 struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req; 322 char tbuff[100]; 323 char tbuff2[100]; 324 325 ackp = AckBuff; 326 nakp = NakBuff; 327 rejp = RejBuff; 328 329 while (plen >= sizeof(struct fsmconfig)) { 330 if (plen < 0) 331 break; 332 type = *cp; 333 length = cp[1]; 334 if (type <= TY_IPADDR) 335 snprintf(tbuff, sizeof(tbuff), " %s[%d] ", cftypes[type], length); 336 else 337 snprintf(tbuff, sizeof(tbuff), " "); 338 339 switch (type) { 340 case TY_IPADDR: /* RFC1332 */ 341 lp = (u_long *)(cp + 2); 342 ipaddr.s_addr = *lp; 343 LogPrintf(LOG_LCP_BIT, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 344 345 switch (mode) { 346 case MODE_REQ: 347 if (!AcceptableAddr(&DefHisAddress, ipaddr)) { 348 /* 349 * If destination address is not acceptable, insist to use 350 * what we want to use. 351 */ 352 bcopy(cp, nakp, 2); 353 bcopy(&IpcpInfo.his_ipaddr.s_addr, nakp+2, length); 354 nakp += length; 355 break; 356 357 } 358 IpcpInfo.his_ipaddr = ipaddr; 359 bcopy(cp, ackp, length); 360 ackp += length; 361 break; 362 case MODE_NAK: 363 if (AcceptableAddr(&DefMyAddress, ipaddr)) { 364 /* 365 * Use address suggested by peer. 366 */ 367 snprintf(tbuff2, sizeof(tbuff2), "%s changing address: %s ", tbuff, inet_ntoa(IpcpInfo.want_ipaddr)); 368 LogPrintf(LOG_LCP_BIT, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 369 IpcpInfo.want_ipaddr = ipaddr; 370 } 371 break; 372 case MODE_REJ: 373 IpcpInfo.his_reject |= (1 << type); 374 break; 375 } 376 break; 377 case TY_COMPPROTO: 378 lp = (u_long *)(cp + 2); 379 compproto = htonl(*lp); 380 LogPrintf(LOG_LCP_BIT, "%s %08x\n", tbuff, compproto); 381 382 switch (mode) { 383 case MODE_REQ: 384 if (!Acceptable(ConfVjcomp)) { 385 bcopy(cp, rejp, length); 386 rejp += length; 387 } else { 388 pcomp = (struct compreq *)(cp + 2); 389 switch (length) { 390 case 4: /* RFC1172 */ 391 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 392 logprintf("** Peer is speaking RFC1172 compression protocol **\n"); 393 IpcpInfo.heis1172 = 1; 394 IpcpInfo.his_compproto = compproto; 395 bcopy(cp, ackp, length); 396 ackp += length; 397 } else { 398 bcopy(cp, nakp, 2); 399 pcomp->proto = htons(PROTO_VJCOMP); 400 bcopy(&pcomp, nakp + 2, 2); 401 nakp += length; 402 } 403 break; 404 case 6: /* RFC1332 */ 405 if (ntohs(pcomp->proto) == PROTO_VJCOMP 406 && pcomp->slots < MAX_STATES && pcomp->slots > 2) { 407 IpcpInfo.his_compproto = compproto; 408 IpcpInfo.heis1172 = 0; 409 bcopy(cp, ackp, length); 410 ackp += length; 411 } else { 412 bcopy(cp, nakp, 2); 413 pcomp->proto = htons(PROTO_VJCOMP); 414 pcomp->slots = MAX_STATES - 1; 415 pcomp->compcid = 0; 416 bcopy(&pcomp, nakp + 2, sizeof(pcomp)); 417 nakp += length; 418 } 419 break; 420 default: 421 bcopy(cp, rejp, length); 422 rejp += length; 423 break; 424 } 425 } 426 break; 427 case MODE_NAK: 428 LogPrintf(LOG_LCP_BIT, "%s changing compproto: %08x --> %08x\n", 429 tbuff, IpcpInfo.want_compproto, compproto); 430 IpcpInfo.want_compproto = compproto; 431 break; 432 case MODE_REJ: 433 IpcpInfo.his_reject |= (1 << type); 434 break; 435 } 436 break; 437 case TY_IPADDRS: /* RFC1172 */ 438 lp = (u_long *)(cp + 2); 439 ipaddr.s_addr = *lp; 440 lp = (u_long *)(cp + 6); 441 dstipaddr.s_addr = *lp; 442 LogPrintf(LOG_LCP_BIT, "%s %s, ", tbuff, inet_ntoa(ipaddr)); 443 LogPrintf(LOG_LCP_BIT, "%s\n", inet_ntoa(dstipaddr)); 444 445 switch (mode) { 446 case MODE_REQ: 447 IpcpInfo.his_ipaddr = ipaddr; 448 IpcpInfo.want_ipaddr = dstipaddr; 449 bcopy(cp, ackp, length); 450 ackp += length; 451 break; 452 case MODE_NAK: 453 LogPrintf(LOG_LCP_BIT, "%s changing address: %s ", 454 tbuff, inet_ntoa(IpcpInfo.want_ipaddr)); 455 LogPrintf(LOG_LCP_BIT, "--> %s\n", inet_ntoa(ipaddr)); 456 IpcpInfo.want_ipaddr = ipaddr; 457 IpcpInfo.his_ipaddr = dstipaddr; 458 break; 459 case MODE_REJ: 460 IpcpInfo.his_reject |= (1 << type); 461 break; 462 } 463 break; 464 465 /* 466 * MS extensions for MS's PPP 467 */ 468 469 #ifdef MSEXT 470 case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */ 471 case TY_SECONDARY_DNS: 472 if( !Enabled( ConfMSExt ) ) { 473 LogPrintf( LOG_LCP, "MS NS req - rejected - msext disabled\n" ); 474 IpcpInfo.my_reject |= ( 1 << type ); 475 bcopy(cp, rejp, length); 476 rejp += length; 477 break; 478 } 479 switch( mode ){ 480 case MODE_REQ: 481 lp = (u_long *)(cp + 2); 482 dnsstuff.s_addr = *lp; 483 ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS)?1:0)].s_addr; 484 if( dnsstuff.s_addr != ms_info_req.s_addr ) 485 { 486 /* 487 So the client has got the DNS stuff wrong (first request) 488 so well tell 'em how it is 489 */ 490 bcopy( cp, nakp, 2 ); /* copy first two (type/length) */ 491 LogPrintf( LOG_LCP, "MS NS req %d:%s->%s - nak\n", 492 type, 493 inet_ntoa( dnsstuff ), 494 inet_ntoa( ms_info_req )); 495 bcopy( &ms_info_req, nakp+2, length ); 496 nakp += length; 497 break; 498 } 499 /* 500 Otherwise they have it right (this time) so we send 501 a ack packet back confirming it... end of story 502 */ 503 LogPrintf( LOG_LCP, "MS NS req %d:%s ok - ack\n", 504 type, 505 inet_ntoa( ms_info_req )); 506 bcopy( cp, ackp, length ); 507 ackp += length; 508 break; 509 case MODE_NAK: /* what does this mean?? */ 510 LogPrintf(LOG_LCP, "MS NS req %d - NAK??\n", type ); 511 break; 512 case MODE_REJ: /* confused?? me to :) */ 513 LogPrintf(LOG_LCP, "MS NS req %d - REJ??\n", type ); 514 break; 515 } 516 break; 517 518 case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */ 519 case TY_SECONDARY_NBNS: 520 if( !Enabled( ConfMSExt ) ) { 521 LogPrintf( LOG_LCP, "MS NBNS req - rejected - msext disabled\n" ); 522 IpcpInfo.my_reject |= ( 1 << type ); 523 bcopy( cp, rejp, length ); 524 rejp += length; 525 break; 526 } 527 switch( mode ){ 528 case MODE_REQ: 529 lp = (u_long *)(cp + 2); 530 dnsstuff.s_addr = *lp; 531 ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS)?1:0)].s_addr; 532 if( dnsstuff.s_addr != ms_info_req.s_addr ) 533 { 534 bcopy( cp, nakp, 2 ); 535 bcopy( &ms_info_req.s_addr , nakp+2, length ); 536 LogPrintf( LOG_LCP, "MS NBNS req %d:%s->%s - nak\n", 537 type, 538 inet_ntoa( dnsstuff ), 539 inet_ntoa( ms_info_req )); 540 nakp += length; 541 break; 542 } 543 LogPrintf( LOG_LCP, "MS NBNS req %d:%s ok - ack\n", 544 type, 545 inet_ntoa( ms_info_req )); 546 bcopy( cp, ackp, length ); 547 ackp += length; 548 break; 549 case MODE_NAK: 550 LogPrintf( LOG_LCP, "MS NBNS req %d - NAK??\n", type ); 551 break; 552 case MODE_REJ: 553 LogPrintf( LOG_LCP, "MS NBNS req %d - REJ??\n", type ); 554 break; 555 } 556 break; 557 558 #endif /* MSEXT */ 559 560 default: 561 IpcpInfo.my_reject |= (1 << type); 562 bcopy(cp, rejp, length); 563 rejp += length; 564 break; 565 } 566 plen -= length; 567 cp += length; 568 } 569 } 570 571 void 572 IpcpInput(struct mbuf *bp) 573 { 574 FsmInput(&IpcpFsm, bp); 575 } 576