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: ipcp.c,v 1.61 1998/06/27 16:24:52 brian Exp $ 21 * 22 * TODO: 23 * o More RFC1772 backward compatibility 24 */ 25 #include <sys/param.h> 26 #include <netinet/in_systm.h> 27 #include <netinet/in.h> 28 #include <netinet/ip.h> 29 #include <arpa/inet.h> 30 #include <sys/socket.h> 31 #include <netdb.h> 32 #include <net/if.h> 33 #include <sys/sockio.h> 34 #include <sys/un.h> 35 36 #ifndef NOALIAS 37 #include <alias.h> 38 #endif 39 #include <fcntl.h> 40 #include <resolv.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <sys/errno.h> 44 #include <termios.h> 45 #include <unistd.h> 46 47 #include "defs.h" 48 #include "command.h" 49 #include "mbuf.h" 50 #include "log.h" 51 #include "timer.h" 52 #include "fsm.h" 53 #include "lcpproto.h" 54 #include "lcp.h" 55 #include "iplist.h" 56 #include "throughput.h" 57 #include "slcompress.h" 58 #include "ipcp.h" 59 #include "filter.h" 60 #include "descriptor.h" 61 #include "vjcomp.h" 62 #include "lqr.h" 63 #include "hdlc.h" 64 #include "async.h" 65 #include "ccp.h" 66 #include "link.h" 67 #include "physical.h" 68 #include "mp.h" 69 #include "bundle.h" 70 #include "id.h" 71 #include "arp.h" 72 #include "systems.h" 73 #include "prompt.h" 74 #include "route.h" 75 76 #undef REJECTED 77 #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 78 #define issep(ch) ((ch) == ' ' || (ch) == '\t') 79 #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 80 81 struct compreq { 82 u_short proto; 83 u_char slots; 84 u_char compcid; 85 }; 86 87 static int IpcpLayerUp(struct fsm *); 88 static void IpcpLayerDown(struct fsm *); 89 static void IpcpLayerStart(struct fsm *); 90 static void IpcpLayerFinish(struct fsm *); 91 static void IpcpInitRestartCounter(struct fsm *); 92 static void IpcpSendConfigReq(struct fsm *); 93 static void IpcpSentTerminateReq(struct fsm *); 94 static void IpcpSendTerminateAck(struct fsm *, u_char); 95 static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 96 struct fsm_decode *); 97 98 static struct fsm_callbacks ipcp_Callbacks = { 99 IpcpLayerUp, 100 IpcpLayerDown, 101 IpcpLayerStart, 102 IpcpLayerFinish, 103 IpcpInitRestartCounter, 104 IpcpSendConfigReq, 105 IpcpSentTerminateReq, 106 IpcpSendTerminateAck, 107 IpcpDecodeConfig, 108 fsm_NullRecvResetReq, 109 fsm_NullRecvResetAck 110 }; 111 112 static const char *cftypes[] = { 113 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 114 "???", 115 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 116 "COMPPROTO", /* 2: IP-Compression-Protocol */ 117 "IPADDR", /* 3: IP-Address */ 118 }; 119 120 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 121 122 static const char *cftypes128[] = { 123 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 124 "???", 125 "PRIDNS", /* 129: Primary DNS Server Address */ 126 "PRINBNS", /* 130: Primary NBNS Server Address */ 127 "SECDNS", /* 131: Secondary DNS Server Address */ 128 "SECNBNS", /* 132: Secondary NBNS Server Address */ 129 }; 130 131 #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 132 133 void 134 ipcp_AddInOctets(struct ipcp *ipcp, int n) 135 { 136 throughput_addin(&ipcp->throughput, n); 137 } 138 139 void 140 ipcp_AddOutOctets(struct ipcp *ipcp, int n) 141 { 142 throughput_addout(&ipcp->throughput, n); 143 } 144 145 static void 146 getdns(struct ipcp *ipcp, struct in_addr addr[2]) 147 { 148 FILE *fp; 149 150 addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 151 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 152 char buf[LINE_LEN], *cp, *end; 153 int n; 154 155 n = 0; 156 buf[sizeof buf - 1] = '\0'; 157 while (fgets(buf, sizeof buf - 1, fp)) { 158 if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 159 for (cp = buf + 11; issep(*cp); cp++) 160 ; 161 for (end = cp; isip(*end); end++) 162 ; 163 *end = '\0'; 164 if (inet_aton(cp, addr+n) && ++n == 2) 165 break; 166 } 167 } 168 if (n == 1) 169 addr[1] = addr[0]; 170 fclose(fp); 171 } 172 } 173 174 static int 175 setdns(struct ipcp *ipcp, struct in_addr addr[2]) 176 { 177 FILE *fp; 178 char wbuf[LINE_LEN + 54]; 179 int wlen; 180 181 if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 182 struct in_addr old[2]; 183 184 getdns(ipcp, old); 185 if (addr[0].s_addr == INADDR_ANY) 186 addr[0] = old[0]; 187 if (addr[1].s_addr == INADDR_ANY) 188 addr[1] = old[1]; 189 } 190 191 if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 192 log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 193 _PATH_RESCONF); 194 return 0; 195 } 196 197 wlen = 0; 198 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 199 char buf[LINE_LEN]; 200 int len; 201 202 buf[sizeof buf - 1] = '\0'; 203 while (fgets(buf, sizeof buf - 1, fp)) { 204 if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 205 len = strlen(buf); 206 if (len > sizeof wbuf - wlen) { 207 log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 208 _PATH_RESCONF, LINE_LEN); 209 fclose(fp); 210 return 0; 211 } 212 memcpy(wbuf + wlen, buf, len); 213 wlen += len; 214 } 215 } 216 fclose(fp); 217 } 218 219 if (addr[0].s_addr != INADDR_ANY) { 220 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 221 inet_ntoa(addr[0])); 222 log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 223 wlen += strlen(wbuf + wlen); 224 } 225 226 if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 227 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 228 inet_ntoa(addr[1])); 229 log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 230 wlen += strlen(wbuf + wlen); 231 } 232 233 if (wlen) { 234 int fd; 235 236 if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 237 if (write(fd, wbuf, wlen) != wlen) { 238 log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 239 close(fd); 240 return 0; 241 } 242 if (ftruncate(fd, wlen) == -1) { 243 log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 244 close(fd); 245 return 0; 246 } 247 close(fd); 248 } else { 249 log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 250 return 0; 251 } 252 } 253 254 return 1; 255 } 256 257 int 258 ipcp_Show(struct cmdargs const *arg) 259 { 260 struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 261 262 prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 263 State2Nam(ipcp->fsm.state)); 264 if (ipcp->fsm.state == ST_OPENED) { 265 prompt_Printf(arg->prompt, " His side: %s, %s\n", 266 inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 267 prompt_Printf(arg->prompt, " My side: %s, %s\n", 268 inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 269 } 270 271 if (ipcp->route) { 272 prompt_Printf(arg->prompt, "\n"); 273 route_ShowSticky(arg->prompt, ipcp->route); 274 } 275 276 prompt_Printf(arg->prompt, "\nDefaults:\n"); 277 prompt_Printf(arg->prompt, " My Address: %s/%d", 278 inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 279 280 if (ipcp->cfg.HaveTriggerAddress) 281 prompt_Printf(arg->prompt, " (trigger with %s)", 282 inet_ntoa(ipcp->cfg.TriggerAddress)); 283 prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot " 284 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 285 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 286 287 if (iplist_isvalid(&ipcp->cfg.peer_list)) 288 prompt_Printf(arg->prompt, " His Address: %s\n", 289 ipcp->cfg.peer_list.src); 290 else 291 prompt_Printf(arg->prompt, " His Address: %s/%d\n", 292 inet_ntoa(ipcp->cfg.peer_range.ipaddr), 293 ipcp->cfg.peer_range.width); 294 295 prompt_Printf(arg->prompt, " DNS: %s, ", 296 inet_ntoa(ipcp->cfg.ns.dns[0])); 297 prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 298 command_ShowNegval(ipcp->cfg.ns.dns_neg)); 299 prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 300 inet_ntoa(ipcp->cfg.ns.nbns[0])); 301 prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 302 303 prompt_Printf(arg->prompt, "\n"); 304 throughput_disp(&ipcp->throughput, arg->prompt); 305 306 return 0; 307 } 308 309 int 310 ipcp_vjset(struct cmdargs const *arg) 311 { 312 if (arg->argc != arg->argn+2) 313 return -1; 314 if (!strcasecmp(arg->argv[arg->argn], "slots")) { 315 int slots; 316 317 slots = atoi(arg->argv[arg->argn+1]); 318 if (slots < 4 || slots > 16) 319 return 1; 320 arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 321 return 0; 322 } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 323 if (!strcasecmp(arg->argv[arg->argn+1], "on")) 324 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 325 else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 326 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 327 else 328 return 2; 329 return 0; 330 } 331 return -1; 332 } 333 334 void 335 ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 336 const struct fsm_parent *parent) 337 { 338 struct hostent *hp; 339 char name[MAXHOSTNAMELEN]; 340 static const char *timer_names[] = 341 {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 342 343 fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP, 344 bundle, l, parent, &ipcp_Callbacks, timer_names); 345 346 ipcp->route = NULL; 347 ipcp->cfg.vj.slots = DEF_VJ_STATES; 348 ipcp->cfg.vj.slotcomp = 1; 349 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 350 if (gethostname(name, sizeof name) == 0) { 351 hp = gethostbyname(name); 352 if (hp && hp->h_addrtype == AF_INET) { 353 memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 354 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 355 ipcp->cfg.peer_range.width = 32; 356 } 357 } 358 ipcp->cfg.netmask.s_addr = INADDR_ANY; 359 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 360 iplist_setsrc(&ipcp->cfg.peer_list, ""); 361 ipcp->cfg.HaveTriggerAddress = 0; 362 363 ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 364 ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 365 ipcp->cfg.ns.dns_neg = 0; 366 ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 367 ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 368 369 ipcp->cfg.fsmretry = DEF_FSMRETRY; 370 ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 371 372 memset(&ipcp->vj, '\0', sizeof ipcp->vj); 373 374 ipcp->my_ifip.s_addr = INADDR_ANY; 375 ipcp->peer_ifip.s_addr = INADDR_ANY; 376 377 throughput_init(&ipcp->throughput); 378 ipcp_Setup(ipcp); 379 } 380 381 void 382 ipcp_SetLink(struct ipcp *ipcp, struct link *l) 383 { 384 ipcp->fsm.link = l; 385 } 386 387 void 388 ipcp_Setup(struct ipcp *ipcp) 389 { 390 int pos; 391 392 ipcp->fsm.open_mode = 0; 393 ipcp->fsm.maxconfig = 10; 394 395 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 396 if (ipcp->my_ifip.s_addr != INADDR_ANY && 397 (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1) 398 ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos); 399 else 400 ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 401 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 402 ipcp->cfg.peer_range.width = 32; 403 } 404 405 ipcp->heis1172 = 0; 406 407 ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 408 ipcp->peer_compproto = 0; 409 410 if (ipcp->cfg.HaveTriggerAddress) { 411 /* 412 * Some implementations of PPP require that we send a 413 * *special* value as our address, even though the rfc specifies 414 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 415 */ 416 ipcp->my_ip = ipcp->cfg.TriggerAddress; 417 log_Printf(LogIPCP, "Using trigger address %s\n", 418 inet_ntoa(ipcp->cfg.TriggerAddress)); 419 } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) == 420 (ipcp->cfg.my_range.ipaddr.s_addr & 421 ipcp->cfg.my_range.mask.s_addr)) 422 /* 423 * Otherwise, if we've been assigned an IP number before, we really 424 * want to keep the same IP number so that we can keep any existing 425 * connections that are bound to that IP. 426 */ 427 ipcp->my_ip = ipcp->my_ifip; 428 else 429 ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 430 431 if (IsEnabled(ipcp->cfg.vj.neg)) 432 ipcp->my_compproto = (PROTO_VJCOMP << 16) + 433 ((ipcp->cfg.vj.slots - 1) << 8) + 434 ipcp->cfg.vj.slotcomp; 435 else 436 ipcp->my_compproto = 0; 437 sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 438 439 ipcp->peer_reject = 0; 440 ipcp->my_reject = 0; 441 } 442 443 static int 444 ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 445 struct in_addr hisaddr, int silent) 446 { 447 struct sockaddr_in *sock_in; 448 int s; 449 u_int32_t mask, addr; 450 struct ifaliasreq ifra; 451 452 /* If given addresses are alreay set, then ignore this request */ 453 if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr && 454 bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr) 455 return 0; 456 457 ipcp_CleanInterface(&bundle->ncp.ipcp); 458 459 s = ID0socket(AF_INET, SOCK_DGRAM, 0); 460 if (s < 0) { 461 log_Printf(LogERROR, "SetIPaddress: socket(): %s\n", strerror(errno)); 462 return (-1); 463 } 464 465 memset(&ifra, '\0', sizeof ifra); 466 strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1); 467 ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 468 469 /* Set interface address */ 470 sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 471 sock_in->sin_family = AF_INET; 472 sock_in->sin_addr = myaddr; 473 sock_in->sin_len = sizeof *sock_in; 474 475 /* Set destination address */ 476 sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 477 sock_in->sin_family = AF_INET; 478 sock_in->sin_addr = hisaddr; 479 sock_in->sin_len = sizeof *sock_in; 480 481 addr = ntohl(myaddr.s_addr); 482 if (IN_CLASSA(addr)) 483 mask = IN_CLASSA_NET; 484 else if (IN_CLASSB(addr)) 485 mask = IN_CLASSB_NET; 486 else 487 mask = IN_CLASSC_NET; 488 489 /* if subnet mask is given, use it instead of class mask */ 490 if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 491 (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask) 492 mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr); 493 494 sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 495 sock_in->sin_family = AF_INET; 496 sock_in->sin_addr.s_addr = htonl(mask); 497 sock_in->sin_len = sizeof *sock_in; 498 499 if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 500 if (!silent) 501 log_Printf(LogERROR, "SetIPaddress: ioctl(SIOCAIFADDR): %s\n", 502 strerror(errno)); 503 close(s); 504 return (-1); 505 } 506 507 if (Enabled(bundle, OPT_SROUTES)) 508 route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 509 510 bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr; 511 bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr; 512 513 if (Enabled(bundle, OPT_PROXY)) 514 arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, s); 515 516 close(s); 517 return (0); 518 } 519 520 static struct in_addr 521 ChooseHisAddr(struct bundle *bundle, const struct in_addr gw) 522 { 523 struct in_addr try; 524 u_long f; 525 526 for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 527 try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 528 log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 529 f, inet_ntoa(try)); 530 if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 531 log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 532 break; 533 } 534 } 535 536 if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 537 log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 538 try.s_addr = INADDR_ANY; 539 } 540 541 return try; 542 } 543 544 static void 545 IpcpInitRestartCounter(struct fsm * fp) 546 { 547 /* Set fsm timer load */ 548 struct ipcp *ipcp = fsm2ipcp(fp); 549 550 fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS; 551 fp->restart = 5; 552 } 553 554 static void 555 IpcpSendConfigReq(struct fsm *fp) 556 { 557 /* Send config REQ please */ 558 struct physical *p = link2physical(fp->link); 559 struct ipcp *ipcp = fsm2ipcp(fp); 560 u_char buff[24]; 561 struct lcp_opt *o; 562 563 o = (struct lcp_opt *)buff; 564 565 if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 566 *(u_int32_t *)o->data = ipcp->my_ip.s_addr; 567 INC_LCP_OPT(TY_IPADDR, 6, o); 568 } 569 570 if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 571 if (ipcp->heis1172) { 572 *(u_int32_t *)o->data = htons(PROTO_VJCOMP); 573 INC_LCP_OPT(TY_COMPPROTO, 4, o); 574 } else { 575 *(u_int32_t *)o->data = htonl(ipcp->my_compproto); 576 INC_LCP_OPT(TY_COMPPROTO, 6, o); 577 } 578 } 579 580 if (IsEnabled(ipcp->cfg.ns.dns_neg) && 581 !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 582 !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 583 struct in_addr dns[2]; 584 getdns(ipcp, dns); 585 *(u_int32_t *)o->data = dns[0].s_addr; 586 INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 587 *(u_int32_t *)o->data = dns[1].s_addr; 588 INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 589 } 590 591 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 592 } 593 594 static void 595 IpcpSentTerminateReq(struct fsm * fp) 596 { 597 /* Term REQ just sent by FSM */ 598 } 599 600 static void 601 IpcpSendTerminateAck(struct fsm *fp, u_char id) 602 { 603 /* Send Term ACK please */ 604 fsm_Output(fp, CODE_TERMACK, id, NULL, 0); 605 } 606 607 static void 608 IpcpLayerStart(struct fsm *fp) 609 { 610 /* We're about to start up ! */ 611 struct ipcp *ipcp = fsm2ipcp(fp); 612 613 log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 614 throughput_start(&ipcp->throughput, "IPCP throughput", 615 Enabled(fp->bundle, OPT_THROUGHPUT)); 616 617 /* This is where we should be setting up the interface in AUTO mode */ 618 } 619 620 static void 621 IpcpLayerFinish(struct fsm *fp) 622 { 623 /* We're now down */ 624 struct ipcp *ipcp = fsm2ipcp(fp); 625 626 log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 627 throughput_stop(&ipcp->throughput); 628 throughput_log(&ipcp->throughput, LogIPCP, NULL); 629 } 630 631 void 632 ipcp_CleanInterface(struct ipcp *ipcp) 633 { 634 struct ifaliasreq ifra; 635 struct sockaddr_in *me, *peer; 636 int s; 637 638 s = ID0socket(AF_INET, SOCK_DGRAM, 0); 639 if (s < 0) { 640 log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno)); 641 return; 642 } 643 644 route_Clean(ipcp->fsm.bundle, ipcp->route); 645 646 if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 647 arp_ClearProxy(ipcp->fsm.bundle, ipcp->peer_ifip, s); 648 649 if (ipcp->my_ifip.s_addr != INADDR_ANY || 650 ipcp->peer_ifip.s_addr != INADDR_ANY) { 651 memset(&ifra, '\0', sizeof ifra); 652 strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifp.Name, 653 sizeof ifra.ifra_name - 1); 654 ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 655 me = (struct sockaddr_in *)&ifra.ifra_addr; 656 peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; 657 me->sin_family = peer->sin_family = AF_INET; 658 me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); 659 me->sin_addr = ipcp->my_ifip; 660 peer->sin_addr = ipcp->peer_ifip; 661 if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) 662 log_Printf(LogERROR, "ipcp_CleanInterface: ioctl(SIOCDIFADDR): %s\n", 663 strerror(errno)); 664 ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY; 665 } 666 667 close(s); 668 } 669 670 static void 671 IpcpLayerDown(struct fsm *fp) 672 { 673 /* About to come down */ 674 struct ipcp *ipcp = fsm2ipcp(fp); 675 const char *s; 676 677 s = inet_ntoa(ipcp->peer_ifip); 678 log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 679 680 /* 681 * XXX this stuff should really live in the FSM. Our config should 682 * associate executable sections in files with events. 683 */ 684 if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 685 if (bundle_GetLabel(fp->bundle)) { 686 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 687 LINKDOWNFILE, NULL, NULL) < 0) 688 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 689 } else 690 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 691 } 692 693 if (!(ipcp->fsm.bundle->phys_type.all & PHYS_AUTO)) 694 ipcp_CleanInterface(ipcp); 695 696 ipcp_Setup(ipcp); 697 } 698 699 int 700 ipcp_InterfaceUp(struct ipcp *ipcp) 701 { 702 if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 703 log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 704 return 0; 705 } 706 707 #ifndef NOALIAS 708 if (ipcp->fsm.bundle->AliasEnabled) 709 PacketAliasSetAddress(ipcp->my_ip); 710 #endif 711 712 return 1; 713 } 714 715 static int 716 IpcpLayerUp(struct fsm *fp) 717 { 718 /* We're now up */ 719 struct ipcp *ipcp = fsm2ipcp(fp); 720 char tbuff[100]; 721 722 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 723 snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 724 log_Printf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip)); 725 726 if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 727 sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 728 729 if (!ipcp_InterfaceUp(ipcp)) 730 return 0; 731 732 /* 733 * XXX this stuff should really live in the FSM. Our config should 734 * associate executable sections in files with events. 735 */ 736 if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, 737 NULL, NULL) < 0) { 738 if (bundle_GetLabel(fp->bundle)) { 739 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 740 LINKUPFILE, NULL, NULL) < 0) 741 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 742 } else 743 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 744 } 745 746 log_DisplayPrompts(); 747 return 1; 748 } 749 750 static int 751 AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 752 { 753 /* Is the given IP in the given range ? */ 754 return (prange->ipaddr.s_addr & prange->mask.s_addr) == 755 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 756 } 757 758 static void 759 IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 760 struct fsm_decode *dec) 761 { 762 /* Deal with incoming PROTO_IPCP */ 763 struct ipcp *ipcp = fsm2ipcp(fp); 764 int type, length; 765 u_int32_t compproto; 766 struct compreq *pcomp; 767 struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 768 char tbuff[100], tbuff2[100]; 769 int gotdns, gotdnsnak; 770 771 gotdns = 0; 772 gotdnsnak = 0; 773 dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 774 775 while (plen >= sizeof(struct fsmconfig)) { 776 type = *cp; 777 length = cp[1]; 778 779 if (length == 0) { 780 log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 781 break; 782 } 783 784 if (type < NCFTYPES) 785 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 786 else if (type > 128 && type < 128 + NCFTYPES128) 787 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 788 else 789 snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 790 791 switch (type) { 792 case TY_IPADDR: /* RFC1332 */ 793 ipaddr.s_addr = *(u_int32_t *)(cp + 2); 794 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 795 796 switch (mode_type) { 797 case MODE_REQ: 798 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 799 if (ipaddr.s_addr == INADDR_ANY || 800 iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 801 ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 802 ipaddr, 1)) { 803 log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 804 inet_ntoa(ipaddr)); 805 if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 806 /* 807 * If we've already got a valid address configured for the peer 808 * (in AUTO mode), try NAKing with that so that we don't 809 * have to upset things too much. 810 */ 811 ipcp->peer_ip = ipcp->peer_ifip; 812 else 813 /* Just pick an IP number from our list */ 814 ipcp->peer_ip = ChooseHisAddr 815 (fp->bundle, ipcp->cfg.my_range.ipaddr); 816 817 if (ipcp->peer_ip.s_addr == INADDR_ANY) { 818 memcpy(dec->rejend, cp, length); 819 dec->rejend += length; 820 } else { 821 memcpy(dec->nakend, cp, 2); 822 memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 823 dec->nakend += length; 824 } 825 break; 826 } 827 } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 828 /* 829 * If destination address is not acceptable, NAK with what we 830 * want to use. 831 */ 832 memcpy(dec->nakend, cp, 2); 833 if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 834 (ipcp->cfg.peer_range.ipaddr.s_addr & 835 ipcp->cfg.peer_range.mask.s_addr)) 836 /* We prefer the already-configured address */ 837 memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 838 else 839 memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 840 dec->nakend += length; 841 break; 842 } 843 ipcp->peer_ip = ipaddr; 844 memcpy(dec->ackend, cp, length); 845 dec->ackend += length; 846 break; 847 case MODE_NAK: 848 if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 849 /* Use address suggested by peer */ 850 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 851 inet_ntoa(ipcp->my_ip)); 852 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 853 ipcp->my_ip = ipaddr; 854 } else { 855 log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 856 "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 857 fsm_Close(&ipcp->fsm); 858 } 859 break; 860 case MODE_REJ: 861 ipcp->peer_reject |= (1 << type); 862 break; 863 } 864 break; 865 case TY_COMPPROTO: 866 compproto = htonl(*(u_int32_t *)(cp + 2)); 867 log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 868 869 switch (mode_type) { 870 case MODE_REQ: 871 if (!IsAccepted(ipcp->cfg.vj.neg)) { 872 memcpy(dec->rejend, cp, length); 873 dec->rejend += length; 874 } else { 875 pcomp = (struct compreq *) (cp + 2); 876 switch (length) { 877 case 4: /* RFC1172 */ 878 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 879 log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 880 ipcp->heis1172 = 1; 881 ipcp->peer_compproto = compproto; 882 memcpy(dec->ackend, cp, length); 883 dec->ackend += length; 884 } else { 885 memcpy(dec->nakend, cp, 2); 886 pcomp->proto = htons(PROTO_VJCOMP); 887 memcpy(dec->nakend+2, &pcomp, 2); 888 dec->nakend += length; 889 } 890 break; 891 case 6: /* RFC1332 */ 892 if (ntohs(pcomp->proto) == PROTO_VJCOMP 893 && pcomp->slots <= MAX_VJ_STATES 894 && pcomp->slots >= MIN_VJ_STATES) { 895 ipcp->peer_compproto = compproto; 896 ipcp->heis1172 = 0; 897 memcpy(dec->ackend, cp, length); 898 dec->ackend += length; 899 } else { 900 memcpy(dec->nakend, cp, 2); 901 pcomp->proto = htons(PROTO_VJCOMP); 902 pcomp->slots = DEF_VJ_STATES; 903 pcomp->compcid = 0; 904 memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 905 dec->nakend += length; 906 } 907 break; 908 default: 909 memcpy(dec->rejend, cp, length); 910 dec->rejend += length; 911 break; 912 } 913 } 914 break; 915 case MODE_NAK: 916 log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 917 tbuff, ipcp->my_compproto, compproto); 918 ipcp->my_compproto = compproto; 919 break; 920 case MODE_REJ: 921 ipcp->peer_reject |= (1 << type); 922 break; 923 } 924 break; 925 case TY_IPADDRS: /* RFC1172 */ 926 ipaddr.s_addr = *(u_int32_t *)(cp + 2); 927 dstipaddr.s_addr = *(u_int32_t *)(cp + 6); 928 snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 929 log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 930 931 switch (mode_type) { 932 case MODE_REQ: 933 ipcp->peer_ip = ipaddr; 934 ipcp->my_ip = dstipaddr; 935 memcpy(dec->ackend, cp, length); 936 dec->ackend += length; 937 break; 938 case MODE_NAK: 939 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 940 inet_ntoa(ipcp->my_ip)); 941 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 942 ipcp->my_ip = ipaddr; 943 ipcp->peer_ip = dstipaddr; 944 break; 945 case MODE_REJ: 946 ipcp->peer_reject |= (1 << type); 947 break; 948 } 949 break; 950 951 case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 952 case TY_SECONDARY_DNS: 953 ipaddr.s_addr = *(u_int32_t *)(cp + 2); 954 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 955 956 switch (mode_type) { 957 case MODE_REQ: 958 if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 959 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 960 memcpy(dec->rejend, cp, length); 961 dec->rejend += length; 962 break; 963 } 964 if (!gotdns) { 965 dns[0] = ipcp->cfg.ns.dns[0]; 966 dns[1] = ipcp->cfg.ns.dns[1]; 967 if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 968 getdns(ipcp, dns); 969 gotdns = 1; 970 } 971 have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 972 973 if (ipaddr.s_addr != have_ip.s_addr) { 974 /* 975 * The client has got the DNS stuff wrong (first request) so 976 * we'll tell 'em how it is 977 */ 978 memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 979 memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 980 dec->nakend += length; 981 } else { 982 /* 983 * Otherwise they have it right (this time) so we send a ack packet 984 * back confirming it... end of story 985 */ 986 memcpy(dec->ackend, cp, length); 987 dec->ackend += length; 988 } 989 break; 990 case MODE_NAK: /* what does this mean?? */ 991 if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 992 gotdnsnak = 1; 993 dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr = 994 *(u_int32_t *)(cp + 2); 995 } 996 break; 997 case MODE_REJ: /* Can't do much, stop asking */ 998 ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 999 break; 1000 } 1001 break; 1002 1003 case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1004 case TY_SECONDARY_NBNS: 1005 ipaddr.s_addr = *(u_int32_t *)(cp + 2); 1006 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1007 1008 switch (mode_type) { 1009 case MODE_REQ: 1010 have_ip.s_addr = 1011 ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 1012 1013 if (have_ip.s_addr == INADDR_ANY) { 1014 log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 1015 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 1016 memcpy(dec->rejend, cp, length); 1017 dec->rejend += length; 1018 break; 1019 } 1020 1021 if (ipaddr.s_addr != have_ip.s_addr) { 1022 memcpy(dec->nakend, cp, 2); 1023 memcpy(dec->nakend+2, &have_ip.s_addr, length); 1024 dec->nakend += length; 1025 } else { 1026 memcpy(dec->ackend, cp, length); 1027 dec->ackend += length; 1028 } 1029 break; 1030 case MODE_NAK: 1031 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1032 break; 1033 case MODE_REJ: 1034 log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1035 break; 1036 } 1037 break; 1038 1039 default: 1040 if (mode_type != MODE_NOP) { 1041 ipcp->my_reject |= (1 << type); 1042 memcpy(dec->rejend, cp, length); 1043 dec->rejend += length; 1044 } 1045 break; 1046 } 1047 plen -= length; 1048 cp += length; 1049 } 1050 1051 if (gotdnsnak) 1052 if (!setdns(ipcp, dnsnak)) { 1053 ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 1054 ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1055 } 1056 1057 if (mode_type != MODE_NOP) { 1058 if (dec->rejend != dec->rej) { 1059 /* rejects are preferred */ 1060 dec->ackend = dec->ack; 1061 dec->nakend = dec->nak; 1062 } else if (dec->nakend != dec->nak) 1063 /* then NAKs */ 1064 dec->ackend = dec->ack; 1065 } 1066 } 1067 1068 void 1069 ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp) 1070 { 1071 /* Got PROTO_IPCP from link */ 1072 if (bundle_Phase(bundle) == PHASE_NETWORK) 1073 fsm_Input(&ipcp->fsm, bp); 1074 else { 1075 if (bundle_Phase(bundle) < PHASE_NETWORK) 1076 log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 1077 ipcp->fsm.link->name, bundle_PhaseName(bundle)); 1078 mbuf_Free(bp); 1079 } 1080 } 1081 1082 int 1083 ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 1084 { 1085 struct ipcp *ipcp = &bundle->ncp.ipcp; 1086 1087 /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 1088 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1089 iplist_reset(&ipcp->cfg.peer_list); 1090 if (strpbrk(hisaddr, ",-")) { 1091 iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 1092 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 1093 iplist_setrandpos(&ipcp->cfg.peer_list); 1094 ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 1095 if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1096 log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 1097 return(0); 1098 } 1099 ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 1100 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 1101 ipcp->cfg.peer_range.width = 32; 1102 } else { 1103 log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 1104 return 0; 1105 } 1106 } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 1107 &ipcp->cfg.peer_range.mask, 1108 &ipcp->cfg.peer_range.width) != 0) { 1109 ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 1110 1111 if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 1112 ipcp->cfg.peer_range.ipaddr, 0) < 0) { 1113 ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 1114 ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 1115 return 0; 1116 } 1117 } else 1118 return 0; 1119 1120 return 1; 1121 } 1122