ipv6cp.c revision 81888
1/*- 2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/usr.sbin/ppp/ipv6cp.c 81888 2001-08-18 13:04:52Z brian $ 27 */ 28 29#include <sys/param.h> 30#include <netinet/in_systm.h> 31#include <netinet/in.h> 32#include <netinet/ip.h> 33#include <sys/socket.h> 34#include <net/route.h> 35#include <net/if.h> 36#include <sys/un.h> 37 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <termios.h> 42 43#include "layer.h" 44#include "defs.h" 45#include "mbuf.h" 46#include "timer.h" 47#include "fsm.h" 48#include "iplist.h" 49#include "throughput.h" 50#include "slcompress.h" 51#include "lqr.h" 52#include "hdlc.h" 53#include "lcp.h" 54#include "ncpaddr.h" 55#include "ip.h" 56#include "ipcp.h" 57#include "ipv6cp.h" 58#include "filter.h" 59#include "descriptor.h" 60#include "ccp.h" 61#include "link.h" 62#include "mp.h" 63#ifndef NORADIUS 64#include "radius.h" 65#endif 66#include "ncp.h" 67#include "bundle.h" 68#include "route.h" 69#include "iface.h" 70#include "log.h" 71#include "proto.h" 72#include "command.h" 73#include "prompt.h" 74#include "async.h" 75#include "physical.h" 76#include "probe.h" 77 78 79#ifndef NOINET6 80static int ipv6cp_LayerUp(struct fsm *); 81static void ipv6cp_LayerDown(struct fsm *); 82static void ipv6cp_LayerStart(struct fsm *); 83static void ipv6cp_LayerFinish(struct fsm *); 84static void ipv6cp_InitRestartCounter(struct fsm *, int); 85static void ipv6cp_SendConfigReq(struct fsm *); 86static void ipv6cp_SentTerminateReq(struct fsm *); 87static void ipv6cp_SendTerminateAck(struct fsm *, u_char); 88static void ipv6cp_DecodeConfig(struct fsm *, u_char *, int, int, 89 struct fsm_decode *); 90 91static struct fsm_callbacks ipv6cp_Callbacks = { 92 ipv6cp_LayerUp, 93 ipv6cp_LayerDown, 94 ipv6cp_LayerStart, 95 ipv6cp_LayerFinish, 96 ipv6cp_InitRestartCounter, 97 ipv6cp_SendConfigReq, 98 ipv6cp_SentTerminateReq, 99 ipv6cp_SendTerminateAck, 100 ipv6cp_DecodeConfig, 101 fsm_NullRecvResetReq, 102 fsm_NullRecvResetAck 103}; 104 105static u_int32_t 106GenerateToken(void) 107{ 108 /* Generate random number which will be used as negotiation token */ 109 randinit(); 110 111 return random() + 1; 112} 113 114static int 115ipcp_SetIPv6address(struct ipv6cp *ipv6cp, u_int32_t mytok, u_int32_t histok) 116{ 117 struct bundle *bundle = ipv6cp->fsm.bundle; 118 struct in6_addr myaddr, hisaddr; 119 struct ncprange myrange; 120 struct sockaddr_storage ssdst, ssgw, ssmask; 121 struct sockaddr *sadst, *sagw, *samask; 122 123 sadst = (struct sockaddr *)&ssdst; 124 sagw = (struct sockaddr *)&ssgw; 125 samask = (struct sockaddr *)&ssmask; 126 127 memset(&myaddr, '\0', sizeof myaddr); 128 memset(&hisaddr, '\0', sizeof hisaddr); 129 130 myaddr.s6_addr[0] = 0xfe; 131 myaddr.s6_addr[1] = 0x80; 132 *(u_int32_t *)(myaddr.s6_addr + 12) = htonl(mytok); 133 134 hisaddr.s6_addr[0] = 0xfe; 135 hisaddr.s6_addr[1] = 0x80; 136 *(u_int32_t *)(hisaddr.s6_addr + 12) = htonl(histok); 137 138 ncpaddr_setip6(&ipv6cp->myaddr, &myaddr); 139 ncpaddr_setip6(&ipv6cp->hisaddr, &hisaddr); 140 ncprange_sethost(&myrange, &ipv6cp->myaddr); 141 142 if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &ipv6cp->hisaddr, 143 IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 144 return 0; 145 146 if (!Enabled(bundle, OPT_IFACEALIAS)) 147 iface_Clear(bundle->iface, &bundle->ncp, AF_INET6, 148 IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 149 150 if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 151 ncprange_getsa(&myrange, &ssgw, &ssmask); 152 if (ncpaddr_isset(&ipv6cp->hisaddr)) 153 ncpaddr_getsa(&ipv6cp->hisaddr, &ssdst); 154 else 155 sadst = NULL; 156 rt_Update(bundle, sadst, sagw, samask); 157 } 158 159 if (Enabled(bundle, OPT_SROUTES)) 160 route_Change(bundle, bundle->ncp.route, &ipv6cp->myaddr, &ipv6cp->hisaddr); 161 162#ifndef NORADIUS 163 if (bundle->radius.valid) 164 route_Change(bundle, bundle->radius.routes, &ipv6cp->myaddr, 165 &ipv6cp->hisaddr); 166#endif 167 168 return 1; /* Ok */ 169} 170 171void 172ipv6cp_Init(struct ipv6cp *ipv6cp, struct bundle *bundle, struct link *l, 173 const struct fsm_parent *parent) 174{ 175 static const char * const timer_names[] = 176 {"IPV6CP restart", "IPV6CP openmode", "IPV6CP stopped"}; 177 int n; 178 179 fsm_Init(&ipv6cp->fsm, "IPV6CP", PROTO_IPV6CP, 1, IPV6CP_MAXCODE, LogIPV6CP, 180 bundle, l, parent, &ipv6cp_Callbacks, timer_names); 181 182 ipv6cp->cfg.fsm.timeout = DEF_FSMRETRY; 183 ipv6cp->cfg.fsm.maxreq = DEF_FSMTRIES; 184 ipv6cp->cfg.fsm.maxtrm = DEF_FSMTRIES; 185 186 ipv6cp->my_token = GenerateToken(); 187 while ((ipv6cp->peer_token = GenerateToken()) == ipv6cp->my_token) 188 ; 189 190 n = 100; 191 while (n && 192 !ipcp_SetIPv6address(ipv6cp, ipv6cp->my_token, ipv6cp->peer_token)) 193 while (n && (ipv6cp->my_token = GenerateToken()) == ipv6cp->peer_token) 194 n--; 195 196 throughput_init(&ipv6cp->throughput, SAMPLE_PERIOD); 197 memset(ipv6cp->Queue, '\0', sizeof ipv6cp->Queue); 198 ipv6cp_Setup(ipv6cp); 199} 200 201void 202ipv6cp_Destroy(struct ipv6cp *ipv6cp) 203{ 204 throughput_destroy(&ipv6cp->throughput); 205} 206 207void 208ipv6cp_Setup(struct ipv6cp *ipv6cp) 209{ 210 ncpaddr_init(&ipv6cp->myaddr); 211 ncpaddr_init(&ipv6cp->hisaddr); 212 213 ipv6cp->his_reject = 0; 214 ipv6cp->my_reject = 0; 215} 216 217void 218ipv6cp_SetLink(struct ipv6cp *ipv6cp, struct link *l) 219{ 220 ipv6cp->fsm.link = l; 221} 222 223int 224ipv6cp_Show(struct cmdargs const *arg) 225{ 226 struct ipv6cp *ipv6cp = &arg->bundle->ncp.ipv6cp; 227 228 if (!probe.ipv6_available) { 229 prompt_Printf(arg->prompt, "ipv6 not available\n"); 230 return 0; 231 } 232 233 prompt_Printf(arg->prompt, "%s [%s]\n", ipv6cp->fsm.name, 234 State2Nam(ipv6cp->fsm.state)); 235 if (ipv6cp->fsm.state == ST_OPENED) { 236 prompt_Printf(arg->prompt, " His side: %s\n", 237 ncpaddr_ntoa(&ipv6cp->hisaddr)); 238 prompt_Printf(arg->prompt, " My side: %s\n", 239 ncpaddr_ntoa(&ipv6cp->myaddr)); 240 prompt_Printf(arg->prompt, " Queued packets: %lu\n", 241 (unsigned long)ipv6cp_QueueLen(ipv6cp)); 242 } 243 244 prompt_Printf(arg->prompt, "\nDefaults:\n"); 245 prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 246 " REQ%s, %u Term REQ%s\n\n", ipv6cp->cfg.fsm.timeout, 247 ipv6cp->cfg.fsm.maxreq, ipv6cp->cfg.fsm.maxreq == 1 ? "" : "s", 248 ipv6cp->cfg.fsm.maxtrm, ipv6cp->cfg.fsm.maxtrm == 1 ? "" : "s"); 249 250 throughput_disp(&ipv6cp->throughput, arg->prompt); 251 252 return 0; 253} 254 255struct mbuf * 256ipv6cp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 257{ 258 /* Got PROTO_IPV6CP from link */ 259 m_settype(bp, MB_IPV6CPIN); 260 if (bundle_Phase(bundle) == PHASE_NETWORK && probe.ipv6_available) 261 fsm_Input(&bundle->ncp.ipv6cp.fsm, bp); 262 else { 263 if (bundle_Phase(bundle) < PHASE_NETWORK) 264 log_Printf(LogIPV6CP, "%s: Error: Unexpected IPV6CP in phase %s" 265 " (ignored)\n", l->name, bundle_PhaseName(bundle)); 266 m_freem(bp); 267 } 268 return NULL; 269} 270 271void 272ipv6cp_AddInOctets(struct ipv6cp *ipv6cp, int n) 273{ 274 throughput_addin(&ipv6cp->throughput, n); 275} 276 277void 278ipv6cp_AddOutOctets(struct ipv6cp *ipv6cp, int n) 279{ 280 throughput_addout(&ipv6cp->throughput, n); 281} 282 283void 284ipv6cp_IfaceAddrAdded(struct ipv6cp *ipv6cp, const struct iface_addr *addr) 285{ 286} 287 288void 289ipv6cp_IfaceAddrDeleted(struct ipv6cp *ipv6cp, const struct iface_addr *addr) 290{ 291} 292 293int 294ipv6cp_InterfaceUp(struct ipv6cp *ipv6cp) 295{ 296 if (!ipcp_SetIPv6address(ipv6cp, ipv6cp->my_token, ipv6cp->peer_token)) { 297 log_Printf(LogERROR, "ipv6cp_InterfaceUp: unable to set ipv6 address\n"); 298 return 0; 299 } 300 301 if (!iface_SetFlags(ipv6cp->fsm.bundle->iface->name, IFF_UP)) { 302 log_Printf(LogERROR, "ipv6cp_InterfaceUp: Can't set the IFF_UP" 303 " flag on %s\n", ipv6cp->fsm.bundle->iface->name); 304 return 0; 305 } 306 307 return 1; 308} 309 310size_t 311ipv6cp_QueueLen(struct ipv6cp *ipv6cp) 312{ 313 struct mqueue *q; 314 size_t result; 315 316 result = 0; 317 for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) 318 result += q->len; 319 320 return result; 321} 322 323int 324ipv6cp_PushPacket(struct ipv6cp *ipv6cp, struct link *l) 325{ 326 struct bundle *bundle = ipv6cp->fsm.bundle; 327 struct mqueue *queue; 328 struct mbuf *bp; 329 int m_len; 330 u_int32_t secs = 0; 331 unsigned alivesecs = 0; 332 333 if (ipv6cp->fsm.state != ST_OPENED) 334 return 0; 335 336 /* 337 * If ccp is not open but is required, do nothing. 338 */ 339 if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 340 log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 341 return 0; 342 } 343 344 queue = ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp) - 1; 345 do { 346 if (queue->top) { 347 bp = m_dequeue(queue); 348 bp = mbuf_Read(bp, &secs, sizeof secs); 349 bp = m_pullup(bp); 350 m_len = m_length(bp); 351 if (!FilterCheck(MBUF_CTOP(bp), AF_INET6, &bundle->filter.alive, 352 &alivesecs)) { 353 if (secs == 0) 354 secs = alivesecs; 355 bundle_StartIdleTimer(bundle, secs); 356 } 357 link_PushPacket(l, bp, bundle, 0, PROTO_IPV6); 358 ipv6cp_AddOutOctets(ipv6cp, m_len); 359 return 1; 360 } 361 } while (queue-- != ipv6cp->Queue); 362 363 return 0; 364} 365 366static int 367ipv6cp_LayerUp(struct fsm *fp) 368{ 369 /* We're now up */ 370 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 371 char tbuff[40]; 372 373 log_Printf(LogIPV6CP, "%s: LayerUp.\n", fp->link->name); 374 if (!ipv6cp_InterfaceUp(ipv6cp)) 375 return 0; 376 377 snprintf(tbuff, sizeof tbuff, "%s", ncpaddr_ntoa(&ipv6cp->myaddr)); 378 log_Printf(LogIPV6CP, "myaddr %s hisaddr = %s\n", 379 tbuff, ncpaddr_ntoa(&ipv6cp->hisaddr)); 380 381 /* XXX: Call radius_Account() and system_Select() */ 382 383 fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3; 384 log_DisplayPrompts(); 385 386 return 1; 387} 388 389static void 390ipv6cp_LayerDown(struct fsm *fp) 391{ 392 /* About to come down */ 393 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 394 static int recursing; 395 char addr[40]; 396 397 if (!recursing++) { 398 snprintf(addr, sizeof addr, "%s", ncpaddr_ntoa(&ipv6cp->myaddr)); 399 log_Printf(LogIPV6CP, "%s: LayerDown: %s\n", fp->link->name, addr); 400 401 /* XXX: Call radius_Account() and system_Select() */ 402 403 ipv6cp_Setup(ipv6cp); 404 } 405 recursing--; 406} 407 408static void 409ipv6cp_LayerStart(struct fsm *fp) 410{ 411 /* We're about to start up ! */ 412 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 413 414 log_Printf(LogIPV6CP, "%s: LayerStart.\n", fp->link->name); 415 throughput_start(&ipv6cp->throughput, "IPV6CP throughput", 416 Enabled(fp->bundle, OPT_THROUGHPUT)); 417 fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3; 418 ipv6cp->peer_tokenreq = 0; 419} 420 421static void 422ipv6cp_LayerFinish(struct fsm *fp) 423{ 424 /* We're now down */ 425 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 426 427 log_Printf(LogIPV6CP, "%s: LayerFinish.\n", fp->link->name); 428 throughput_stop(&ipv6cp->throughput); 429 throughput_log(&ipv6cp->throughput, LogIPV6CP, NULL); 430} 431 432static void 433ipv6cp_InitRestartCounter(struct fsm *fp, int what) 434{ 435 /* Set fsm timer load */ 436 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 437 438 fp->FsmTimer.load = ipv6cp->cfg.fsm.timeout * SECTICKS; 439 switch (what) { 440 case FSM_REQ_TIMER: 441 fp->restart = ipv6cp->cfg.fsm.maxreq; 442 break; 443 case FSM_TRM_TIMER: 444 fp->restart = ipv6cp->cfg.fsm.maxtrm; 445 break; 446 default: 447 fp->restart = 1; 448 break; 449 } 450} 451 452static void 453ipv6cp_SendConfigReq(struct fsm *fp) 454{ 455 /* Send config REQ please */ 456 struct physical *p = link2physical(fp->link); 457 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 458 u_char buff[6]; 459 struct lcp_opt *o; 460 461 o = (struct lcp_opt *)buff; 462 463 if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) { 464 memcpy(o->data, &ipv6cp->my_token, 4); 465 INC_LCP_OPT(TY_TOKEN, 6, o); 466 } 467 468 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 469 MB_IPV6CPOUT); 470} 471 472static void 473ipv6cp_SentTerminateReq(struct fsm *fp) 474{ 475 /* Term REQ just sent by FSM */ 476} 477 478static void 479ipv6cp_SendTerminateAck(struct fsm *fp, u_char id) 480{ 481 /* Send Term ACK please */ 482 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPV6CPOUT); 483} 484 485static const char * 486protoname(int proto) 487{ 488 static const char *cftypes[] = { "TOKEN", "COMPPROTO" }; 489 490 if (proto > 0 && proto <= sizeof cftypes / sizeof *cftypes) 491 return cftypes[proto - 1]; 492 493 return NumStr(proto, NULL, 0); 494} 495 496static void 497ipv6cp_ValidateToken(struct ipv6cp *ipv6cp, u_int32_t token, 498 struct fsm_decode *dec) 499{ 500 if (token != 0 && token != ipv6cp->my_token) 501 ipv6cp->peer_token = token; 502 503 if (token == ipv6cp->peer_token) { 504 *dec->ackend++ = TY_TOKEN; 505 *dec->ackend++ = 6; 506 memcpy(dec->ackend, &ipv6cp->peer_token, 4); 507 dec->ackend += 4; 508 } else { 509 *dec->nakend++ = TY_TOKEN; 510 *dec->nakend++ = 6; 511 memcpy(dec->nakend, &ipv6cp->peer_token, 4); 512 dec->nakend += 4; 513 } 514} 515 516static void 517ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 518 struct fsm_decode *dec) 519{ 520 /* Deal with incoming PROTO_IPV6CP */ 521 struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 522 int type, length, n; 523 char tbuff[100]; 524 u_int32_t token; 525 526 while (plen >= sizeof(struct fsmconfig)) { 527 type = *cp; 528 length = cp[1]; 529 530 if (length == 0) { 531 log_Printf(LogIPV6CP, "%s: IPV6CP size zero\n", fp->link->name); 532 break; 533 } 534 535 snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length); 536 537 switch (type) { 538 case TY_TOKEN: 539 memcpy(&token, cp + 2, 4); 540 log_Printf(LogIPV6CP, "%s 0x%08lx\n", tbuff, (unsigned long)token); 541 542 switch (mode_type) { 543 case MODE_REQ: 544 ipv6cp->peer_tokenreq = 1; 545 ipv6cp_ValidateToken(ipv6cp, token, dec); 546 break; 547 548 case MODE_NAK: 549 if (token == 0) { 550 log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 551 "0x00000000: Unacceptable token!\n"); 552 fsm_Close(&ipv6cp->fsm); 553 } else if (token == ipv6cp->peer_token) 554 log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 555 "0x08lx: Unacceptable token!\n", (unsigned long)token); 556 else if (token != ipv6cp->my_token) { 557 n = 100; 558 while (n && !ipcp_SetIPv6address(ipv6cp, token, ipv6cp->peer_token)) 559 while (n && (token = GenerateToken()) == ipv6cp->peer_token) 560 n--; 561 562 if (n == 0) { 563 log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 564 "0x00000000: Unacceptable token!\n"); 565 fsm_Close(&ipv6cp->fsm); 566 } else { 567 log_Printf(LogIPV6CP, "%s changing token: 0x%08lx --> 0x%08lx\n", 568 tbuff, (unsigned long)ipv6cp->my_token, 569 (unsigned long)token); 570 ipv6cp->my_token = token; 571 bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL); 572 } 573 } 574 break; 575 576 case MODE_REJ: 577 ipv6cp->his_reject |= (1 << type); 578 break; 579 } 580 break; 581 582 default: 583 if (mode_type != MODE_NOP) { 584 ipv6cp->my_reject |= (1 << type); 585 memcpy(dec->rejend, cp, length); 586 dec->rejend += length; 587 } 588 break; 589 } 590 plen -= length; 591 cp += length; 592 } 593 594 if (mode_type != MODE_NOP) { 595 if (mode_type == MODE_REQ && !ipv6cp->peer_tokenreq) { 596 if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 597 /* 598 * Pretend the peer has requested a TOKEN. 599 * We do this to ensure that we only send one NAK if the only 600 * reason for the NAK is because the peer isn't sending a 601 * TY_TOKEN REQ. This stops us from repeatedly trying to tell 602 * the peer that we have to have an IP address on their end. 603 */ 604 ipv6cp->peer_tokenreq = 1; 605 } 606 ipv6cp_ValidateToken(ipv6cp, 0, dec); 607 } 608 if (dec->rejend != dec->rej) { 609 /* rejects are preferred */ 610 dec->ackend = dec->ack; 611 dec->nakend = dec->nak; 612 } else if (dec->nakend != dec->nak) 613 /* then NAKs */ 614 dec->ackend = dec->ack; 615 } 616} 617#endif 618