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