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