ipcp.c revision 47695
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.78 1999/05/31 23:57:40 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 91struct compreq { 92 u_short proto; 93 u_char slots; 94 u_char compcid; 95}; 96 97static int IpcpLayerUp(struct fsm *); 98static void IpcpLayerDown(struct fsm *); 99static void IpcpLayerStart(struct fsm *); 100static void IpcpLayerFinish(struct fsm *); 101static void IpcpInitRestartCounter(struct fsm *, int); 102static void IpcpSendConfigReq(struct fsm *); 103static void IpcpSentTerminateReq(struct fsm *); 104static void IpcpSendTerminateAck(struct fsm *, u_char); 105static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 106 struct fsm_decode *); 107 108static 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 122static 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 132static 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 143void 144ipcp_AddInOctets(struct ipcp *ipcp, int n) 145{ 146 throughput_addin(&ipcp->throughput, n); 147} 148 149void 150ipcp_AddOutOctets(struct ipcp *ipcp, int n) 151{ 152 throughput_addout(&ipcp->throughput, n); 153} 154 155static void 156getdns(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 184static int 185setdns(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 267int 268ipcp_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 324int 325ipcp_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 349void 350ipcp_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 393void 394ipcp_SetLink(struct ipcp *ipcp, struct link *l) 395{ 396 ipcp->fsm.link = l; 397} 398 399void 400ipcp_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 474static int 475ipcp_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 503static int 504ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 505 struct in_addr hisaddr, int silent) 506{ 507 static struct in_addr none = { INADDR_ANY }; 508 struct in_addr mask, oaddr; 509 510 mask = addr2mask(myaddr); 511 512 if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY && 513 (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr) 514 mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr; 515 516 oaddr.s_addr = bundle->iface->in_addrs ? 517 bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY; 518 if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr, 519 IFACE_ADD_FIRST|IFACE_FORCE_ADD)) 520 return -1; 521 522 if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1 523 && myaddr.s_addr != oaddr.s_addr) 524 /* Nuke the old one */ 525 iface_inDelete(bundle->iface, oaddr); 526 527 if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) 528 bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 529 530 if (Enabled(bundle, OPT_SROUTES)) 531 route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 532 533#ifndef NORADIUS 534 if (bundle->radius.valid) 535 route_Change(bundle, bundle->radius.routes, myaddr, hisaddr); 536#endif 537 538 if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { 539 int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 540 if (s < 0) 541 log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", 542 strerror(errno)); 543 else { 544 if (Enabled(bundle, OPT_PROXYALL)) 545 ipcp_doproxyall(bundle, arp_SetProxy, s); 546 else if (Enabled(bundle, OPT_PROXY)) 547 arp_SetProxy(bundle, hisaddr, s); 548 close(s); 549 } 550 } 551 552 return 0; 553} 554 555static struct in_addr 556ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 557{ 558 struct in_addr try; 559 u_long f; 560 561 for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 562 try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 563 log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 564 f, inet_ntoa(try)); 565 if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 566 log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 567 break; 568 } 569 } 570 571 if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 572 log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 573 try.s_addr = INADDR_ANY; 574 } 575 576 return try; 577} 578 579static void 580IpcpInitRestartCounter(struct fsm *fp, int what) 581{ 582 /* Set fsm timer load */ 583 struct ipcp *ipcp = fsm2ipcp(fp); 584 585 fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 586 switch (what) { 587 case FSM_REQ_TIMER: 588 fp->restart = ipcp->cfg.fsm.maxreq; 589 break; 590 case FSM_TRM_TIMER: 591 fp->restart = ipcp->cfg.fsm.maxtrm; 592 break; 593 default: 594 fp->restart = 1; 595 break; 596 } 597} 598 599static void 600IpcpSendConfigReq(struct fsm *fp) 601{ 602 /* Send config REQ please */ 603 struct physical *p = link2physical(fp->link); 604 struct ipcp *ipcp = fsm2ipcp(fp); 605 u_char buff[24]; 606 struct lcp_opt *o; 607 608 o = (struct lcp_opt *)buff; 609 610 if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 611 memcpy(o->data, &ipcp->my_ip.s_addr, 4); 612 INC_LCP_OPT(TY_IPADDR, 6, o); 613 } 614 615 if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 616 if (ipcp->heis1172) { 617 u_int16_t proto = PROTO_VJCOMP; 618 619 ua_htons(&proto, o->data); 620 INC_LCP_OPT(TY_COMPPROTO, 4, o); 621 } else { 622 struct compreq req; 623 624 req.proto = htons(ipcp->my_compproto >> 16); 625 req.slots = (ipcp->my_compproto >> 8) & 255; 626 req.compcid = ipcp->my_compproto & 1; 627 memcpy(o->data, &req, 4); 628 INC_LCP_OPT(TY_COMPPROTO, 6, o); 629 } 630 } 631 632 if (IsEnabled(ipcp->cfg.ns.dns_neg) && 633 !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 634 !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 635 struct in_addr dns[2]; 636 getdns(ipcp, dns); 637 memcpy(o->data, &dns[0].s_addr, 4); 638 INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 639 memcpy(o->data, &dns[1].s_addr, 4); 640 INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 641 } 642 643 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 644 MB_IPCPOUT); 645} 646 647static void 648IpcpSentTerminateReq(struct fsm *fp) 649{ 650 /* Term REQ just sent by FSM */ 651} 652 653static void 654IpcpSendTerminateAck(struct fsm *fp, u_char id) 655{ 656 /* Send Term ACK please */ 657 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 658} 659 660static void 661IpcpLayerStart(struct fsm *fp) 662{ 663 /* We're about to start up ! */ 664 struct ipcp *ipcp = fsm2ipcp(fp); 665 666 log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 667 throughput_start(&ipcp->throughput, "IPCP throughput", 668 Enabled(fp->bundle, OPT_THROUGHPUT)); 669 fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 670} 671 672static void 673IpcpLayerFinish(struct fsm *fp) 674{ 675 /* We're now down */ 676 struct ipcp *ipcp = fsm2ipcp(fp); 677 678 log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 679 throughput_stop(&ipcp->throughput); 680 throughput_log(&ipcp->throughput, LogIPCP, NULL); 681} 682 683void 684ipcp_CleanInterface(struct ipcp *ipcp) 685{ 686 struct iface *iface = ipcp->fsm.bundle->iface; 687 688 route_Clean(ipcp->fsm.bundle, ipcp->route); 689 690 if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) || 691 Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { 692 int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 693 if (s < 0) 694 log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", 695 strerror(errno)); 696 else { 697 if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) 698 ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); 699 else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 700 arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s); 701 close(s); 702 } 703 } 704 705 iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL); 706} 707 708static void 709IpcpLayerDown(struct fsm *fp) 710{ 711 /* About to come down */ 712 struct ipcp *ipcp = fsm2ipcp(fp); 713 const char *s; 714 715 if (ipcp->fsm.bundle->iface->in_addrs) 716 s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa); 717 else 718 s = "Interface configuration error !"; 719 log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 720 721 /* 722 * XXX this stuff should really live in the FSM. Our config should 723 * associate executable sections in files with events. 724 */ 725 if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 726 if (bundle_GetLabel(fp->bundle)) { 727 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 728 LINKDOWNFILE, NULL, NULL) < 0) 729 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 730 } else 731 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 732 } 733 734 ipcp_Setup(ipcp, INADDR_NONE); 735} 736 737int 738ipcp_InterfaceUp(struct ipcp *ipcp) 739{ 740 if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 741 log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 742 return 0; 743 } 744 745#ifndef NOALIAS 746 if (ipcp->fsm.bundle->AliasEnabled) 747 PacketAliasSetAddress(ipcp->my_ip); 748#endif 749 750 return 1; 751} 752 753static int 754IpcpLayerUp(struct fsm *fp) 755{ 756 /* We're now up */ 757 struct ipcp *ipcp = fsm2ipcp(fp); 758 char tbuff[16]; 759 760 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 761 snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 762 log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 763 tbuff, inet_ntoa(ipcp->peer_ip)); 764 765 if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 766 sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 767 768 if (!ipcp_InterfaceUp(ipcp)) 769 return 0; 770 771 /* 772 * XXX this stuff should really live in the FSM. Our config should 773 * associate executable sections in files with events. 774 */ 775 if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 776 if (bundle_GetLabel(fp->bundle)) { 777 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 778 LINKUPFILE, NULL, NULL) < 0) 779 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 780 } else 781 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 782 } 783 784 fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 785 log_DisplayPrompts(); 786 787 return 1; 788} 789 790static int 791AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) 792{ 793 /* Is the given IP in the given range ? */ 794 return (prange->ipaddr.s_addr & prange->mask.s_addr) == 795 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 796} 797 798static void 799IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 800 struct fsm_decode *dec) 801{ 802 /* Deal with incoming PROTO_IPCP */ 803 struct iface *iface = fp->bundle->iface; 804 struct ipcp *ipcp = fsm2ipcp(fp); 805 int type, length, gotdns, gotdnsnak, n; 806 u_int32_t compproto; 807 struct compreq *pcomp; 808 struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 809 char tbuff[100], tbuff2[100]; 810 811 gotdns = 0; 812 gotdnsnak = 0; 813 dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 814 815 while (plen >= sizeof(struct fsmconfig)) { 816 type = *cp; 817 length = cp[1]; 818 819 if (length == 0) { 820 log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 821 break; 822 } 823 824 if (type < NCFTYPES) 825 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 826 else if (type > 128 && type < 128 + NCFTYPES128) 827 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 828 else 829 snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 830 831 switch (type) { 832 case TY_IPADDR: /* RFC1332 */ 833 memcpy(&ipaddr.s_addr, cp + 2, 4); 834 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 835 836 switch (mode_type) { 837 case MODE_REQ: 838 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 839 if (ipaddr.s_addr == INADDR_ANY || 840 iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 841 ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 842 ipaddr, 1)) { 843 log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 844 inet_ntoa(ipaddr)); 845 /* 846 * If we've already had a valid address configured for the peer, 847 * try NAKing with that so that we don't have to upset things 848 * too much. 849 */ 850 for (n = 0; n < iface->in_addrs; n++) 851 if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) 852 >=0) { 853 ipcp->peer_ip = iface->in_addr[n].brd; 854 break; 855 } 856 857 if (n == iface->in_addrs) 858 /* Just pick an IP number from our list */ 859 ipcp->peer_ip = ChooseHisAddr 860 (fp->bundle, ipcp->cfg.my_range.ipaddr); 861 862 if (ipcp->peer_ip.s_addr == INADDR_ANY) { 863 memcpy(dec->rejend, cp, length); 864 dec->rejend += length; 865 } else { 866 memcpy(dec->nakend, cp, 2); 867 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 868 dec->nakend += length; 869 } 870 break; 871 } 872 } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 873 /* 874 * If destination address is not acceptable, NAK with what we 875 * want to use. 876 */ 877 memcpy(dec->nakend, cp, 2); 878 for (n = 0; n < iface->in_addrs; n++) 879 if ((iface->in_addr[n].brd.s_addr & 880 ipcp->cfg.peer_range.mask.s_addr) 881 == (ipcp->cfg.peer_range.ipaddr.s_addr & 882 ipcp->cfg.peer_range.mask.s_addr)) { 883 /* We prefer the already-configured address */ 884 memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, 885 length - 2); 886 break; 887 } 888 889 if (n == iface->in_addrs) 890 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 891 892 dec->nakend += length; 893 break; 894 } 895 ipcp->peer_ip = ipaddr; 896 memcpy(dec->ackend, cp, length); 897 dec->ackend += length; 898 break; 899 900 case MODE_NAK: 901 if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 902 /* Use address suggested by peer */ 903 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 904 inet_ntoa(ipcp->my_ip)); 905 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 906 ipcp->my_ip = ipaddr; 907 bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL); 908 } else { 909 log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 910 "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 911 fsm_Close(&ipcp->fsm); 912 } 913 break; 914 915 case MODE_REJ: 916 ipcp->peer_reject |= (1 << type); 917 break; 918 } 919 break; 920 921 case TY_COMPPROTO: 922 pcomp = (struct compreq *)(cp + 2); 923 compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 924 pcomp->compcid; 925 log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 926 927 switch (mode_type) { 928 case MODE_REQ: 929 if (!IsAccepted(ipcp->cfg.vj.neg)) { 930 memcpy(dec->rejend, cp, length); 931 dec->rejend += length; 932 } else { 933 switch (length) { 934 case 4: /* RFC1172 */ 935 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 936 log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 937 "protocol !\n"); 938 ipcp->heis1172 = 1; 939 ipcp->peer_compproto = compproto; 940 memcpy(dec->ackend, cp, length); 941 dec->ackend += length; 942 } else { 943 memcpy(dec->nakend, cp, 2); 944 pcomp->proto = htons(PROTO_VJCOMP); 945 memcpy(dec->nakend+2, &pcomp, 2); 946 dec->nakend += length; 947 } 948 break; 949 case 6: /* RFC1332 */ 950 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 951 if (pcomp->slots <= MAX_VJ_STATES 952 && pcomp->slots >= MIN_VJ_STATES) { 953 /* Ok, we can do that */ 954 ipcp->peer_compproto = compproto; 955 ipcp->heis1172 = 0; 956 memcpy(dec->ackend, cp, length); 957 dec->ackend += length; 958 } else { 959 /* Get as close as we can to what he wants */ 960 ipcp->heis1172 = 0; 961 memcpy(dec->nakend, cp, 2); 962 pcomp->slots = pcomp->slots < MIN_VJ_STATES ? 963 MIN_VJ_STATES : MAX_VJ_STATES; 964 memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 965 dec->nakend += length; 966 } 967 } else { 968 /* What we really want */ 969 memcpy(dec->nakend, cp, 2); 970 pcomp->proto = htons(PROTO_VJCOMP); 971 pcomp->slots = DEF_VJ_STATES; 972 pcomp->compcid = 1; 973 memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 974 dec->nakend += length; 975 } 976 break; 977 default: 978 memcpy(dec->rejend, cp, length); 979 dec->rejend += length; 980 break; 981 } 982 } 983 break; 984 985 case MODE_NAK: 986 if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 987 if (pcomp->slots > MAX_VJ_STATES) 988 pcomp->slots = MAX_VJ_STATES; 989 else if (pcomp->slots < MIN_VJ_STATES) 990 pcomp->slots = MIN_VJ_STATES; 991 compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 992 pcomp->compcid; 993 } else 994 compproto = 0; 995 log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 996 tbuff, ipcp->my_compproto, compproto); 997 ipcp->my_compproto = compproto; 998 break; 999 1000 case MODE_REJ: 1001 ipcp->peer_reject |= (1 << type); 1002 break; 1003 } 1004 break; 1005 1006 case TY_IPADDRS: /* RFC1172 */ 1007 memcpy(&ipaddr.s_addr, cp + 2, 4); 1008 memcpy(&dstipaddr.s_addr, cp + 6, 4); 1009 snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1010 log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1011 1012 switch (mode_type) { 1013 case MODE_REQ: 1014 memcpy(dec->rejend, cp, length); 1015 dec->rejend += length; 1016 break; 1017 1018 case MODE_NAK: 1019 case MODE_REJ: 1020 break; 1021 } 1022 break; 1023 1024 case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1025 case TY_SECONDARY_DNS: 1026 memcpy(&ipaddr.s_addr, cp + 2, 4); 1027 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1028 1029 switch (mode_type) { 1030 case MODE_REQ: 1031 if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 1032 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 1033 memcpy(dec->rejend, cp, length); 1034 dec->rejend += length; 1035 break; 1036 } 1037 if (!gotdns) { 1038 dns[0] = ipcp->cfg.ns.dns[0]; 1039 dns[1] = ipcp->cfg.ns.dns[1]; 1040 if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 1041 getdns(ipcp, dns); 1042 gotdns = 1; 1043 } 1044 have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 1045 1046 if (ipaddr.s_addr != have_ip.s_addr) { 1047 /* 1048 * The client has got the DNS stuff wrong (first request) so 1049 * we'll tell 'em how it is 1050 */ 1051 memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 1052 memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 1053 dec->nakend += length; 1054 } else { 1055 /* 1056 * Otherwise they have it right (this time) so we send a ack packet 1057 * back confirming it... end of story 1058 */ 1059 memcpy(dec->ackend, cp, length); 1060 dec->ackend += length; 1061 } 1062 break; 1063 1064 case MODE_NAK: /* what does this mean?? */ 1065 if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 1066 gotdnsnak = 1; 1067 memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 1068 } 1069 break; 1070 1071 case MODE_REJ: /* Can't do much, stop asking */ 1072 ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1073 break; 1074 } 1075 break; 1076 1077 case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1078 case TY_SECONDARY_NBNS: 1079 memcpy(&ipaddr.s_addr, cp + 2, 4); 1080 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1081 1082 switch (mode_type) { 1083 case MODE_REQ: 1084 have_ip.s_addr = 1085 ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 1086 1087 if (have_ip.s_addr == INADDR_ANY) { 1088 log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 1089 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 1090 memcpy(dec->rejend, cp, length); 1091 dec->rejend += length; 1092 break; 1093 } 1094 1095 if (ipaddr.s_addr != have_ip.s_addr) { 1096 memcpy(dec->nakend, cp, 2); 1097 memcpy(dec->nakend+2, &have_ip.s_addr, length); 1098 dec->nakend += length; 1099 } else { 1100 memcpy(dec->ackend, cp, length); 1101 dec->ackend += length; 1102 } 1103 break; 1104 1105 case MODE_NAK: 1106 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1107 break; 1108 1109 case MODE_REJ: 1110 log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1111 break; 1112 } 1113 break; 1114 1115 default: 1116 if (mode_type != MODE_NOP) { 1117 ipcp->my_reject |= (1 << type); 1118 memcpy(dec->rejend, cp, length); 1119 dec->rejend += length; 1120 } 1121 break; 1122 } 1123 plen -= length; 1124 cp += length; 1125 } 1126 1127 if (gotdnsnak) 1128 if (!setdns(ipcp, dnsnak)) { 1129 ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 1130 ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1131 } 1132 1133 if (mode_type != MODE_NOP) { 1134 if (dec->rejend != dec->rej) { 1135 /* rejects are preferred */ 1136 dec->ackend = dec->ack; 1137 dec->nakend = dec->nak; 1138 } else if (dec->nakend != dec->nak) 1139 /* then NAKs */ 1140 dec->ackend = dec->ack; 1141 } 1142} 1143 1144extern struct mbuf * 1145ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 1146{ 1147 /* Got PROTO_IPCP from link */ 1148 mbuf_SetType(bp, MB_IPCPIN); 1149 if (bundle_Phase(bundle) == PHASE_NETWORK) 1150 fsm_Input(&bundle->ncp.ipcp.fsm, bp); 1151 else { 1152 if (bundle_Phase(bundle) < PHASE_NETWORK) 1153 log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 1154 l->name, bundle_PhaseName(bundle)); 1155 mbuf_Free(bp); 1156 } 1157 return NULL; 1158} 1159 1160int 1161ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 1162{ 1163 struct ipcp *ipcp = &bundle->ncp.ipcp; 1164 1165 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1166 iplist_reset(&ipcp->cfg.peer_list); 1167 ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr; 1168 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 1169 ipcp->cfg.peer_range.width = 32; 1170 1171 if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0) 1172 return 0; 1173 1174 return 1; /* Ok */ 1175} 1176 1177int 1178ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 1179{ 1180 struct ipcp *ipcp = &bundle->ncp.ipcp; 1181 1182 /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 1183 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1184 iplist_reset(&ipcp->cfg.peer_list); 1185 if (strpbrk(hisaddr, ",-")) { 1186 iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 1187 if (iplist_isvalid(&ipcp->cfg.peer_list)) { 1188 iplist_setrandpos(&ipcp->cfg.peer_list); 1189 ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 1190 if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1191 log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 1192 return 0; 1193 } 1194 ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 1195 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 1196 ipcp->cfg.peer_range.width = 32; 1197 } else { 1198 log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 1199 return 0; 1200 } 1201 } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr, 1202 &ipcp->cfg.peer_range.mask, 1203 &ipcp->cfg.peer_range.width) != 0) { 1204 ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 1205 1206 if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 1207 ipcp->cfg.peer_range.ipaddr, 0) < 0) 1208 return 0; 1209 } else 1210 return 0; 1211 1212 bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip); 1213 1214 return 1; /* Ok */ 1215} 1216 1217struct in_addr 1218addr2mask(struct in_addr addr) 1219{ 1220 u_int32_t haddr = ntohl(addr.s_addr); 1221 1222 haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1223 IN_CLASSB(haddr) ? IN_CLASSB_NET : 1224 IN_CLASSC_NET; 1225 addr.s_addr = htonl(haddr); 1226 1227 return addr; 1228} 1229