ipv6cp.c revision 94894
1165138Syongari/*- 2165138Syongari * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org> 3165138Syongari * All rights reserved. 4165138Syongari * 5165138Syongari * Redistribution and use in source and binary forms, with or without 6165138Syongari * modification, are permitted provided that the following conditions 7165138Syongari * are met: 8165138Syongari * 1. Redistributions of source code must retain the above copyright 9165138Syongari * notice, this list of conditions and the following disclaimer. 10165138Syongari * 2. Redistributions in binary form must reproduce the above copyright 11165138Syongari * notice, this list of conditions and the following disclaimer in the 12165138Syongari * documentation and/or other materials provided with the distribution. 13165138Syongari * 14165138Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15165138Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16165138Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17165138Syongari * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18165138Syongari * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19165138Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20165138Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21165138Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22165138Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23165138Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24165138Syongari * SUCH DAMAGE. 25165138Syongari * 26165138Syongari * $FreeBSD: head/usr.sbin/ppp/ipv6cp.c 94894 2002-04-16 23:57:09Z brian $ 27165138Syongari */ 28165138Syongari 29165138Syongari#include <sys/param.h> 30165138Syongari#include <netinet/in_systm.h> 31165138Syongari#include <netinet/in.h> 32165138Syongari#include <netinet/ip.h> 33165138Syongari#include <sys/socket.h> 34165138Syongari#include <net/route.h> 35165138Syongari#include <net/if.h> 36165138Syongari#include <sys/un.h> 37165138Syongari 38165138Syongari#include <stdio.h> 39165138Syongari#include <stdlib.h> 40165138Syongari#include <string.h> 41165138Syongari#include <termios.h> 42165138Syongari 43165138Syongari#include "layer.h" 44165138Syongari#include "defs.h" 45165138Syongari#include "mbuf.h" 46165138Syongari#include "timer.h" 47165138Syongari#include "fsm.h" 48165138Syongari#include "iplist.h" 49165138Syongari#include "throughput.h" 50165138Syongari#include "slcompress.h" 51165138Syongari#include "lqr.h" 52165138Syongari#include "hdlc.h" 53165138Syongari#include "lcp.h" 54165138Syongari#include "ncpaddr.h" 55165138Syongari#include "ip.h" 56165138Syongari#include "ipcp.h" 57165138Syongari#include "ipv6cp.h" 58165138Syongari#include "filter.h" 59165138Syongari#include "descriptor.h" 60165138Syongari#include "ccp.h" 61165138Syongari#include "link.h" 62165138Syongari#include "mp.h" 63165138Syongari#ifndef NORADIUS 64165138Syongari#include "radius.h" 65165138Syongari#endif 66165138Syongari#include "ncp.h" 67165138Syongari#include "bundle.h" 68165138Syongari#include "route.h" 69165138Syongari#include "iface.h" 70165138Syongari#include "log.h" 71165138Syongari#include "proto.h" 72165138Syongari#include "command.h" 73165138Syongari#include "prompt.h" 74165138Syongari#include "async.h" 75165138Syongari#include "physical.h" 76165138Syongari#include "probe.h" 77165138Syongari 78165138Syongari 79165138Syongari#ifndef NOINET6 80165138Syongaristatic int ipv6cp_LayerUp(struct fsm *); 81165138Syongaristatic void ipv6cp_LayerDown(struct fsm *); 82165138Syongaristatic void ipv6cp_LayerStart(struct fsm *); 83165138Syongaristatic void ipv6cp_LayerFinish(struct fsm *); 84165138Syongaristatic void ipv6cp_InitRestartCounter(struct fsm *, int); 85165138Syongaristatic void ipv6cp_SendConfigReq(struct fsm *); 86165138Syongaristatic void ipv6cp_SentTerminateReq(struct fsm *); 87165138Syongaristatic void ipv6cp_SendTerminateAck(struct fsm *, u_char); 88165138Syongaristatic void ipv6cp_DecodeConfig(struct fsm *, u_char *, u_char *, int, 89165138Syongari struct fsm_decode *); 90165138Syongari 91165138Syongaristatic struct fsm_callbacks ipv6cp_Callbacks = { 92165138Syongari ipv6cp_LayerUp, 93165138Syongari ipv6cp_LayerDown, 94165138Syongari ipv6cp_LayerStart, 95165138Syongari ipv6cp_LayerFinish, 96165138Syongari ipv6cp_InitRestartCounter, 97165138Syongari ipv6cp_SendConfigReq, 98165138Syongari ipv6cp_SentTerminateReq, 99165138Syongari ipv6cp_SendTerminateAck, 100165138Syongari ipv6cp_DecodeConfig, 101165138Syongari fsm_NullRecvResetReq, 102165138Syongari fsm_NullRecvResetAck 103165138Syongari}; 104165138Syongari 105165138Syongaristatic u_int32_t 106165138SyongariGenerateToken(void) 107165138Syongari{ 108165138Syongari /* Generate random number which will be used as negotiation token */ 109165138Syongari randinit(); 110165138Syongari 111165138Syongari return random() + 1; 112165138Syongari} 113165138Syongari 114165138Syongaristatic int 115165138Syongariipcp_SetIPv6address(struct ipv6cp *ipv6cp, u_int32_t mytok, u_int32_t histok) 116165138Syongari{ 117165138Syongari struct bundle *bundle = ipv6cp->fsm.bundle; 118165138Syongari struct in6_addr myaddr, hisaddr; 119165138Syongari struct ncprange myrange; 120165138Syongari struct sockaddr_storage ssdst, ssgw, ssmask; 121165138Syongari struct sockaddr *sadst, *sagw, *samask; 122165138Syongari 123165138Syongari sadst = (struct sockaddr *)&ssdst; 124165138Syongari sagw = (struct sockaddr *)&ssgw; 125165138Syongari samask = (struct sockaddr *)&ssmask; 126165138Syongari 127165138Syongari memset(&myaddr, '\0', sizeof myaddr); 128165138Syongari memset(&hisaddr, '\0', sizeof hisaddr); 129165138Syongari 130165138Syongari myaddr.s6_addr[0] = 0xfe; 131165138Syongari myaddr.s6_addr[1] = 0x80; 132165138Syongari *(u_int32_t *)(myaddr.s6_addr + 12) = htonl(mytok); 133192736Syongari 134192736Syongari hisaddr.s6_addr[0] = 0xfe; 135192736Syongari hisaddr.s6_addr[1] = 0x80; 136192736Syongari *(u_int32_t *)(hisaddr.s6_addr + 12) = htonl(histok); 137165138Syongari 138165138Syongari ncpaddr_setip6(&ipv6cp->myaddr, &myaddr); 139165138Syongari ncpaddr_setip6(&ipv6cp->hisaddr, &hisaddr); 140165138Syongari ncprange_sethost(&myrange, &ipv6cp->myaddr); 141165138Syongari 142193299Syongari if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &ipv6cp->hisaddr, 143173775Syongari IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 144193299Syongari return 0; 145193299Syongari 146165138Syongari if (!Enabled(bundle, OPT_IFACEALIAS)) 147165138Syongari iface_Clear(bundle->iface, &bundle->ncp, AF_INET6, 148165138Syongari IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 149165138Syongari 150165138Syongari if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 151197592Syongari ncprange_getsa(&myrange, &ssgw, &ssmask); 152165138Syongari if (ncpaddr_isset(&ipv6cp->hisaddr)) 153165138Syongari ncpaddr_getsa(&ipv6cp->hisaddr, &ssdst); 154165138Syongari else 155165138Syongari sadst = NULL; 156165138Syongari rt_Update(bundle, sadst, sagw, samask); 157165138Syongari } 158165138Syongari 159165138Syongari if (Enabled(bundle, OPT_SROUTES)) 160165138Syongari route_Change(bundle, bundle->ncp.route, &ipv6cp->myaddr, &ipv6cp->hisaddr); 161165138Syongari 162165138Syongari#ifndef NORADIUS 163165138Syongari if (bundle->radius.valid) 164165138Syongari route_Change(bundle, bundle->radius.routes, &ipv6cp->myaddr, 165165138Syongari &ipv6cp->hisaddr); 166165138Syongari#endif 167165138Syongari 168165138Syongari return 1; /* Ok */ 169165138Syongari} 170165138Syongari 171165138Syongarivoid 172165138Syongariipv6cp_Init(struct ipv6cp *ipv6cp, struct bundle *bundle, struct link *l, 173165138Syongari const struct fsm_parent *parent) 174165138Syongari{ 175165138Syongari static const char * const timer_names[] = 176165138Syongari {"IPV6CP restart", "IPV6CP openmode", "IPV6CP stopped"}; 177165138Syongari int n; 178165138Syongari 179165138Syongari fsm_Init(&ipv6cp->fsm, "IPV6CP", PROTO_IPV6CP, 1, IPV6CP_MAXCODE, LogIPV6CP, 180165138Syongari bundle, l, parent, &ipv6cp_Callbacks, timer_names); 181165138Syongari 182165138Syongari ipv6cp->cfg.fsm.timeout = DEF_FSMRETRY; 183165138Syongari ipv6cp->cfg.fsm.maxreq = DEF_FSMTRIES; 184165138Syongari ipv6cp->cfg.fsm.maxtrm = DEF_FSMTRIES; 185165138Syongari 186165138Syongari ipv6cp->my_token = GenerateToken(); 187165138Syongari while ((ipv6cp->peer_token = GenerateToken()) == ipv6cp->my_token) 188165138Syongari ; 189165138Syongari 190165138Syongari if (probe.ipv6_available) { 191165138Syongari n = 100; 192165138Syongari while (n && 193165138Syongari !ipcp_SetIPv6address(ipv6cp, ipv6cp->my_token, ipv6cp->peer_token)) { 194165138Syongari n--; 195165138Syongari while (n && (ipv6cp->my_token = GenerateToken()) == ipv6cp->peer_token) 196165138Syongari n--; 197165138Syongari } 198165138Syongari } 199165138Syongari 200165138Syongari throughput_init(&ipv6cp->throughput, SAMPLE_PERIOD); 201165138Syongari memset(ipv6cp->Queue, '\0', sizeof ipv6cp->Queue); 202165138Syongari ipv6cp_Setup(ipv6cp); 203165138Syongari} 204165138Syongari 205165138Syongarivoid 206165138Syongariipv6cp_Destroy(struct ipv6cp *ipv6cp) 207165138Syongari{ 208165138Syongari throughput_destroy(&ipv6cp->throughput); 209165138Syongari} 210165138Syongari 211165138Syongarivoid 212165138Syongariipv6cp_Setup(struct ipv6cp *ipv6cp) 213165138Syongari{ 214165138Syongari ncpaddr_init(&ipv6cp->myaddr); 215165138Syongari ncpaddr_init(&ipv6cp->hisaddr); 216165138Syongari 217165138Syongari ipv6cp->his_reject = 0; 218165138Syongari ipv6cp->my_reject = 0; 219165138Syongari} 220165138Syongari 221165138Syongarivoid 222165138Syongariipv6cp_SetLink(struct ipv6cp *ipv6cp, struct link *l) 223165138Syongari{ 224165138Syongari ipv6cp->fsm.link = l; 225165138Syongari} 226165138Syongari 227165138Syongariint 228165138Syongariipv6cp_Show(struct cmdargs const *arg) 229165138Syongari{ 230165138Syongari struct ipv6cp *ipv6cp = &arg->bundle->ncp.ipv6cp; 231193293Syongari 232193293Syongari prompt_Printf(arg->prompt, "%s [%s]\n", ipv6cp->fsm.name, 233165138Syongari State2Nam(ipv6cp->fsm.state)); 234165138Syongari if (ipv6cp->fsm.state == ST_OPENED) { 235165138Syongari prompt_Printf(arg->prompt, " His side: %s\n", 236165138Syongari ncpaddr_ntoa(&ipv6cp->hisaddr)); 237165138Syongari prompt_Printf(arg->prompt, " My side: %s\n", 238165138Syongari ncpaddr_ntoa(&ipv6cp->myaddr)); 239165138Syongari prompt_Printf(arg->prompt, " Queued packets: %lu\n", 240165138Syongari (unsigned long)ipv6cp_QueueLen(ipv6cp)); 241165138Syongari } 242165138Syongari 243165138Syongari prompt_Printf(arg->prompt, "\nDefaults:\n"); 244165138Syongari prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 245165138Syongari " REQ%s, %u Term REQ%s\n\n", ipv6cp->cfg.fsm.timeout, 246165138Syongari ipv6cp->cfg.fsm.maxreq, ipv6cp->cfg.fsm.maxreq == 1 ? "" : "s", 247165138Syongari ipv6cp->cfg.fsm.maxtrm, ipv6cp->cfg.fsm.maxtrm == 1 ? "" : "s"); 248165138Syongari 249165138Syongari throughput_disp(&ipv6cp->throughput, arg->prompt); 250165138Syongari 251165138Syongari return 0; 252165138Syongari} 253165138Syongari 254165138Syongaristruct mbuf * 255165138Syongariipv6cp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 256165138Syongari{ 257165138Syongari /* Got PROTO_IPV6CP from link */ 258165138Syongari m_settype(bp, MB_IPV6CPIN); 259165138Syongari if (bundle_Phase(bundle) == PHASE_NETWORK) 260165138Syongari fsm_Input(&bundle->ncp.ipv6cp.fsm, bp); 261165138Syongari else { 262165138Syongari if (bundle_Phase(bundle) < PHASE_NETWORK) 263165138Syongari log_Printf(LogIPV6CP, "%s: Error: Unexpected IPV6CP in phase %s" 264165138Syongari " (ignored)\n", l->name, bundle_PhaseName(bundle)); 265165138Syongari m_freem(bp); 266165138Syongari } 267165138Syongari return NULL; 268165138Syongari} 269165138Syongari 270165138Syongarivoid 271165138Syongariipv6cp_AddInOctets(struct ipv6cp *ipv6cp, int n) 272165138Syongari{ 273165138Syongari throughput_addin(&ipv6cp->throughput, n); 274165138Syongari} 275165138Syongari 276165138Syongarivoid 277165138Syongariipv6cp_AddOutOctets(struct ipv6cp *ipv6cp, int n) 278165138Syongari{ 279165138Syongari throughput_addout(&ipv6cp->throughput, n); 280165138Syongari} 281165138Syongari 282165138Syongarivoid 283165138Syongariipv6cp_IfaceAddrAdded(struct ipv6cp *ipv6cp, const struct iface_addr *addr) 284165138Syongari{ 285165138Syongari} 286165138Syongari 287165138Syongarivoid 288165138Syongariipv6cp_IfaceAddrDeleted(struct ipv6cp *ipv6cp, const struct iface_addr *addr) 289165138Syongari{ 290165138Syongari} 291165138Syongari 292165138Syongariint 293165138Syongariipv6cp_InterfaceUp(struct ipv6cp *ipv6cp) 294165138Syongari{ 295165138Syongari if (!ipcp_SetIPv6address(ipv6cp, ipv6cp->my_token, ipv6cp->peer_token)) { 296165138Syongari log_Printf(LogERROR, "ipv6cp_InterfaceUp: unable to set ipv6 address\n"); 297165138Syongari return 0; 298165138Syongari } 299165138Syongari 300165138Syongari if (!iface_SetFlags(ipv6cp->fsm.bundle->iface->name, IFF_UP)) { 301165138Syongari log_Printf(LogERROR, "ipv6cp_InterfaceUp: Can't set the IFF_UP" 302165138Syongari " flag on %s\n", ipv6cp->fsm.bundle->iface->name); 303165138Syongari return 0; 304165138Syongari } 305165138Syongari 306165138Syongari return 1; 307165138Syongari} 308165138Syongari 309165138Syongarisize_t 310165138Syongariipv6cp_QueueLen(struct ipv6cp *ipv6cp) 311165138Syongari{ 312165138Syongari struct mqueue *q; 313165138Syongari size_t result; 314165138Syongari 315165138Syongari result = 0; 316165138Syongari for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) 317165138Syongari result += q->len; 318165138Syongari 319165138Syongari return result; 320165138Syongari} 321165138Syongari 322165138Syongariint 323165138Syongariipv6cp_PushPacket(struct ipv6cp *ipv6cp, struct link *l) 324165138Syongari{ 325165138Syongari struct bundle *bundle = ipv6cp->fsm.bundle; 326165138Syongari struct mqueue *queue; 327165138Syongari struct mbuf *bp; 328165138Syongari int m_len; 329165138Syongari u_int32_t secs = 0; 330165138Syongari unsigned alivesecs = 0; 331165138Syongari 332165138Syongari if (ipv6cp->fsm.state != ST_OPENED) 333193293Syongari return 0; 334193293Syongari 335193293Syongari /* 336193293Syongari * If ccp is not open but is required, do nothing. 337193293Syongari */ 338193293Syongari if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 339193293Syongari log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 340193293Syongari return 0; 341193293Syongari } 342193293Syongari 343193293Syongari queue = ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp) - 1; 344193293Syongari do { 345193293Syongari if (queue->top) { 346193293Syongari bp = m_dequeue(queue); 347193293Syongari bp = mbuf_Read(bp, &secs, sizeof secs); 348193293Syongari bp = m_pullup(bp); 349193293Syongari m_len = m_length(bp); 350193293Syongari if (!FilterCheck(MBUF_CTOP(bp), AF_INET6, &bundle->filter.alive, 351193293Syongari &alivesecs)) { 352193293Syongari if (secs == 0) 353193293Syongari secs = alivesecs; 354193293Syongari bundle_StartIdleTimer(bundle, secs); 355193293Syongari } 356193293Syongari link_PushPacket(l, bp, bundle, 0, PROTO_IPV6); 357193293Syongari ipv6cp_AddOutOctets(ipv6cp, m_len); 358193293Syongari return 1; 359193293Syongari } 360193293Syongari } while (queue-- != ipv6cp->Queue); 361193293Syongari 362193293Syongari return 0; 363193293Syongari} 364193293Syongari 365193293Syongaristatic int 366193293Syongariipv6cp_LayerUp(struct fsm *fp) 367193293Syongari{ 368193293Syongari /* We're now up */ 369193293Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 370193293Syongari char tbuff[40]; 371193293Syongari 372193293Syongari log_Printf(LogIPV6CP, "%s: LayerUp.\n", fp->link->name); 373193293Syongari if (!ipv6cp_InterfaceUp(ipv6cp)) 374193293Syongari return 0; 375193293Syongari 376193293Syongari snprintf(tbuff, sizeof tbuff, "%s", ncpaddr_ntoa(&ipv6cp->myaddr)); 377193293Syongari log_Printf(LogIPV6CP, "myaddr %s hisaddr = %s\n", 378193293Syongari tbuff, ncpaddr_ntoa(&ipv6cp->hisaddr)); 379193293Syongari 380193293Syongari /* XXX: Call radius_Account() and system_Select() */ 381193293Syongari 382193293Syongari fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3; 383165138Syongari log_DisplayPrompts(); 384165138Syongari 385165138Syongari return 1; 386165138Syongari} 387165138Syongari 388165138Syongaristatic void 389165138Syongariipv6cp_LayerDown(struct fsm *fp) 390165138Syongari{ 391165138Syongari /* About to come down */ 392165138Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 393165138Syongari static int recursing; 394165138Syongari char addr[40]; 395165138Syongari 396165138Syongari if (!recursing++) { 397165138Syongari snprintf(addr, sizeof addr, "%s", ncpaddr_ntoa(&ipv6cp->myaddr)); 398165138Syongari log_Printf(LogIPV6CP, "%s: LayerDown: %s\n", fp->link->name, addr); 399165138Syongari 400165138Syongari /* XXX: Call radius_Account() and system_Select() */ 401165138Syongari 402165138Syongari ipv6cp_Setup(ipv6cp); 403165138Syongari } 404165138Syongari recursing--; 405165138Syongari} 406165138Syongari 407165138Syongaristatic void 408165138Syongariipv6cp_LayerStart(struct fsm *fp) 409165138Syongari{ 410165138Syongari /* We're about to start up ! */ 411165138Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 412165138Syongari 413165138Syongari log_Printf(LogIPV6CP, "%s: LayerStart.\n", fp->link->name); 414165138Syongari throughput_start(&ipv6cp->throughput, "IPV6CP throughput", 415165138Syongari Enabled(fp->bundle, OPT_THROUGHPUT)); 416165138Syongari fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3; 417165138Syongari ipv6cp->peer_tokenreq = 0; 418165138Syongari} 419165138Syongari 420165138Syongaristatic void 421165138Syongariipv6cp_LayerFinish(struct fsm *fp) 422165138Syongari{ 423165138Syongari /* We're now down */ 424165138Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 425165138Syongari 426165138Syongari log_Printf(LogIPV6CP, "%s: LayerFinish.\n", fp->link->name); 427165138Syongari throughput_stop(&ipv6cp->throughput); 428165138Syongari throughput_log(&ipv6cp->throughput, LogIPV6CP, NULL); 429165138Syongari} 430165138Syongari 431165138Syongaristatic void 432165138Syongariipv6cp_InitRestartCounter(struct fsm *fp, int what) 433165138Syongari{ 434165138Syongari /* Set fsm timer load */ 435165138Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 436165138Syongari 437165138Syongari fp->FsmTimer.load = ipv6cp->cfg.fsm.timeout * SECTICKS; 438165138Syongari switch (what) { 439165138Syongari case FSM_REQ_TIMER: 440165138Syongari fp->restart = ipv6cp->cfg.fsm.maxreq; 441165138Syongari break; 442165138Syongari case FSM_TRM_TIMER: 443165138Syongari fp->restart = ipv6cp->cfg.fsm.maxtrm; 444165138Syongari break; 445165138Syongari default: 446165138Syongari fp->restart = 1; 447165138Syongari break; 448165138Syongari } 449165138Syongari} 450165138Syongari 451165138Syongaristatic void 452165138Syongariipv6cp_SendConfigReq(struct fsm *fp) 453165138Syongari{ 454165138Syongari /* Send config REQ please */ 455165138Syongari struct physical *p = link2physical(fp->link); 456165138Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 457165138Syongari u_char buff[6]; 458165138Syongari struct fsm_opt *o; 459165138Syongari 460165138Syongari o = (struct fsm_opt *)buff; 461165138Syongari 462165138Syongari if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) { 463165138Syongari memcpy(o->data, &ipv6cp->my_token, 4); 464165138Syongari INC_FSM_OPT(TY_TOKEN, 6, o); 465165138Syongari } 466165138Syongari 467165138Syongari fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 468165138Syongari MB_IPV6CPOUT); 469165138Syongari} 470165138Syongari 471165138Syongaristatic void 472165138Syongariipv6cp_SentTerminateReq(struct fsm *fp) 473165138Syongari{ 474165138Syongari /* Term REQ just sent by FSM */ 475165138Syongari} 476165138Syongari 477165138Syongaristatic void 478165138Syongariipv6cp_SendTerminateAck(struct fsm *fp, u_char id) 479165138Syongari{ 480165138Syongari /* Send Term ACK please */ 481165138Syongari fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPV6CPOUT); 482165138Syongari} 483165138Syongari 484165138Syongaristatic const char * 485165138Syongariprotoname(int proto) 486165138Syongari{ 487165138Syongari static const char *cftypes[] = { "TOKEN", "COMPPROTO" }; 488165138Syongari 489165138Syongari if (proto > 0 && proto <= sizeof cftypes / sizeof *cftypes) 490165138Syongari return cftypes[proto - 1]; 491165138Syongari 492165138Syongari return NumStr(proto, NULL, 0); 493165138Syongari} 494165138Syongari 495165138Syongaristatic void 496165138Syongariipv6cp_ValidateToken(struct ipv6cp *ipv6cp, u_int32_t token, 497165138Syongari struct fsm_decode *dec) 498165138Syongari{ 499165138Syongari struct fsm_opt opt; 500165138Syongari 501165138Syongari if (token != 0 && token != ipv6cp->my_token) 502165138Syongari ipv6cp->peer_token = token; 503165138Syongari 504165138Syongari opt.hdr.id = TY_TOKEN; 505165138Syongari opt.hdr.len = 6; 506165138Syongari memcpy(opt.data, &ipv6cp->peer_token, 4); 507165138Syongari if (token == ipv6cp->peer_token) 508165138Syongari fsm_ack(dec, &opt); 509165138Syongari else 510165138Syongari fsm_nak(dec, &opt); 511165138Syongari} 512165138Syongari 513165138Syongaristatic void 514165138Syongariipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 515165138Syongari struct fsm_decode *dec) 516165138Syongari{ 517165138Syongari /* Deal with incoming PROTO_IPV6CP */ 518165138Syongari struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); 519165138Syongari int n; 520165138Syongari char tbuff[100]; 521165138Syongari u_int32_t token; 522165138Syongari struct fsm_opt *opt; 523165138Syongari 524165138Syongari while (end - cp >= sizeof(opt->hdr)) { 525165138Syongari if ((opt = fsm_readopt(&cp)) == NULL) 526165138Syongari break; 527165138Syongari 528165138Syongari snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 529165138Syongari opt->hdr.len); 530165138Syongari 531165138Syongari switch (opt->hdr.id) { 532165138Syongari case TY_TOKEN: 533165138Syongari memcpy(&token, opt->data, 4); 534165138Syongari log_Printf(LogIPV6CP, "%s 0x%08lx\n", tbuff, (unsigned long)token); 535165138Syongari 536165138Syongari switch (mode_type) { 537165138Syongari case MODE_REQ: 538165138Syongari ipv6cp->peer_tokenreq = 1; 539165138Syongari ipv6cp_ValidateToken(ipv6cp, token, dec); 540165138Syongari break; 541165138Syongari 542165138Syongari case MODE_NAK: 543165138Syongari if (token == 0) { 544165138Syongari log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 545165138Syongari "0x00000000: Unacceptable token!\n"); 546165138Syongari fsm_Close(&ipv6cp->fsm); 547165138Syongari } else if (token == ipv6cp->peer_token) 548165138Syongari log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 549165138Syongari "0x%08lx: Unacceptable token!\n", (unsigned long)token); 550165138Syongari else if (token != ipv6cp->my_token) { 551165138Syongari n = 100; 552165138Syongari while (n && !ipcp_SetIPv6address(ipv6cp, token, ipv6cp->peer_token)) { 553165138Syongari n--; 554165138Syongari while (n && (token = GenerateToken()) == ipv6cp->peer_token) 555165138Syongari n--; 556165138Syongari } 557165138Syongari 558165138Syongari if (n == 0) { 559165138Syongari log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE, 560165138Syongari "0x00000000: Unacceptable token!\n"); 561165138Syongari fsm_Close(&ipv6cp->fsm); 562165138Syongari } else { 563165138Syongari log_Printf(LogIPV6CP, "%s changing token: 0x%08lx --> 0x%08lx\n", 564165138Syongari tbuff, (unsigned long)ipv6cp->my_token, 565165138Syongari (unsigned long)token); 566165138Syongari ipv6cp->my_token = token; 567165138Syongari bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL); 568165138Syongari } 569165138Syongari } 570165138Syongari break; 571165138Syongari 572165138Syongari case MODE_REJ: 573165138Syongari ipv6cp->his_reject |= (1 << opt->hdr.id); 574165138Syongari break; 575165138Syongari } 576165138Syongari break; 577165138Syongari 578165138Syongari default: 579165138Syongari if (mode_type != MODE_NOP) { 580165138Syongari ipv6cp->my_reject |= (1 << opt->hdr.id); 581165138Syongari fsm_rej(dec, opt); 582165138Syongari } 583165138Syongari break; 584165138Syongari } 585165138Syongari } 586165138Syongari 587165138Syongari if (mode_type != MODE_NOP) { 588165138Syongari if (mode_type == MODE_REQ && !ipv6cp->peer_tokenreq) { 589165138Syongari if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 590165138Syongari /* 591165138Syongari * Pretend the peer has requested a TOKEN. 592165138Syongari * We do this to ensure that we only send one NAK if the only 593165138Syongari * reason for the NAK is because the peer isn't sending a 594165138Syongari * TY_TOKEN REQ. This stops us from repeatedly trying to tell 595165138Syongari * the peer that we have to have an IP address on their end. 596165138Syongari */ 597165138Syongari ipv6cp->peer_tokenreq = 1; 598165138Syongari } 599165138Syongari ipv6cp_ValidateToken(ipv6cp, 0, dec); 600165138Syongari } 601165138Syongari fsm_opt_normalise(dec); 602165138Syongari } 603165138Syongari} 604165138Syongari#endif 605165138Syongari