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