1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <netinet/in_systm.h> 33 #include <netinet/in.h> 34 #include <netinet/ip.h> 35 #include <sys/socket.h> 36 #include <net/route.h> 37 #include <net/if.h> 38 #include <net/if_types.h> 39 #include <net/if_dl.h> 40 #include <sys/un.h> 41 42 #include <stdarg.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <termios.h> 47 #include <ifaddrs.h> 48 49 #include "layer.h" 50 #include "defs.h" 51 #include "mbuf.h" 52 #include "timer.h" 53 #include "fsm.h" 54 #include "iplist.h" 55 #include "throughput.h" 56 #include "slcompress.h" 57 #include "lqr.h" 58 #include "hdlc.h" 59 #include "lcp.h" 60 #include "ncpaddr.h" 61 #include "ip.h" 62 #include "ipcp.h" 63 #include "ipv6cp.h" 64 #include "filter.h" 65 #include "descriptor.h" 66 #include "ccp.h" 67 #include "link.h" 68 #include "mp.h" 69 #ifndef NORADIUS 70 #include "radius.h" 71 #endif 72 #include "ncp.h" 73 #include "bundle.h" 74 #include "route.h" 75 #include "iface.h" 76 #include "log.h" 77 #include "proto.h" 78 #include "command.h" 79 #include "prompt.h" 80 #include "async.h" 81 #include "physical.h" 82 #include "probe.h" 83 #include "systems.h" 84 85 86 #ifndef NOINET6 87 #define IN6ADDR_LINKLOCAL_MCAST_INIT \ 88 {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} 90 static const struct in6_addr in6addr_linklocal_mcast = 91 IN6ADDR_LINKLOCAL_MCAST_INIT; 92 93 static int ipv6cp_LayerUp(struct fsm *); 94 static void ipv6cp_LayerDown(struct fsm *); 95 static void ipv6cp_LayerStart(struct fsm *); 96 static void ipv6cp_LayerFinish(struct fsm *); 97 static void ipv6cp_InitRestartCounter(struct fsm *, int); 98 static void ipv6cp_SendConfigReq(struct fsm *); 99 static void ipv6cp_SentTerminateReq(struct fsm *); 100 static void ipv6cp_SendTerminateAck(struct fsm *, u_char); 101 static void ipv6cp_DecodeConfig(struct fsm *, u_char *, u_char *, int, 102 struct fsm_decode *); 103 104 static struct fsm_callbacks ipv6cp_Callbacks = { 105 ipv6cp_LayerUp, 106 ipv6cp_LayerDown, 107 ipv6cp_LayerStart, 108 ipv6cp_LayerFinish, 109 ipv6cp_InitRestartCounter, 110 ipv6cp_SendConfigReq, 111 ipv6cp_SentTerminateReq, 112 ipv6cp_SendTerminateAck, 113 ipv6cp_DecodeConfig, 114 fsm_NullRecvResetReq, 115 fsm_NullRecvResetAck 116 }; 117 118 static void 119 SetInterfaceID(u_char *ifid, int userandom) 120 { 121 struct ifaddrs *ifa, *ifap = NULL; 122 struct sockaddr_dl *sdl; 123 const u_long i32_max = 0xffffffff; 124 u_long r1, r2; 125 126 /* configure an interface ID based on Section 4.1 of RFC 2472 */ 127 memset(ifid, 0, IPV6CP_IFIDLEN); 128 129 /* 130 * 1) If an IEEE global identifier (EUI-48 or EUI-64) is 131 * available anywhere on the node, it should be used to construct 132 * the tentative Interface-Identifier due to its uniqueness 133 * properties. 134 */ 135 if (userandom) 136 goto randomid; 137 if (getifaddrs(&ifap) < 0) 138 goto randomid; 139 140 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 141 char *cp; 142 143 if (ifa->ifa_addr->sa_family != AF_LINK) 144 continue; 145 146 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 147 if (sdl->sdl_alen < 6) 148 continue; 149 /* we're only interested in IEEE hardware addresses */ 150 switch(sdl->sdl_type) { 151 case IFT_ETHER: 152 case IFT_FDDI: 153 case IFT_L2VLAN: 154 /* XXX need more cases? */ 155 break; 156 default: 157 continue; 158 } 159 160 cp = (char *)(sdl->sdl_data + sdl->sdl_nlen); 161 ifid[0] = cp[0]; 162 ifid[0] ^= 0x02; /* reverse the u/l bit*/ 163 ifid[1] = cp[1]; 164 ifid[2] = cp[2]; 165 ifid[3] = 0xff; 166 ifid[4] = 0xfe; 167 ifid[5] = cp[3]; 168 ifid[6] = cp[4]; 169 ifid[7] = cp[5]; 170 171 freeifaddrs(ifap); 172 return; 173 } 174 175 freeifaddrs(ifap); 176 177 /* 178 * 2) If an IEEE global identifier is not available a different source 179 * of uniqueness should be used. 180 * XXX: we skip this case. 181 */ 182 183 /* 184 * 3) If a good source of uniqueness cannot be found, it is 185 * recommended that a random number be generated. In this case the 186 * "u" bit of the interface identifier MUST be set to zero (0). 187 */ 188 randomid: 189 randinit(); 190 r1 = (((u_long)random()) % i32_max) + 1; 191 r2 = (((u_long)random()) % i32_max) + 1; 192 memcpy(ifid, &r1, sizeof(r1)); 193 memcpy(ifid + 4, &r2, sizeof(r2)); 194 ifid[0] &= 0xfd; 195 return; 196 } 197 198 static int 199 ipcp_SetIPv6address(struct ipv6cp *ipv6cp, u_char *myifid, u_char *hisifid) 200 { 201 struct bundle *bundle = ipv6cp->fsm.bundle; 202 struct in6_addr myaddr, hisaddr; 203 struct ncprange myrange, range; 204 struct ncpaddr addr; 205 struct sockaddr_storage ssdst, ssgw, ssmask; 206 struct sockaddr *sadst, *sagw, *samask; 207 208 sadst = (struct sockaddr *)&ssdst; 209 sagw = (struct sockaddr *)&ssgw; 210 samask = (struct sockaddr *)&ssmask; 211 212 memset(&myaddr, '\0', sizeof myaddr); 213 memset(&hisaddr, '\0', sizeof hisaddr); 214 215 myaddr.s6_addr[0] = 0xfe; 216 myaddr.s6_addr[1] = 0x80; 217 memcpy(&myaddr.s6_addr[8], myifid, IPV6CP_IFIDLEN); 218 #if 0 219 myaddr.s6_addr[8] |= 0x02; /* set 'universal' bit */ 220 #endif 221 222 hisaddr.s6_addr[0] = 0xfe; 223 hisaddr.s6_addr[1] = 0x80; 224 memcpy(&hisaddr.s6_addr[8], hisifid, IPV6CP_IFIDLEN); 225 #if 0 226 hisaddr.s6_addr[8] |= 0x02; /* set 'universal' bit */ 227 #endif 228 229 ncpaddr_setip6(&ipv6cp->myaddr, &myaddr); 230 ncpaddr_setip6(&ipv6cp->hisaddr, &hisaddr); 231 ncprange_set(&myrange, &ipv6cp->myaddr, 64); 232 233 if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &ipv6cp->hisaddr, 234 IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 235 return 0; 236 237 if (!Enabled(bundle, OPT_IFACEALIAS)) 238 iface_Clear(bundle->iface, &bundle->ncp, AF_INET6, 239 IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 240 241 ncpaddr_setip6(&addr, &in6addr_linklocal_mcast); 242 ncprange_set(&range, &addr, 32); 243 rt_Set(bundle, RTM_ADD, &range, &ipv6cp->myaddr, 1, 0); 244 245 if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 246 ncprange_getsa(&myrange, &ssgw, &ssmask); 247 if (ncpaddr_isset(&ipv6cp->hisaddr)) 248 ncpaddr_getsa(&ipv6cp->hisaddr, &ssdst); 249 else 250 sadst = NULL; 251 rt_Update(bundle, sadst, sagw, samask, NULL, NULL); 252 } 253 254 if (Enabled(bundle, OPT_SROUTES)) 255 route_Change(bundle, bundle->ncp.route, &ipv6cp->myaddr, &ipv6cp->hisaddr); 256 257 #ifndef NORADIUS 258 if (bundle->radius.valid) 259 route_Change(bundle, bundle->radius.ipv6routes, &ipv6cp->myaddr, 260 &ipv6cp->hisaddr); 261 #endif 262 263 return 1; /* Ok */ 264 } 265 266 void 267 ipv6cp_Init(struct ipv6cp *ipv6cp, struct bundle *bundle, struct link *l, 268 const struct fsm_parent *parent) 269 { 270 static const char * const timer_names[] = 271 {"IPV6CP restart", "IPV6CP openmode", "IPV6CP stopped"}; 272 int n; 273 274 fsm_Init(&ipv6cp->fsm, "IPV6CP", PROTO_IPV6CP, 1, IPV6CP_MAXCODE, LogIPV6CP, 275 bundle, l, parent, &ipv6cp_Callbacks, timer_names); 276 277 ipv6cp->cfg.fsm.timeout = DEF_FSMRETRY; 278 ipv6cp->cfg.fsm.maxreq = DEF_FSMTRIES; 279 ipv6cp->cfg.fsm.maxtrm = DEF_FSMTRIES; 280 281 SetInterfaceID(ipv6cp->my_ifid, 0); 282 do { 283 SetInterfaceID(ipv6cp->his_ifid, 1); 284 } while (memcmp(ipv6cp->his_ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) == 0); 285 286 if (probe.ipv6_available) { 287 n = 100; 288 while (n && 289 !ipcp_SetIPv6address(ipv6cp, ipv6cp->my_ifid, ipv6cp->his_ifid)) { 290 do { 291 n--; 292 SetInterfaceID(ipv6cp->my_ifid, 1); 293 } while (n 294 && memcmp(ipv6cp->his_ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) == 0); 295 } 296 } 297 298 throughput_init(&ipv6cp->throughput, SAMPLE_PERIOD); 299 memset(ipv6cp->Queue, '\0', sizeof ipv6cp->Queue); 300 ipv6cp_Setup(ipv6cp); 301 } 302 303 void 304 ipv6cp_Destroy(struct ipv6cp *ipv6cp) 305 { 306 throughput_destroy(&ipv6cp->throughput); 307 } 308 309 void 310 ipv6cp_Setup(struct ipv6cp *ipv6cp) 311 { 312 ncpaddr_init(&ipv6cp->myaddr); 313 ncpaddr_init(&ipv6cp->hisaddr); 314 315 ipv6cp->his_reject = 0; 316 ipv6cp->my_reject = 0; 317 } 318 319 void 320 ipv6cp_SetLink(struct ipv6cp *ipv6cp, struct link *l) 321 { 322 ipv6cp->fsm.link = l; 323 } 324 325 int 326 ipv6cp_Show(struct cmdargs const *arg) 327 { 328 struct ipv6cp *ipv6cp = &arg->bundle->ncp.ipv6cp; 329 330 prompt_Printf(arg->prompt, "%s [%s]\n", ipv6cp->fsm.name, 331 State2Nam(ipv6cp->fsm.state)); 332 if (ipv6cp->fsm.state == ST_OPENED) { 333 prompt_Printf(arg->prompt, " His side: %s\n", 334 ncpaddr_ntoa(&ipv6cp->hisaddr)); 335 prompt_Printf(arg->prompt, " My side: %s\n", 336 ncpaddr_ntoa(&ipv6cp->myaddr)); 337 prompt_Printf(arg->prompt, " Queued packets: %lu\n", 338 (unsigned long)ipv6cp_QueueLen(ipv6cp)); 339 } 340 341 prompt_Printf(arg->prompt, "\nDefaults:\n"); 342 prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 343 " REQ%s, %u Term REQ%s\n\n", ipv6cp->cfg.fsm.timeout, 344 ipv6cp->cfg.fsm.maxreq, ipv6cp->cfg.fsm.maxreq == 1 ? "" : "s", 345 ipv6cp->cfg.fsm.maxtrm, ipv6cp->cfg.fsm.maxtrm == 1 ? "" : "s"); 346 347 throughput_disp(&ipv6cp->throughput, arg->prompt); 348 349 return 0; 350 } 351 352 struct mbuf * 353 ipv6cp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 354 { 355 /* Got PROTO_IPV6CP from link */ 356 m_settype(bp, MB_IPV6CPIN); 357 if (bundle_Phase(bundle) == PHASE_NETWORK) 358 fsm_Input(&bundle->ncp.ipv6cp.fsm, bp); 359 else { 360 if (bundle_Phase(bundle) < PHASE_NETWORK) 361 log_Printf(LogIPV6CP, "%s: Error: Unexpected IPV6CP in phase %s" 362 " (ignored)\n", l->name, bundle_PhaseName(bundle)); 363 m_freem(bp); 364 } 365 return NULL; 366 } 367 368 void 369 ipv6cp_AddInOctets(struct ipv6cp *ipv6cp, int n) 370 { 371 throughput_addin(&ipv6cp->throughput, n); 372 } 373 374 void 375 ipv6cp_AddOutOctets(struct ipv6cp *ipv6cp, int n) 376 { 377 throughput_addout(&ipv6cp->throughput, n); 378 } 379 380 void 381 ipv6cp_IfaceAddrAdded(struct ipv6cp *ipv6cp __unused, 382 const struct iface_addr *addr __unused) 383 { 384 } 385 386 void 387 ipv6cp_IfaceAddrDeleted(struct ipv6cp *ipv6cp __unused, 388 const struct iface_addr *addr __unused) 389 { 390 } 391 392 int 393 ipv6cp_InterfaceUp(struct ipv6cp *ipv6cp) 394 { 395 if (!ipcp_SetIPv6address(ipv6cp, ipv6cp->my_ifid, ipv6cp->his_ifid)) { 396 log_Printf(LogERROR, "ipv6cp_InterfaceUp: unable to set ipv6 address\n"); 397 return 0; 398 } 399 400 if (!iface_SetFlags(ipv6cp->fsm.bundle->iface->name, IFF_UP)) { 401 log_Printf(LogERROR, "ipv6cp_InterfaceUp: Can't set the IFF_UP" 402 " flag on %s\n", ipv6cp->fsm.bundle->iface->name); 403 return 0; 404 } 405 406 return 1; 407 } 408 409 size_t 410 ipv6cp_QueueLen(struct ipv6cp *ipv6cp) 411 { 412 struct mqueue *q; 413 size_t result; 414 415 result = 0; 416 for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) 417 result += q->len; 418 419 return result; 420 } 421 422 int 423 ipv6cp_PushPacket(struct ipv6cp *ipv6cp, struct link *l) 424 { 425 struct bundle *bundle = ipv6cp->fsm.bundle; 426 struct mqueue *queue; 427 struct mbuf *bp; 428 int m_len; 429 u_int32_t secs = 0; 430 unsigned alivesecs = 0; 431 432 if (ipv6cp->fsm.state != ST_OPENED) 433 return 0; 434 435 /* 436 * If ccp is not open but is required, do nothing. 437 */ 438 if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 439 log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 440 return 0; 441 } 442 443 queue = ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp) - 1; 444 do { 445 if (queue->top) { 446 bp = m_dequeue(queue); 447 bp = mbuf_Read(bp, &secs, sizeof secs); 448 bp = m_pullup(bp); 449 m_len = m_length(bp); 450 if (!FilterCheck(MBUF_CTOP(bp), AF_INET6, &bundle->filter.alive, 451 &alivesecs)) { 452 if (secs == 0) 453 secs = alivesecs; 454 bundle_StartIdleTimer(bundle, secs); 455 } 456 link_PushPacket(l, bp, bundle, 0, PROTO_IPV6); 457 ipv6cp_AddOutOctets(ipv6cp, m_len); 458 return 1; 459 } 460 } while (queue-- != ipv6cp->Queue); 461 462 return 0; 463 } 464 465 static int 466 ipv6cp_LayerUp(struct fsm *fp) 467 { 468 /* We're now up */ 469 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 470 char tbuff[NCP_ASCIIBUFFERSIZE]; 471 472 log_Printf(LogIPV6CP, "%s: LayerUp.\n", fp->link->name); 473 if (!ipv6cp_InterfaceUp(ipv6cp)) 474 return 0; 475 476 snprintf(tbuff, sizeof tbuff, "%s", ncpaddr_ntoa(&ipv6cp->myaddr)); 477 log_Printf(LogIPV6CP, "myaddr %s hisaddr = %s\n", 478 tbuff, ncpaddr_ntoa(&ipv6cp->hisaddr)); 479 480 #ifndef NORADIUS 481 radius_Account_Set_Ipv6(&fp->bundle->radacct6, ipv6cp->his_ifid); 482 radius_Account(&fp->bundle->radius, &fp->bundle->radacct6, 483 fp->bundle->links, RAD_START, &ipv6cp->throughput); 484 485 /* 486 * XXX: Avoid duplicate evaluation of filterid between IPCP and 487 * IPV6CP. When IPCP is enabled and rejected, filterid is not 488 * evaluated. 489 */ 490 if (!Enabled(fp->bundle, OPT_IPCP)) { 491 if (*fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 492 system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE, 493 NULL, NULL); 494 } 495 #endif 496 497 /* 498 * XXX this stuff should really live in the FSM. Our config should 499 * associate executable sections in files with events. 500 */ 501 if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 502 /* 503 * XXX: Avoid duplicate evaluation of label between IPCP and 504 * IPV6CP. When IPCP is enabled and rejected, label is not 505 * evaluated. 506 */ 507 if (bundle_GetLabel(fp->bundle) && !Enabled(fp->bundle, OPT_IPCP)) { 508 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 509 LINKUPFILE, NULL, NULL) < 0) 510 system_Select(fp->bundle, "MYADDR6", LINKUPFILE, NULL, NULL); 511 } else 512 system_Select(fp->bundle, "MYADDR6", LINKUPFILE, NULL, NULL); 513 } 514 515 fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3; 516 log_DisplayPrompts(); 517 518 return 1; 519 } 520 521 static void 522 ipv6cp_LayerDown(struct fsm *fp) 523 { 524 /* About to come down */ 525 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 526 static int recursing; 527 char addr[NCP_ASCIIBUFFERSIZE]; 528 529 if (!recursing++) { 530 snprintf(addr, sizeof addr, "%s", ncpaddr_ntoa(&ipv6cp->myaddr)); 531 log_Printf(LogIPV6CP, "%s: LayerDown: %s\n", fp->link->name, addr); 532 533 #ifndef NORADIUS 534 radius_Flush(&fp->bundle->radius); 535 radius_Account(&fp->bundle->radius, &fp->bundle->radacct6, 536 fp->bundle->links, RAD_STOP, &ipv6cp->throughput); 537 538 /* 539 * XXX: Avoid duplicate evaluation of filterid between IPCP and 540 * IPV6CP. When IPCP is enabled and rejected, filterid is not 541 * evaluated. 542 */ 543 if (!Enabled(fp->bundle, OPT_IPCP)) { 544 if (*fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 545 system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE, 546 NULL, NULL); 547 } 548 #endif 549 550 /* 551 * XXX this stuff should really live in the FSM. Our config should 552 * associate executable sections in files with events. 553 */ 554 if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) { 555 /* 556 * XXX: Avoid duplicate evaluation of label between IPCP and 557 * IPV6CP. When IPCP is enabled and rejected, label is not 558 * evaluated. 559 */ 560 if (bundle_GetLabel(fp->bundle) && !Enabled(fp->bundle, OPT_IPCP)) { 561 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 562 LINKDOWNFILE, NULL, NULL) < 0) 563 system_Select(fp->bundle, "MYADDR6", LINKDOWNFILE, NULL, NULL); 564 } else 565 system_Select(fp->bundle, "MYADDR6", LINKDOWNFILE, NULL, NULL); 566 } 567 568 ipv6cp_Setup(ipv6cp); 569 } 570 recursing--; 571 } 572 573 static void 574 ipv6cp_LayerStart(struct fsm *fp) 575 { 576 /* We're about to start up ! */ 577 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 578 579 log_Printf(LogIPV6CP, "%s: LayerStart.\n", fp->link->name); 580 throughput_start(&ipv6cp->throughput, "IPV6CP throughput", 581 Enabled(fp->bundle, OPT_THROUGHPUT)); 582 fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3; 583 ipv6cp->peer_tokenreq = 0; 584 } 585 586 static void 587 ipv6cp_LayerFinish(struct fsm *fp) 588 { 589 /* We're now down */ 590 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 591 592 log_Printf(LogIPV6CP, "%s: LayerFinish.\n", fp->link->name); 593 throughput_stop(&ipv6cp->throughput); 594 throughput_log(&ipv6cp->throughput, LogIPV6CP, NULL); 595 } 596 597 static void 598 ipv6cp_InitRestartCounter(struct fsm *fp, int what) 599 { 600 /* Set fsm timer load */ 601 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 602 603 fp->FsmTimer.load = ipv6cp->cfg.fsm.timeout * SECTICKS; 604 switch (what) { 605 case FSM_REQ_TIMER: 606 fp->restart = ipv6cp->cfg.fsm.maxreq; 607 break; 608 case FSM_TRM_TIMER: 609 fp->restart = ipv6cp->cfg.fsm.maxtrm; 610 break; 611 default: 612 fp->restart = 1; 613 break; 614 } 615 } 616 617 static void 618 ipv6cp_SendConfigReq(struct fsm *fp) 619 { 620 /* Send config REQ please */ 621 struct physical *p = link2physical(fp->link); 622 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 623 u_char buff[IPV6CP_IFIDLEN+2]; 624 struct fsm_opt *o; 625 626 o = (struct fsm_opt *)buff; 627 628 if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) { 629 memcpy(o->data, ipv6cp->my_ifid, IPV6CP_IFIDLEN); 630 INC_FSM_OPT(TY_TOKEN, IPV6CP_IFIDLEN + 2, o); 631 } 632 633 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 634 MB_IPV6CPOUT); 635 } 636 637 static void 638 ipv6cp_SentTerminateReq(struct fsm *fp __unused) 639 { 640 /* Term REQ just sent by FSM */ 641 } 642 643 static void 644 ipv6cp_SendTerminateAck(struct fsm *fp, u_char id) 645 { 646 /* Send Term ACK please */ 647 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPV6CPOUT); 648 } 649 650 static const char * 651 protoname(unsigned proto) 652 { 653 static const char *cftypes[] = { "IFACEID", "COMPPROTO" }; 654 655 if (proto > 0 && proto <= sizeof cftypes / sizeof *cftypes) 656 return cftypes[proto - 1]; 657 658 return NumStr(proto, NULL, 0); 659 } 660 661 static void 662 ipv6cp_ValidateInterfaceID(struct ipv6cp *ipv6cp, u_char *ifid, 663 struct fsm_decode *dec) 664 { 665 struct fsm_opt opt; 666 u_char zero[IPV6CP_IFIDLEN]; 667 668 memset(zero, 0, IPV6CP_IFIDLEN); 669 670 if (memcmp(ifid, zero, IPV6CP_IFIDLEN) != 0 671 && memcmp(ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) != 0) 672 memcpy(ipv6cp->his_ifid, ifid, IPV6CP_IFIDLEN); 673 674 opt.hdr.id = TY_TOKEN; 675 opt.hdr.len = IPV6CP_IFIDLEN + 2; 676 memcpy(opt.data, &ipv6cp->his_ifid, IPV6CP_IFIDLEN); 677 if (memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0) 678 fsm_ack(dec, &opt); 679 else 680 fsm_nak(dec, &opt); 681 } 682 683 static void 684 ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 685 struct fsm_decode *dec) 686 { 687 /* Deal with incoming PROTO_IPV6CP */ 688 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 689 int n; 690 char tbuff[100]; 691 u_char ifid[IPV6CP_IFIDLEN], zero[IPV6CP_IFIDLEN]; 692 struct fsm_opt *opt; 693 694 memset(zero, 0, IPV6CP_IFIDLEN); 695 696 while (end - cp >= (int)sizeof(opt->hdr)) { 697 if ((opt = fsm_readopt(&cp)) == NULL) 698 break; 699 700 snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 701 opt->hdr.len); 702 703 switch (opt->hdr.id) { 704 case TY_TOKEN: 705 memcpy(ifid, opt->data, IPV6CP_IFIDLEN); 706 log_Printf(LogIPV6CP, "%s 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", tbuff, 707 ifid[0], ifid[1], ifid[2], ifid[3], ifid[4], ifid[5], ifid[6], ifid[7]); 708 709 switch (mode_type) { 710 case MODE_REQ: 711 ipv6cp->peer_tokenreq = 1; 712 ipv6cp_ValidateInterfaceID(ipv6cp, ifid, dec); 713 break; 714 715 case MODE_NAK: 716 if (memcmp(ifid, zero, IPV6CP_IFIDLEN) == 0) { 717 log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 718 "0x0000000000000000: Unacceptable IntefaceID!\n"); 719 fsm_Close(&ipv6cp->fsm); 720 } else if (memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0) { 721 log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 722 "0x%02x%02x%02x%02x%02x%02x%02x%02x: " 723 "Unacceptable IntefaceID!\n", 724 ifid[0], ifid[1], ifid[2], ifid[3], 725 ifid[4], ifid[5], ifid[6], ifid[7]); 726 } else if (memcmp(ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) != 0) { 727 n = 100; 728 while (n && !ipcp_SetIPv6address(ipv6cp, ifid, ipv6cp->his_ifid)) { 729 do { 730 n--; 731 SetInterfaceID(ifid, 1); 732 } while (n && memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0); 733 } 734 735 if (n == 0) { 736 log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 737 "0x0000000000000000: Unacceptable IntefaceID!\n"); 738 fsm_Close(&ipv6cp->fsm); 739 } else { 740 log_Printf(LogIPV6CP, "%s changing IntefaceID: " 741 "0x%02x%02x%02x%02x%02x%02x%02x%02x " 742 "--> 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", tbuff, 743 ipv6cp->my_ifid[0], ipv6cp->my_ifid[1], 744 ipv6cp->my_ifid[2], ipv6cp->my_ifid[3], 745 ipv6cp->my_ifid[4], ipv6cp->my_ifid[5], 746 ipv6cp->my_ifid[6], ipv6cp->my_ifid[7], 747 ifid[0], ifid[1], ifid[2], ifid[3], 748 ifid[4], ifid[5], ifid[6], ifid[7]); 749 memcpy(ipv6cp->my_ifid, ifid, IPV6CP_IFIDLEN); 750 bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL); 751 } 752 } 753 break; 754 755 case MODE_REJ: 756 ipv6cp->his_reject |= (1 << opt->hdr.id); 757 break; 758 } 759 break; 760 761 default: 762 if (mode_type != MODE_NOP) { 763 ipv6cp->my_reject |= (1 << opt->hdr.id); 764 fsm_rej(dec, opt); 765 } 766 break; 767 } 768 } 769 770 if (mode_type != MODE_NOP) { 771 if (mode_type == MODE_REQ && !ipv6cp->peer_tokenreq) { 772 if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 773 /* 774 * Pretend the peer has requested a TOKEN. 775 * We do this to ensure that we only send one NAK if the only 776 * reason for the NAK is because the peer isn't sending a 777 * TY_TOKEN REQ. This stops us from repeatedly trying to tell 778 * the peer that we have to have an IP address on their end. 779 */ 780 ipv6cp->peer_tokenreq = 1; 781 } 782 memset(ifid, 0, IPV6CP_IFIDLEN); 783 ipv6cp_ValidateInterfaceID(ipv6cp, ifid, dec); 784 } 785 fsm_opt_normalise(dec); 786 } 787 } 788 #endif 789