1706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*-
2706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * All rights reserved.
4706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
5706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Redistribution and use in source and binary forms, with or without
6706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * modification, are permitted provided that the following conditions
7706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * are met:
8706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 1. Redistributions of source code must retain the above copyright
9706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer.
10706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 2. Redistributions in binary form must reproduce the above copyright
11706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer in the
12706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    documentation and/or other materials provided with the distribution.
13706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
14706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * SUCH DAMAGE.
25706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
26706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * $FreeBSD: src/usr.sbin/ppp/ipv6cp.c,v 1.17.10.1.2.1 2010/12/21 17:10:29 kensmith Exp $
27706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
28706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
29706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/param.h>
30706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in_systm.h>
31706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in.h>
32706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/ip.h>
33706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/socket.h>
34706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/route.h>
35706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/if.h>
36706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/if_types.h>
37706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/if_dl.h>
38706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/un.h>
39706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
40706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdarg.h>
41706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdio.h>
42706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdlib.h>
43706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <string.h>
44706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <termios.h>
45706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <ifaddrs.h>
46706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
47706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "layer.h"
48706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "defs.h"
49706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mbuf.h"
50706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "timer.h"
51706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "fsm.h"
52706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iplist.h"
53706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "throughput.h"
54706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "slcompress.h"
55706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lqr.h"
56706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "hdlc.h"
57706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lcp.h"
58706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncpaddr.h"
59706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ip.h"
60706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipcp.h"
61706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipv6cp.h"
62706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "filter.h"
63706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "descriptor.h"
64706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ccp.h"
65706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "link.h"
66706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mp.h"
67706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
68706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "radius.h"
69706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
70706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncp.h"
71706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "bundle.h"
72706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "route.h"
73706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iface.h"
74706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "log.h"
75706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "proto.h"
76706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "command.h"
77706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "prompt.h"
78706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "async.h"
79706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "physical.h"
80706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "probe.h"
81706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "systems.h"
82706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
83706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
84706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NOINET6
85706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#define IN6ADDR_LINKLOCAL_MCAST_INIT \
86706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
87706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
88706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic const struct in6_addr in6addr_linklocal_mcast =
89706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	IN6ADDR_LINKLOCAL_MCAST_INIT;
90706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
91706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int ipv6cp_LayerUp(struct fsm *);
92706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_LayerDown(struct fsm *);
93706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_LayerStart(struct fsm *);
94706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_LayerFinish(struct fsm *);
95706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_InitRestartCounter(struct fsm *, int);
96706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_SendConfigReq(struct fsm *);
97706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_SentTerminateReq(struct fsm *);
98706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_SendTerminateAck(struct fsm *, u_char);
99706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void ipv6cp_DecodeConfig(struct fsm *, u_char *, u_char *, int,
100706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                                struct fsm_decode *);
101706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
102706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct fsm_callbacks ipv6cp_Callbacks = {
103706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_LayerUp,
104706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_LayerDown,
105706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_LayerStart,
106706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_LayerFinish,
107706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_InitRestartCounter,
108706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_SendConfigReq,
109706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_SentTerminateReq,
110706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_SendTerminateAck,
111706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_DecodeConfig,
112706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fsm_NullRecvResetReq,
113706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fsm_NullRecvResetAck
114706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh};
115706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
116706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
117706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi YehSetInterfaceID(u_char *ifid, int userandom)
118706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
119706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ifaddrs *ifa, *ifap = NULL;
120706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct sockaddr_dl *sdl;
121706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  const u_long i32_max = 0xffffffff;
122706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_long r1, r2;
123706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
124706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* configure an interface ID based on Section 4.1 of RFC 2472 */
125706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(ifid, 0, IPV6CP_IFIDLEN);
126706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
127706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
128706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * 1) If an IEEE global identifier (EUI-48 or EUI-64) is
129706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * available anywhere on the node, it should be used to construct
130706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * the tentative Interface-Identifier due to its uniqueness
131706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * properties.
132706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
133706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (userandom)
134706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    goto randomid;
135706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (getifaddrs(&ifap) < 0)
136706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    goto randomid;
137706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
138706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
139706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    char *cp;
140706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
141706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (ifa->ifa_addr->sa_family != AF_LINK)
142706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      continue;
143706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
144706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    sdl = (struct sockaddr_dl *)ifa->ifa_addr;
145706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (sdl->sdl_alen < 6)
146706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      continue;
147706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /* we're only interested in IEEE hardware addresses */
148706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    switch(sdl->sdl_type) {
149706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case IFT_ETHER:
150706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case IFT_FDDI:
151706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case IFT_L2VLAN:
152706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* XXX need more cases? */
153706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
154706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    default:
155706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      continue;
156706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
157706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
158706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cp = (char *)(sdl->sdl_data + sdl->sdl_nlen);
159706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[0] = cp[0];
160706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[0] ^= 0x02; /* reverse the u/l bit*/
161706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[1] = cp[1];
162706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[2] = cp[2];
163706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[3] = 0xff;
164706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[4] = 0xfe;
165706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[5] = cp[3];
166706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[6] = cp[4];
167706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ifid[7] = cp[5];
168706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
169706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    freeifaddrs(ifap);
170706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
171706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
172706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
173706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  freeifaddrs(ifap);
174706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
175706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
176706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * 2) If an IEEE global identifier is not available a different source
177706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * of uniqueness should be used.
178706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * XXX: we skip this case.
179706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
180706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
181706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
182706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * 3) If a good source of uniqueness cannot be found, it is
183706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * recommended that a random number be generated.  In this case the
184706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * "u" bit of the interface identifier MUST be set to zero (0).
185706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
186706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh randomid:
187706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  randinit();
188706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  r1 = (((u_long)random()) % i32_max) + 1;
189706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  r2 = (((u_long)random()) % i32_max) + 1;
190706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memcpy(ifid, &r1, sizeof(r1));
191706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memcpy(ifid + 4, &r2, sizeof(r2));
192706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ifid[0] &= 0xfd;
193706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return;
194706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
195706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
196706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
197706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipcp_SetIPv6address(struct ipv6cp *ipv6cp, u_char *myifid, u_char *hisifid)
198706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
199706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = ipv6cp->fsm.bundle;
200706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct in6_addr myaddr, hisaddr;
201706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ncprange myrange, range;
202706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ncpaddr addr;
203706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct sockaddr_storage ssdst, ssgw, ssmask;
204706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct sockaddr *sadst, *sagw, *samask;
205706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
206706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  sadst = (struct sockaddr *)&ssdst;
207706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  sagw = (struct sockaddr *)&ssgw;
208706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  samask = (struct sockaddr *)&ssmask;
209706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
210706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(&myaddr, '\0', sizeof myaddr);
211706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(&hisaddr, '\0', sizeof hisaddr);
212706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
213706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  myaddr.s6_addr[0] = 0xfe;
214706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  myaddr.s6_addr[1] = 0x80;
215706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memcpy(&myaddr.s6_addr[8], myifid, IPV6CP_IFIDLEN);
216706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#if 0
217706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  myaddr.s6_addr[8] |= 0x02;	/* set 'universal' bit */
218706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
219706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
220706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  hisaddr.s6_addr[0] = 0xfe;
221706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  hisaddr.s6_addr[1] = 0x80;
222706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memcpy(&hisaddr.s6_addr[8], hisifid, IPV6CP_IFIDLEN);
223706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#if 0
224706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  hisaddr.s6_addr[8] |= 0x02;	/* set 'universal' bit */
225706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
226706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
227706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncpaddr_setip6(&ipv6cp->myaddr, &myaddr);
228706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncpaddr_setip6(&ipv6cp->hisaddr, &hisaddr);
229706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncprange_set(&myrange, &ipv6cp->myaddr, 64);
230706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
231706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &ipv6cp->hisaddr,
232706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM))
233706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
234706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
235706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!Enabled(bundle, OPT_IFACEALIAS))
236706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    iface_Clear(bundle->iface, &bundle->ncp, AF_INET6,
237706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                IFACE_CLEAR_ALIASES|IFACE_SYSTEM);
238706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
239706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncpaddr_setip6(&addr, &in6addr_linklocal_mcast);
240706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncprange_set(&range, &addr, 32);
241706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  rt_Set(bundle, RTM_ADD, &range, &ipv6cp->myaddr, 1, 0);
242706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
243706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) {
244706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ncprange_getsa(&myrange, &ssgw, &ssmask);
245706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (ncpaddr_isset(&ipv6cp->hisaddr))
246706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ncpaddr_getsa(&ipv6cp->hisaddr, &ssdst);
247706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
248706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      sadst = NULL;
249706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    rt_Update(bundle, sadst, sagw, samask);
250706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
251706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
252706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (Enabled(bundle, OPT_SROUTES))
253706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    route_Change(bundle, bundle->ncp.route, &ipv6cp->myaddr, &ipv6cp->hisaddr);
254706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
255706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
256706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle->radius.valid)
257706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    route_Change(bundle, bundle->radius.ipv6routes, &ipv6cp->myaddr,
258706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 &ipv6cp->hisaddr);
259706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
260706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
261706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 1;	/* Ok */
262706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
263706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
264706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
265706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_Init(struct ipv6cp *ipv6cp, struct bundle *bundle, struct link *l,
266706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 const struct fsm_parent *parent)
267706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
268706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  static const char * const timer_names[] =
269706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    {"IPV6CP restart", "IPV6CP openmode", "IPV6CP stopped"};
270706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int n;
271706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
272706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fsm_Init(&ipv6cp->fsm, "IPV6CP", PROTO_IPV6CP, 1, IPV6CP_MAXCODE, LogIPV6CP,
273706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh           bundle, l, parent, &ipv6cp_Callbacks, timer_names);
274706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
275706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->cfg.fsm.timeout = DEF_FSMRETRY;
276706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->cfg.fsm.maxreq = DEF_FSMTRIES;
277706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->cfg.fsm.maxtrm = DEF_FSMTRIES;
278706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
279706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  SetInterfaceID(ipv6cp->my_ifid, 0);
280706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  do {
281706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    SetInterfaceID(ipv6cp->his_ifid, 1);
282706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } while (memcmp(ipv6cp->his_ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) == 0);
283706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
284706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (probe.ipv6_available) {
285706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    n = 100;
286706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    while (n &&
287706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh           !ipcp_SetIPv6address(ipv6cp, ipv6cp->my_ifid, ipv6cp->his_ifid)) {
288706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      do {
289706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	n--;
290706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    	SetInterfaceID(ipv6cp->my_ifid, 1);
291706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } while (n
292706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	&& memcmp(ipv6cp->his_ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) == 0);
293706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
294706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
295706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
296706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_init(&ipv6cp->throughput, SAMPLE_PERIOD);
297706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(ipv6cp->Queue, '\0', sizeof ipv6cp->Queue);
298706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp_Setup(ipv6cp);
299706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
300706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
301706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
302706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_Destroy(struct ipv6cp *ipv6cp)
303706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
304706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_destroy(&ipv6cp->throughput);
305706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
306706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
307706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
308706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_Setup(struct ipv6cp *ipv6cp)
309706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
310706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncpaddr_init(&ipv6cp->myaddr);
311706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ncpaddr_init(&ipv6cp->hisaddr);
312706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
313706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->his_reject = 0;
314706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->my_reject = 0;
315706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
316706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
317706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
318706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_SetLink(struct ipv6cp *ipv6cp, struct link *l)
319706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
320706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->fsm.link = l;
321706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
322706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
323706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
324706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_Show(struct cmdargs const *arg)
325706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
326706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = &arg->bundle->ncp.ipv6cp;
327706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
328706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, "%s [%s]\n", ipv6cp->fsm.name,
329706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                State2Nam(ipv6cp->fsm.state));
330706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ipv6cp->fsm.state == ST_OPENED) {
331706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, " His side:        %s\n",
332706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  ncpaddr_ntoa(&ipv6cp->hisaddr));
333706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, " My side:         %s\n",
334706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  ncpaddr_ntoa(&ipv6cp->myaddr));
335706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, " Queued packets:  %lu\n",
336706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                  (unsigned long)ipv6cp_QueueLen(ipv6cp));
337706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
338706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
339706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, "\nDefaults:\n");
340706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  prompt_Printf(arg->prompt, "  FSM retry = %us, max %u Config"
341706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                " REQ%s, %u Term REQ%s\n\n", ipv6cp->cfg.fsm.timeout,
342706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                ipv6cp->cfg.fsm.maxreq, ipv6cp->cfg.fsm.maxreq == 1 ? "" : "s",
343706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                ipv6cp->cfg.fsm.maxtrm, ipv6cp->cfg.fsm.maxtrm == 1 ? "" : "s");
344706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
345706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_disp(&ipv6cp->throughput, arg->prompt);
346706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
347706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
348706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
349706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
350706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstruct mbuf *
351706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
352706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
353706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Got PROTO_IPV6CP from link */
354706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  m_settype(bp, MB_IPV6CPIN);
355706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bundle_Phase(bundle) == PHASE_NETWORK)
356706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fsm_Input(&bundle->ncp.ipv6cp.fsm, bp);
357706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  else {
358706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle_Phase(bundle) < PHASE_NETWORK)
359706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogIPV6CP, "%s: Error: Unexpected IPV6CP in phase %s"
360706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 " (ignored)\n", l->name, bundle_PhaseName(bundle));
361706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    m_freem(bp);
362706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
363706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return NULL;
364706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
365706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
366706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
367706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_AddInOctets(struct ipv6cp *ipv6cp, int n)
368706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
369706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_addin(&ipv6cp->throughput, n);
370706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
371706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
372706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
373706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_AddOutOctets(struct ipv6cp *ipv6cp, int n)
374706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
375706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_addout(&ipv6cp->throughput, n);
376706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
377706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
378706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
379706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_IfaceAddrAdded(struct ipv6cp *ipv6cp __unused,
380706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		      const struct iface_addr *addr __unused)
381706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
382706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
383706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
384706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehvoid
385706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_IfaceAddrDeleted(struct ipv6cp *ipv6cp __unused,
386706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh			const struct iface_addr *addr __unused)
387706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
388706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
389706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
390706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
391706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_InterfaceUp(struct ipv6cp *ipv6cp)
392706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
393706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!ipcp_SetIPv6address(ipv6cp, ipv6cp->my_ifid, ipv6cp->his_ifid)) {
394706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "ipv6cp_InterfaceUp: unable to set ipv6 address\n");
395706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
396706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
397706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
398706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!iface_SetFlags(ipv6cp->fsm.bundle->iface->name, IFF_UP)) {
399706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogERROR, "ipv6cp_InterfaceUp: Can't set the IFF_UP"
400706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               " flag on %s\n", ipv6cp->fsm.bundle->iface->name);
401706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
402706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
403706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
404706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 1;
405706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
406706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
407706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehsize_t
408706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_QueueLen(struct ipv6cp *ipv6cp)
409706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
410706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct mqueue *q;
411706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  size_t result;
412706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
413706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  result = 0;
414706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++)
415706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    result += q->len;
416706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
417706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return result;
418706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
419706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
420706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
421706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_PushPacket(struct ipv6cp *ipv6cp, struct link *l)
422706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
423706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct bundle *bundle = ipv6cp->fsm.bundle;
424706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct mqueue *queue;
425706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct mbuf *bp;
426706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int m_len;
427706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_int32_t secs = 0;
428706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  unsigned alivesecs = 0;
429706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
430706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (ipv6cp->fsm.state != ST_OPENED)
431706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
432706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
433706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
434706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * If ccp is not open but is required, do nothing.
435706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
436706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) {
437706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name);
438706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
439706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
440706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
441706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  queue = ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp) - 1;
442706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  do {
443706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (queue->top) {
444706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bp = m_dequeue(queue);
445706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bp = mbuf_Read(bp, &secs, sizeof secs);
446706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bp = m_pullup(bp);
447706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      m_len = m_length(bp);
448706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (!FilterCheck(MBUF_CTOP(bp), AF_INET6, &bundle->filter.alive,
449706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       &alivesecs)) {
450706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (secs == 0)
451706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          secs = alivesecs;
452706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bundle_StartIdleTimer(bundle, secs);
453706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
454706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      link_PushPacket(l, bp, bundle, 0, PROTO_IPV6);
455706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ipv6cp_AddOutOctets(ipv6cp, m_len);
456706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
457706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
458706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } while (queue-- != ipv6cp->Queue);
459706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
460706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
461706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
462706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
463706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
464706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_LayerUp(struct fsm *fp)
465706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
466706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* We're now up */
467706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
468706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char tbuff[40];
469706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
470706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogIPV6CP, "%s: LayerUp.\n", fp->link->name);
471706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!ipv6cp_InterfaceUp(ipv6cp))
472706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
473706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
474706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  snprintf(tbuff, sizeof tbuff, "%s", ncpaddr_ntoa(&ipv6cp->myaddr));
475706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogIPV6CP, "myaddr %s hisaddr = %s\n",
476706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             tbuff, ncpaddr_ntoa(&ipv6cp->hisaddr));
477706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
478706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
479706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  radius_Account_Set_Ipv6(&fp->bundle->radacct6, ipv6cp->his_ifid);
480706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  radius_Account(&fp->bundle->radius, &fp->bundle->radacct6,
481706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		 fp->bundle->links, RAD_START, &ipv6cp->throughput);
482706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
483706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
484706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * XXX: Avoid duplicate evaluation of filterid between IPCP and
485706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * IPV6CP.  When IPCP is enabled and rejected, filterid is not
486706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * evaluated.
487706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
488706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!Enabled(fp->bundle, OPT_IPCP)) {
489706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid)
490706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE,
491706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		    NULL, NULL);
492706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
493706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
494706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
495706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
496706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * XXX this stuff should really live in the FSM.  Our config should
497706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * associate executable sections in files with events.
498706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
499706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
500706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
501706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * XXX: Avoid duplicate evaluation of label between IPCP and
502706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * IPV6CP.  When IPCP is enabled and rejected, label is not
503706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * evaluated.
504706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
505706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (bundle_GetLabel(fp->bundle) && !Enabled(fp->bundle, OPT_IPCP)) {
506706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
507706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh			LINKUPFILE, NULL, NULL) < 0)
508706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	system_Select(fp->bundle, "MYADDR6", LINKUPFILE, NULL, NULL);
509706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else
510706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      system_Select(fp->bundle, "MYADDR6", LINKUPFILE, NULL, NULL);
511706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
512706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
513706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3;
514706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_DisplayPrompts();
515706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
516706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 1;
517706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
518706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
519706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
520706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_LayerDown(struct fsm *fp)
521706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
522706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* About to come down */
523706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
524706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  static int recursing;
525706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char addr[40];
526706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
527706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!recursing++) {
528706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    snprintf(addr, sizeof addr, "%s", ncpaddr_ntoa(&ipv6cp->myaddr));
529706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogIPV6CP, "%s: LayerDown: %s\n", fp->link->name, addr);
530706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
531706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
532706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    radius_Flush(&fp->bundle->radius);
533706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    radius_Account(&fp->bundle->radius, &fp->bundle->radacct6,
534706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		   fp->bundle->links, RAD_STOP, &ipv6cp->throughput);
535706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
536706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
537706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * XXX: Avoid duplicate evaluation of filterid between IPCP and
538706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * IPV6CP.  When IPCP is enabled and rejected, filterid is not
539706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * evaluated.
540706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
541706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (!Enabled(fp->bundle, OPT_IPCP)) {
542706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid)
543706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE,
544706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		      NULL, NULL);
545706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
546706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
547706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
548706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    /*
549706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * XXX this stuff should really live in the FSM.  Our config should
550706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     * associate executable sections in files with events.
551706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh     */
552706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) {
553706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /*
554706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       * XXX: Avoid duplicate evaluation of label between IPCP and
555706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       * IPV6CP.  When IPCP is enabled and rejected, label is not
556706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       * evaluated.
557706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       */
558706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (bundle_GetLabel(fp->bundle) && !Enabled(fp->bundle, OPT_IPCP)) {
559706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
560706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh			  LINKDOWNFILE, NULL, NULL) < 0)
561706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	  system_Select(fp->bundle, "MYADDR6", LINKDOWNFILE, NULL, NULL);
562706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else
563706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	system_Select(fp->bundle, "MYADDR6", LINKDOWNFILE, NULL, NULL);
564706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
565706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
566706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    ipv6cp_Setup(ipv6cp);
567706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
568706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  recursing--;
569706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
570706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
571706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
572706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_LayerStart(struct fsm *fp)
573706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
574706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* We're about to start up ! */
575706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
576706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
577706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogIPV6CP, "%s: LayerStart.\n", fp->link->name);
578706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_start(&ipv6cp->throughput, "IPV6CP throughput",
579706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                   Enabled(fp->bundle, OPT_THROUGHPUT));
580706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3;
581706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ipv6cp->peer_tokenreq = 0;
582706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
583706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
584706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
585706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_LayerFinish(struct fsm *fp)
586706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
587706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* We're now down */
588706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
589706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
590706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogIPV6CP, "%s: LayerFinish.\n", fp->link->name);
591706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_stop(&ipv6cp->throughput);
592706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  throughput_log(&ipv6cp->throughput, LogIPV6CP, NULL);
593706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
594706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
595706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
596706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_InitRestartCounter(struct fsm *fp, int what)
597706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
598706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Set fsm timer load */
599706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
600706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
601706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fp->FsmTimer.load = ipv6cp->cfg.fsm.timeout * SECTICKS;
602706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  switch (what) {
603706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case FSM_REQ_TIMER:
604706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      fp->restart = ipv6cp->cfg.fsm.maxreq;
605706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
606706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case FSM_TRM_TIMER:
607706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      fp->restart = ipv6cp->cfg.fsm.maxtrm;
608706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
609706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    default:
610706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      fp->restart = 1;
611706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
612706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
613706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
614706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
615706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
616706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_SendConfigReq(struct fsm *fp)
617706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
618706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Send config REQ please */
619706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct physical *p = link2physical(fp->link);
620706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
621706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_char buff[IPV6CP_IFIDLEN+2];
622706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct fsm_opt *o;
623706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
624706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  o = (struct fsm_opt *)buff;
625706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
626706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) {
627706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    memcpy(o->data, ipv6cp->my_ifid, IPV6CP_IFIDLEN);
628706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    INC_FSM_OPT(TY_TOKEN, IPV6CP_IFIDLEN + 2, o);
629706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
630706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
631706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
632706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             MB_IPV6CPOUT);
633706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
634706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
635706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
636706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_SentTerminateReq(struct fsm *fp __unused)
637706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
638706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Term REQ just sent by FSM */
639706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
640706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
641706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
642706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_SendTerminateAck(struct fsm *fp, u_char id)
643706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
644706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Send Term ACK please */
645706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPV6CPOUT);
646706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
647706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
648706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic const char *
649706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehprotoname(unsigned proto)
650706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
651706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  static const char *cftypes[] = { "IFACEID", "COMPPROTO" };
652706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
653706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (proto > 0 && proto <= sizeof cftypes / sizeof *cftypes)
654706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return cftypes[proto - 1];
655706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
656706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return NumStr(proto, NULL, 0);
657706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
658706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
659706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
660706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_ValidateInterfaceID(struct ipv6cp *ipv6cp, u_char *ifid,
661706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh			   struct fsm_decode *dec)
662706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
663706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct fsm_opt opt;
664706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_char zero[IPV6CP_IFIDLEN];
665706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
666706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(zero, 0, IPV6CP_IFIDLEN);
667706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
668706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (memcmp(ifid, zero, IPV6CP_IFIDLEN) != 0
669706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      && memcmp(ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) != 0)
670706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    memcpy(ipv6cp->his_ifid, ifid, IPV6CP_IFIDLEN);
671706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
672706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  opt.hdr.id = TY_TOKEN;
673706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  opt.hdr.len = IPV6CP_IFIDLEN + 2;
674706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memcpy(opt.data, &ipv6cp->his_ifid, IPV6CP_IFIDLEN);
675706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0)
676706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fsm_ack(dec, &opt);
677706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  else
678706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fsm_nak(dec, &opt);
679706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
680706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
681706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
682706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
683706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    struct fsm_decode *dec)
684706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
685706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Deal with incoming PROTO_IPV6CP */
686706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
687706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int n;
688706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char tbuff[100];
689706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_char ifid[IPV6CP_IFIDLEN], zero[IPV6CP_IFIDLEN];
690706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct fsm_opt *opt;
691706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
692706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  memset(zero, 0, IPV6CP_IFIDLEN);
693706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
694706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  while (end - cp >= (int)sizeof(opt->hdr)) {
695706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if ((opt = fsm_readopt(&cp)) == NULL)
696706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
697706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
698706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id),
699706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             opt->hdr.len);
700706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
701706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    switch (opt->hdr.id) {
702706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case TY_TOKEN:
703706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      memcpy(ifid, opt->data, IPV6CP_IFIDLEN);
704706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogIPV6CP, "%s 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", tbuff,
705706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		 ifid[0], ifid[1], ifid[2], ifid[3], ifid[4], ifid[5], ifid[6], ifid[7]);
706706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
707706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      switch (mode_type) {
708706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      case MODE_REQ:
709706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        ipv6cp->peer_tokenreq = 1;
710706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        ipv6cp_ValidateInterfaceID(ipv6cp, ifid, dec);
711706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
712706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
713706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      case MODE_NAK:
714706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (memcmp(ifid, zero, IPV6CP_IFIDLEN) == 0) {
715706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
716706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		     "0x0000000000000000: Unacceptable IntefaceID!\n");
717706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          fsm_Close(&ipv6cp->fsm);
718706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        } else if (memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0) {
719706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
720706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		     "0x%02x%02x%02x%02x%02x%02x%02x%02x: "
721706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		     "Unacceptable IntefaceID!\n",
722706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		     ifid[0], ifid[1], ifid[2], ifid[3],
723706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		     ifid[4], ifid[5], ifid[6], ifid[7]);
724706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        } else if (memcmp(ifid, ipv6cp->my_ifid, IPV6CP_IFIDLEN) != 0) {
725706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          n = 100;
726706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	  while (n && !ipcp_SetIPv6address(ipv6cp, ifid, ipv6cp->his_ifid)) {
727706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	    do {
728706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	      n--;
729706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	      SetInterfaceID(ifid, 1);
730706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	    } while (n && memcmp(ifid, ipv6cp->his_ifid, IPV6CP_IFIDLEN) == 0);
731706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	  }
732706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
733706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          if (n == 0) {
734706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
735706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                       "0x0000000000000000: Unacceptable IntefaceID!\n");
736706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            fsm_Close(&ipv6cp->fsm);
737706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          } else {
738706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	    log_Printf(LogIPV6CP, "%s changing IntefaceID: "
739706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       "0x%02x%02x%02x%02x%02x%02x%02x%02x "
740706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       "--> 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", tbuff,
741706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       ipv6cp->my_ifid[0], ipv6cp->my_ifid[1],
742706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       ipv6cp->my_ifid[2], ipv6cp->my_ifid[3],
743706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       ipv6cp->my_ifid[4], ipv6cp->my_ifid[5],
744706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       ipv6cp->my_ifid[6], ipv6cp->my_ifid[7],
745706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       ifid[0], ifid[1], ifid[2], ifid[3],
746706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		       ifid[4], ifid[5], ifid[6], ifid[7]);
747706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            memcpy(ipv6cp->my_ifid, ifid, IPV6CP_IFIDLEN);
748706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh            bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL);
749706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          }
750706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        }
751706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
752706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
753706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      case MODE_REJ:
754706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        ipv6cp->his_reject |= (1 << opt->hdr.id);
755706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
756706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
757706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
758706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
759706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    default:
760706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (mode_type != MODE_NOP) {
761706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        ipv6cp->my_reject |= (1 << opt->hdr.id);
762706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        fsm_rej(dec, opt);
763706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
764706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
765706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
766706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
767706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
768706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (mode_type != MODE_NOP) {
769706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (mode_type == MODE_REQ && !ipv6cp->peer_tokenreq) {
770706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (dec->rejend == dec->rej && dec->nakend == dec->nak) {
771706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        /*
772706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * Pretend the peer has requested a TOKEN.
773706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * We do this to ensure that we only send one NAK if the only
774706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * reason for the NAK is because the peer isn't sending a
775706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * TY_TOKEN REQ.  This stops us from repeatedly trying to tell
776706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         * the peer that we have to have an IP address on their end.
777706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh         */
778706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        ipv6cp->peer_tokenreq = 1;
779706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
780706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      memset(ifid, 0, IPV6CP_IFIDLEN);
781706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ipv6cp_ValidateInterfaceID(ipv6cp, ifid, dec);
782706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
783706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    fsm_opt_normalise(dec);
784706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
785706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
786706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
787