1*5d5fbe79SDavid van Moolenbroek /*
2*5d5fbe79SDavid van Moolenbroek * ipv6cp.c - PPP IPV6 Control Protocol.
3*5d5fbe79SDavid van Moolenbroek *
4*5d5fbe79SDavid van Moolenbroek * Copyright (c) 1999 Tommi Komulainen. All rights reserved.
5*5d5fbe79SDavid van Moolenbroek *
6*5d5fbe79SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
7*5d5fbe79SDavid van Moolenbroek * modification, are permitted provided that the following conditions
8*5d5fbe79SDavid van Moolenbroek * are met:
9*5d5fbe79SDavid van Moolenbroek *
10*5d5fbe79SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*5d5fbe79SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*5d5fbe79SDavid van Moolenbroek *
13*5d5fbe79SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
14*5d5fbe79SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in
15*5d5fbe79SDavid van Moolenbroek * the documentation and/or other materials provided with the
16*5d5fbe79SDavid van Moolenbroek * distribution.
17*5d5fbe79SDavid van Moolenbroek *
18*5d5fbe79SDavid van Moolenbroek * 3. The name(s) of the authors of this software must not be used to
19*5d5fbe79SDavid van Moolenbroek * endorse or promote products derived from this software without
20*5d5fbe79SDavid van Moolenbroek * prior written permission.
21*5d5fbe79SDavid van Moolenbroek *
22*5d5fbe79SDavid van Moolenbroek * 4. Redistributions of any form whatsoever must retain the following
23*5d5fbe79SDavid van Moolenbroek * acknowledgment:
24*5d5fbe79SDavid van Moolenbroek * "This product includes software developed by Tommi Komulainen
25*5d5fbe79SDavid van Moolenbroek * <Tommi.Komulainen@iki.fi>".
26*5d5fbe79SDavid van Moolenbroek *
27*5d5fbe79SDavid van Moolenbroek * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
28*5d5fbe79SDavid van Moolenbroek * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
29*5d5fbe79SDavid van Moolenbroek * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
30*5d5fbe79SDavid van Moolenbroek * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
31*5d5fbe79SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
32*5d5fbe79SDavid van Moolenbroek * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
33*5d5fbe79SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34*5d5fbe79SDavid van Moolenbroek *
35*5d5fbe79SDavid van Moolenbroek */
36*5d5fbe79SDavid van Moolenbroek
37*5d5fbe79SDavid van Moolenbroek /* Original version, based on RFC2023 :
38*5d5fbe79SDavid van Moolenbroek
39*5d5fbe79SDavid van Moolenbroek Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt,
40*5d5fbe79SDavid van Moolenbroek Alain.Durand@imag.fr, IMAG,
41*5d5fbe79SDavid van Moolenbroek Jean-Luc.Richier@imag.fr, IMAG-LSR.
42*5d5fbe79SDavid van Moolenbroek
43*5d5fbe79SDavid van Moolenbroek Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE,
44*5d5fbe79SDavid van Moolenbroek Alain.Durand@imag.fr, IMAG,
45*5d5fbe79SDavid van Moolenbroek Jean-Luc.Richier@imag.fr, IMAG-LSR.
46*5d5fbe79SDavid van Moolenbroek
47*5d5fbe79SDavid van Moolenbroek Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt
48*5d5fbe79SDavid van Moolenbroek Économique ayant pour membres BULL S.A. et l'INRIA).
49*5d5fbe79SDavid van Moolenbroek
50*5d5fbe79SDavid van Moolenbroek Ce logiciel informatique est disponible aux conditions
51*5d5fbe79SDavid van Moolenbroek usuelles dans la recherche, c'est-à-dire qu'il peut
52*5d5fbe79SDavid van Moolenbroek être utilisé, copié, modifié, distribué à l'unique
53*5d5fbe79SDavid van Moolenbroek condition que ce texte soit conservé afin que
54*5d5fbe79SDavid van Moolenbroek l'origine de ce logiciel soit reconnue.
55*5d5fbe79SDavid van Moolenbroek
56*5d5fbe79SDavid van Moolenbroek Le nom de l'Institut National de Recherche en Informatique
57*5d5fbe79SDavid van Moolenbroek et en Automatique (INRIA), de l'IMAG, ou d'une personne morale
58*5d5fbe79SDavid van Moolenbroek ou physique ayant participé à l'élaboration de ce logiciel ne peut
59*5d5fbe79SDavid van Moolenbroek être utilisé sans son accord préalable explicite.
60*5d5fbe79SDavid van Moolenbroek
61*5d5fbe79SDavid van Moolenbroek Ce logiciel est fourni tel quel sans aucune garantie,
62*5d5fbe79SDavid van Moolenbroek support ou responsabilité d'aucune sorte.
63*5d5fbe79SDavid van Moolenbroek Ce logiciel est dérivé de sources d'origine
64*5d5fbe79SDavid van Moolenbroek "University of California at Berkeley" et
65*5d5fbe79SDavid van Moolenbroek "Digital Equipment Corporation" couvertes par des copyrights.
66*5d5fbe79SDavid van Moolenbroek
67*5d5fbe79SDavid van Moolenbroek L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG)
68*5d5fbe79SDavid van Moolenbroek est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National
69*5d5fbe79SDavid van Moolenbroek Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant
70*5d5fbe79SDavid van Moolenbroek sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR).
71*5d5fbe79SDavid van Moolenbroek
72*5d5fbe79SDavid van Moolenbroek This work has been done in the context of GIE DYADE (joint R & D venture
73*5d5fbe79SDavid van Moolenbroek between BULL S.A. and INRIA).
74*5d5fbe79SDavid van Moolenbroek
75*5d5fbe79SDavid van Moolenbroek This software is available with usual "research" terms
76*5d5fbe79SDavid van Moolenbroek with the aim of retain credits of the software.
77*5d5fbe79SDavid van Moolenbroek Permission to use, copy, modify and distribute this software for any
78*5d5fbe79SDavid van Moolenbroek purpose and without fee is hereby granted, provided that the above
79*5d5fbe79SDavid van Moolenbroek copyright notice and this permission notice appear in all copies,
80*5d5fbe79SDavid van Moolenbroek and the name of INRIA, IMAG, or any contributor not be used in advertising
81*5d5fbe79SDavid van Moolenbroek or publicity pertaining to this material without the prior explicit
82*5d5fbe79SDavid van Moolenbroek permission. The software is provided "as is" without any
83*5d5fbe79SDavid van Moolenbroek warranties, support or liabilities of any kind.
84*5d5fbe79SDavid van Moolenbroek This software is derived from source code from
85*5d5fbe79SDavid van Moolenbroek "University of California at Berkeley" and
86*5d5fbe79SDavid van Moolenbroek "Digital Equipment Corporation" protected by copyrights.
87*5d5fbe79SDavid van Moolenbroek
88*5d5fbe79SDavid van Moolenbroek Grenoble's Institute of Computer Science and Applied Mathematics (IMAG)
89*5d5fbe79SDavid van Moolenbroek is a federation of seven research units funded by the CNRS, National
90*5d5fbe79SDavid van Moolenbroek Polytechnic Institute of Grenoble and University Joseph Fourier.
91*5d5fbe79SDavid van Moolenbroek The research unit in Software, Systems, Networks (LSR) is member of IMAG.
92*5d5fbe79SDavid van Moolenbroek */
93*5d5fbe79SDavid van Moolenbroek
94*5d5fbe79SDavid van Moolenbroek /*
95*5d5fbe79SDavid van Moolenbroek * Derived from :
96*5d5fbe79SDavid van Moolenbroek *
97*5d5fbe79SDavid van Moolenbroek *
98*5d5fbe79SDavid van Moolenbroek * ipcp.c - PPP IP Control Protocol.
99*5d5fbe79SDavid van Moolenbroek *
100*5d5fbe79SDavid van Moolenbroek * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
101*5d5fbe79SDavid van Moolenbroek *
102*5d5fbe79SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
103*5d5fbe79SDavid van Moolenbroek * modification, are permitted provided that the following conditions
104*5d5fbe79SDavid van Moolenbroek * are met:
105*5d5fbe79SDavid van Moolenbroek *
106*5d5fbe79SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
107*5d5fbe79SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
108*5d5fbe79SDavid van Moolenbroek *
109*5d5fbe79SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
110*5d5fbe79SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in
111*5d5fbe79SDavid van Moolenbroek * the documentation and/or other materials provided with the
112*5d5fbe79SDavid van Moolenbroek * distribution.
113*5d5fbe79SDavid van Moolenbroek *
114*5d5fbe79SDavid van Moolenbroek * 3. The name "Carnegie Mellon University" must not be used to
115*5d5fbe79SDavid van Moolenbroek * endorse or promote products derived from this software without
116*5d5fbe79SDavid van Moolenbroek * prior written permission. For permission or any legal
117*5d5fbe79SDavid van Moolenbroek * details, please contact
118*5d5fbe79SDavid van Moolenbroek * Office of Technology Transfer
119*5d5fbe79SDavid van Moolenbroek * Carnegie Mellon University
120*5d5fbe79SDavid van Moolenbroek * 5000 Forbes Avenue
121*5d5fbe79SDavid van Moolenbroek * Pittsburgh, PA 15213-3890
122*5d5fbe79SDavid van Moolenbroek * (412) 268-4387, fax: (412) 268-7395
123*5d5fbe79SDavid van Moolenbroek * tech-transfer@andrew.cmu.edu
124*5d5fbe79SDavid van Moolenbroek *
125*5d5fbe79SDavid van Moolenbroek * 4. Redistributions of any form whatsoever must retain the following
126*5d5fbe79SDavid van Moolenbroek * acknowledgment:
127*5d5fbe79SDavid van Moolenbroek * "This product includes software developed by Computing Services
128*5d5fbe79SDavid van Moolenbroek * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
129*5d5fbe79SDavid van Moolenbroek *
130*5d5fbe79SDavid van Moolenbroek * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
131*5d5fbe79SDavid van Moolenbroek * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
132*5d5fbe79SDavid van Moolenbroek * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
133*5d5fbe79SDavid van Moolenbroek * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134*5d5fbe79SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
135*5d5fbe79SDavid van Moolenbroek * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
136*5d5fbe79SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
137*5d5fbe79SDavid van Moolenbroek *
138*5d5fbe79SDavid van Moolenbroek * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $
139*5d5fbe79SDavid van Moolenbroek */
140*5d5fbe79SDavid van Moolenbroek
141*5d5fbe79SDavid van Moolenbroek /*
142*5d5fbe79SDavid van Moolenbroek * @todo:
143*5d5fbe79SDavid van Moolenbroek *
144*5d5fbe79SDavid van Moolenbroek * Proxy Neighbour Discovery.
145*5d5fbe79SDavid van Moolenbroek *
146*5d5fbe79SDavid van Moolenbroek * Better defines for selecting the ordering of
147*5d5fbe79SDavid van Moolenbroek * interface up / set address.
148*5d5fbe79SDavid van Moolenbroek */
149*5d5fbe79SDavid van Moolenbroek
150*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/ppp_opts.h"
151*5d5fbe79SDavid van Moolenbroek #if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */
152*5d5fbe79SDavid van Moolenbroek
153*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
154*5d5fbe79SDavid van Moolenbroek #include <stdio.h>
155*5d5fbe79SDavid van Moolenbroek #include <string.h>
156*5d5fbe79SDavid van Moolenbroek #include <unistd.h>
157*5d5fbe79SDavid van Moolenbroek #include <netdb.h>
158*5d5fbe79SDavid van Moolenbroek #include <sys/param.h>
159*5d5fbe79SDavid van Moolenbroek #include <sys/types.h>
160*5d5fbe79SDavid van Moolenbroek #include <sys/socket.h>
161*5d5fbe79SDavid van Moolenbroek #include <netinet/in.h>
162*5d5fbe79SDavid van Moolenbroek #include <arpa/inet.h>
163*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
164*5d5fbe79SDavid van Moolenbroek
165*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/ppp_impl.h"
166*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/fsm.h"
167*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/ipcp.h"
168*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/ipv6cp.h"
169*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/magic.h"
170*5d5fbe79SDavid van Moolenbroek
171*5d5fbe79SDavid van Moolenbroek /* global vars */
172*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
173*5d5fbe79SDavid van Moolenbroek int no_ifaceid_neg = 0;
174*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
175*5d5fbe79SDavid van Moolenbroek
176*5d5fbe79SDavid van Moolenbroek /*
177*5d5fbe79SDavid van Moolenbroek * Callbacks for fsm code. (CI = Configuration Information)
178*5d5fbe79SDavid van Moolenbroek */
179*5d5fbe79SDavid van Moolenbroek static void ipv6cp_resetci(fsm *f); /* Reset our CI */
180*5d5fbe79SDavid van Moolenbroek static int ipv6cp_cilen(fsm *f); /* Return length of our CI */
181*5d5fbe79SDavid van Moolenbroek static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */
182*5d5fbe79SDavid van Moolenbroek static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */
183*5d5fbe79SDavid van Moolenbroek static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */
184*5d5fbe79SDavid van Moolenbroek static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */
185*5d5fbe79SDavid van Moolenbroek static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */
186*5d5fbe79SDavid van Moolenbroek static void ipv6cp_up(fsm *f); /* We're UP */
187*5d5fbe79SDavid van Moolenbroek static void ipv6cp_down(fsm *f); /* We're DOWN */
188*5d5fbe79SDavid van Moolenbroek static void ipv6cp_finished(fsm *f); /* Don't need lower layer */
189*5d5fbe79SDavid van Moolenbroek
190*5d5fbe79SDavid van Moolenbroek static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */
191*5d5fbe79SDavid van Moolenbroek ipv6cp_resetci, /* Reset our Configuration Information */
192*5d5fbe79SDavid van Moolenbroek ipv6cp_cilen, /* Length of our Configuration Information */
193*5d5fbe79SDavid van Moolenbroek ipv6cp_addci, /* Add our Configuration Information */
194*5d5fbe79SDavid van Moolenbroek ipv6cp_ackci, /* ACK our Configuration Information */
195*5d5fbe79SDavid van Moolenbroek ipv6cp_nakci, /* NAK our Configuration Information */
196*5d5fbe79SDavid van Moolenbroek ipv6cp_rejci, /* Reject our Configuration Information */
197*5d5fbe79SDavid van Moolenbroek ipv6cp_reqci, /* Request peer's Configuration Information */
198*5d5fbe79SDavid van Moolenbroek ipv6cp_up, /* Called when fsm reaches OPENED state */
199*5d5fbe79SDavid van Moolenbroek ipv6cp_down, /* Called when fsm leaves OPENED state */
200*5d5fbe79SDavid van Moolenbroek NULL, /* Called when we want the lower layer up */
201*5d5fbe79SDavid van Moolenbroek ipv6cp_finished, /* Called when we want the lower layer down */
202*5d5fbe79SDavid van Moolenbroek NULL, /* Called when Protocol-Reject received */
203*5d5fbe79SDavid van Moolenbroek NULL, /* Retransmission is necessary */
204*5d5fbe79SDavid van Moolenbroek NULL, /* Called to handle protocol-specific codes */
205*5d5fbe79SDavid van Moolenbroek "IPV6CP" /* String name of protocol */
206*5d5fbe79SDavid van Moolenbroek };
207*5d5fbe79SDavid van Moolenbroek
208*5d5fbe79SDavid van Moolenbroek #if PPP_OPTIONS
209*5d5fbe79SDavid van Moolenbroek /*
210*5d5fbe79SDavid van Moolenbroek * Command-line options.
211*5d5fbe79SDavid van Moolenbroek */
212*5d5fbe79SDavid van Moolenbroek static int setifaceid(char **arg));
213*5d5fbe79SDavid van Moolenbroek static void printifaceid(option_t *,
214*5d5fbe79SDavid van Moolenbroek void (*)(void *, char *, ...), void *));
215*5d5fbe79SDavid van Moolenbroek
216*5d5fbe79SDavid van Moolenbroek static option_t ipv6cp_option_list[] = {
217*5d5fbe79SDavid van Moolenbroek { "ipv6", o_special, (void *)setifaceid,
218*5d5fbe79SDavid van Moolenbroek "Set interface identifiers for IPV6",
219*5d5fbe79SDavid van Moolenbroek OPT_A2PRINTER, (void *)printifaceid },
220*5d5fbe79SDavid van Moolenbroek
221*5d5fbe79SDavid van Moolenbroek { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag,
222*5d5fbe79SDavid van Moolenbroek "Enable IPv6 and IPv6CP", OPT_PRIO | 1 },
223*5d5fbe79SDavid van Moolenbroek { "noipv6", o_bool, &ipv6cp_protent.enabled_flag,
224*5d5fbe79SDavid van Moolenbroek "Disable IPv6 and IPv6CP", OPT_PRIOSUB },
225*5d5fbe79SDavid van Moolenbroek { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag,
226*5d5fbe79SDavid van Moolenbroek "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS },
227*5d5fbe79SDavid van Moolenbroek
228*5d5fbe79SDavid van Moolenbroek { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local,
229*5d5fbe79SDavid van Moolenbroek "Accept peer's interface identifier for us", 1 },
230*5d5fbe79SDavid van Moolenbroek
231*5d5fbe79SDavid van Moolenbroek { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip,
232*5d5fbe79SDavid van Moolenbroek "Use (default) IPv4 address as interface identifier", 1 },
233*5d5fbe79SDavid van Moolenbroek
234*5d5fbe79SDavid van Moolenbroek { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent,
235*5d5fbe79SDavid van Moolenbroek "Use uniquely-available persistent value for link local address", 1 },
236*5d5fbe79SDavid van Moolenbroek
237*5d5fbe79SDavid van Moolenbroek { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime,
238*5d5fbe79SDavid van Moolenbroek "Set timeout for IPv6CP", OPT_PRIO },
239*5d5fbe79SDavid van Moolenbroek { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits,
240*5d5fbe79SDavid van Moolenbroek "Set max #xmits for term-reqs", OPT_PRIO },
241*5d5fbe79SDavid van Moolenbroek { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits,
242*5d5fbe79SDavid van Moolenbroek "Set max #xmits for conf-reqs", OPT_PRIO },
243*5d5fbe79SDavid van Moolenbroek { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops,
244*5d5fbe79SDavid van Moolenbroek "Set max #conf-naks for IPv6CP", OPT_PRIO },
245*5d5fbe79SDavid van Moolenbroek
246*5d5fbe79SDavid van Moolenbroek { NULL }
247*5d5fbe79SDavid van Moolenbroek };
248*5d5fbe79SDavid van Moolenbroek #endif /* PPP_OPTIONS */
249*5d5fbe79SDavid van Moolenbroek
250*5d5fbe79SDavid van Moolenbroek /*
251*5d5fbe79SDavid van Moolenbroek * Protocol entry points from main code.
252*5d5fbe79SDavid van Moolenbroek */
253*5d5fbe79SDavid van Moolenbroek static void ipv6cp_init(ppp_pcb *pcb);
254*5d5fbe79SDavid van Moolenbroek static void ipv6cp_open(ppp_pcb *pcb);
255*5d5fbe79SDavid van Moolenbroek static void ipv6cp_close(ppp_pcb *pcb, const char *reason);
256*5d5fbe79SDavid van Moolenbroek static void ipv6cp_lowerup(ppp_pcb *pcb);
257*5d5fbe79SDavid van Moolenbroek static void ipv6cp_lowerdown(ppp_pcb *pcb);
258*5d5fbe79SDavid van Moolenbroek static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len);
259*5d5fbe79SDavid van Moolenbroek static void ipv6cp_protrej(ppp_pcb *pcb);
260*5d5fbe79SDavid van Moolenbroek #if PPP_OPTIONS
261*5d5fbe79SDavid van Moolenbroek static void ipv6_check_options(void);
262*5d5fbe79SDavid van Moolenbroek #endif /* PPP_OPTIONS */
263*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
264*5d5fbe79SDavid van Moolenbroek static int ipv6_demand_conf(int u);
265*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
266*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
267*5d5fbe79SDavid van Moolenbroek static int ipv6cp_printpkt(const u_char *p, int plen,
268*5d5fbe79SDavid van Moolenbroek void (*printer)(void *, const char *, ...), void *arg);
269*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
270*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
271*5d5fbe79SDavid van Moolenbroek static int ipv6_active_pkt(u_char *pkt, int len);
272*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
273*5d5fbe79SDavid van Moolenbroek
274*5d5fbe79SDavid van Moolenbroek const struct protent ipv6cp_protent = {
275*5d5fbe79SDavid van Moolenbroek PPP_IPV6CP,
276*5d5fbe79SDavid van Moolenbroek ipv6cp_init,
277*5d5fbe79SDavid van Moolenbroek ipv6cp_input,
278*5d5fbe79SDavid van Moolenbroek ipv6cp_protrej,
279*5d5fbe79SDavid van Moolenbroek ipv6cp_lowerup,
280*5d5fbe79SDavid van Moolenbroek ipv6cp_lowerdown,
281*5d5fbe79SDavid van Moolenbroek ipv6cp_open,
282*5d5fbe79SDavid van Moolenbroek ipv6cp_close,
283*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
284*5d5fbe79SDavid van Moolenbroek ipv6cp_printpkt,
285*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
286*5d5fbe79SDavid van Moolenbroek #if PPP_DATAINPUT
287*5d5fbe79SDavid van Moolenbroek NULL,
288*5d5fbe79SDavid van Moolenbroek #endif /* PPP_DATAINPUT */
289*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
290*5d5fbe79SDavid van Moolenbroek "IPV6CP",
291*5d5fbe79SDavid van Moolenbroek "IPV6",
292*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
293*5d5fbe79SDavid van Moolenbroek #if PPP_OPTIONS
294*5d5fbe79SDavid van Moolenbroek ipv6cp_option_list,
295*5d5fbe79SDavid van Moolenbroek ipv6_check_options,
296*5d5fbe79SDavid van Moolenbroek #endif /* PPP_OPTIONS */
297*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
298*5d5fbe79SDavid van Moolenbroek ipv6_demand_conf,
299*5d5fbe79SDavid van Moolenbroek ipv6_active_pkt
300*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
301*5d5fbe79SDavid van Moolenbroek };
302*5d5fbe79SDavid van Moolenbroek
303*5d5fbe79SDavid van Moolenbroek static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid);
304*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
305*5d5fbe79SDavid van Moolenbroek static void ipv6cp_script(char *));
306*5d5fbe79SDavid van Moolenbroek static void ipv6cp_script_done(void *));
307*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
308*5d5fbe79SDavid van Moolenbroek
309*5d5fbe79SDavid van Moolenbroek /*
310*5d5fbe79SDavid van Moolenbroek * Lengths of configuration options.
311*5d5fbe79SDavid van Moolenbroek */
312*5d5fbe79SDavid van Moolenbroek #define CILEN_VOID 2
313*5d5fbe79SDavid van Moolenbroek #define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */
314*5d5fbe79SDavid van Moolenbroek #define CILEN_IFACEID 10 /* RFC2472, interface identifier */
315*5d5fbe79SDavid van Moolenbroek
316*5d5fbe79SDavid van Moolenbroek #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
317*5d5fbe79SDavid van Moolenbroek (x) == CONFNAK ? "NAK" : "REJ")
318*5d5fbe79SDavid van Moolenbroek
319*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
320*5d5fbe79SDavid van Moolenbroek /*
321*5d5fbe79SDavid van Moolenbroek * This state variable is used to ensure that we don't
322*5d5fbe79SDavid van Moolenbroek * run an ipcp-up/down script while one is already running.
323*5d5fbe79SDavid van Moolenbroek */
324*5d5fbe79SDavid van Moolenbroek static enum script_state {
325*5d5fbe79SDavid van Moolenbroek s_down,
326*5d5fbe79SDavid van Moolenbroek s_up,
327*5d5fbe79SDavid van Moolenbroek } ipv6cp_script_state;
328*5d5fbe79SDavid van Moolenbroek static pid_t ipv6cp_script_pid;
329*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
330*5d5fbe79SDavid van Moolenbroek
331*5d5fbe79SDavid van Moolenbroek static char *llv6_ntoa(eui64_t ifaceid);
332*5d5fbe79SDavid van Moolenbroek
333*5d5fbe79SDavid van Moolenbroek #if PPP_OPTIONS
334*5d5fbe79SDavid van Moolenbroek /*
335*5d5fbe79SDavid van Moolenbroek * setifaceid - set the interface identifiers manually
336*5d5fbe79SDavid van Moolenbroek */
337*5d5fbe79SDavid van Moolenbroek static int
setifaceid(argv)338*5d5fbe79SDavid van Moolenbroek setifaceid(argv)
339*5d5fbe79SDavid van Moolenbroek char **argv;
340*5d5fbe79SDavid van Moolenbroek {
341*5d5fbe79SDavid van Moolenbroek char *comma, *arg, c;
342*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &ipv6cp_wantoptions[0];
343*5d5fbe79SDavid van Moolenbroek struct in6_addr addr;
344*5d5fbe79SDavid van Moolenbroek static int prio_local, prio_remote;
345*5d5fbe79SDavid van Moolenbroek
346*5d5fbe79SDavid van Moolenbroek #define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \
347*5d5fbe79SDavid van Moolenbroek (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) )
348*5d5fbe79SDavid van Moolenbroek
349*5d5fbe79SDavid van Moolenbroek arg = *argv;
350*5d5fbe79SDavid van Moolenbroek if ((comma = strchr(arg, ',')) == NULL)
351*5d5fbe79SDavid van Moolenbroek comma = arg + strlen(arg);
352*5d5fbe79SDavid van Moolenbroek
353*5d5fbe79SDavid van Moolenbroek /*
354*5d5fbe79SDavid van Moolenbroek * If comma first character, then no local identifier
355*5d5fbe79SDavid van Moolenbroek */
356*5d5fbe79SDavid van Moolenbroek if (comma != arg) {
357*5d5fbe79SDavid van Moolenbroek c = *comma;
358*5d5fbe79SDavid van Moolenbroek *comma = '\0';
359*5d5fbe79SDavid van Moolenbroek
360*5d5fbe79SDavid van Moolenbroek if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) {
361*5d5fbe79SDavid van Moolenbroek option_error("Illegal interface identifier (local): %s", arg);
362*5d5fbe79SDavid van Moolenbroek return 0;
363*5d5fbe79SDavid van Moolenbroek }
364*5d5fbe79SDavid van Moolenbroek
365*5d5fbe79SDavid van Moolenbroek if (option_priority >= prio_local) {
366*5d5fbe79SDavid van Moolenbroek eui64_copy(addr.s6_addr32[2], wo->ourid);
367*5d5fbe79SDavid van Moolenbroek wo->opt_local = 1;
368*5d5fbe79SDavid van Moolenbroek prio_local = option_priority;
369*5d5fbe79SDavid van Moolenbroek }
370*5d5fbe79SDavid van Moolenbroek *comma = c;
371*5d5fbe79SDavid van Moolenbroek }
372*5d5fbe79SDavid van Moolenbroek
373*5d5fbe79SDavid van Moolenbroek /*
374*5d5fbe79SDavid van Moolenbroek * If comma last character, the no remote identifier
375*5d5fbe79SDavid van Moolenbroek */
376*5d5fbe79SDavid van Moolenbroek if (*comma != 0 && *++comma != '\0') {
377*5d5fbe79SDavid van Moolenbroek if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) {
378*5d5fbe79SDavid van Moolenbroek option_error("Illegal interface identifier (remote): %s", comma);
379*5d5fbe79SDavid van Moolenbroek return 0;
380*5d5fbe79SDavid van Moolenbroek }
381*5d5fbe79SDavid van Moolenbroek if (option_priority >= prio_remote) {
382*5d5fbe79SDavid van Moolenbroek eui64_copy(addr.s6_addr32[2], wo->hisid);
383*5d5fbe79SDavid van Moolenbroek wo->opt_remote = 1;
384*5d5fbe79SDavid van Moolenbroek prio_remote = option_priority;
385*5d5fbe79SDavid van Moolenbroek }
386*5d5fbe79SDavid van Moolenbroek }
387*5d5fbe79SDavid van Moolenbroek
388*5d5fbe79SDavid van Moolenbroek if (override_value("+ipv6", option_priority, option_source))
389*5d5fbe79SDavid van Moolenbroek ipv6cp_protent.enabled_flag = 1;
390*5d5fbe79SDavid van Moolenbroek return 1;
391*5d5fbe79SDavid van Moolenbroek }
392*5d5fbe79SDavid van Moolenbroek
393*5d5fbe79SDavid van Moolenbroek static void
394*5d5fbe79SDavid van Moolenbroek printifaceid(opt, printer, arg)
395*5d5fbe79SDavid van Moolenbroek option_t *opt;
396*5d5fbe79SDavid van Moolenbroek void (*printer)(void *, char *, ...));
397*5d5fbe79SDavid van Moolenbroek void *arg;
398*5d5fbe79SDavid van Moolenbroek {
399*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &ipv6cp_wantoptions[0];
400*5d5fbe79SDavid van Moolenbroek
401*5d5fbe79SDavid van Moolenbroek if (wo->opt_local)
402*5d5fbe79SDavid van Moolenbroek printer(arg, "%s", llv6_ntoa(wo->ourid));
403*5d5fbe79SDavid van Moolenbroek printer(arg, ",");
404*5d5fbe79SDavid van Moolenbroek if (wo->opt_remote)
405*5d5fbe79SDavid van Moolenbroek printer(arg, "%s", llv6_ntoa(wo->hisid));
406*5d5fbe79SDavid van Moolenbroek }
407*5d5fbe79SDavid van Moolenbroek #endif /* PPP_OPTIONS */
408*5d5fbe79SDavid van Moolenbroek
409*5d5fbe79SDavid van Moolenbroek /*
410*5d5fbe79SDavid van Moolenbroek * Make a string representation of a network address.
411*5d5fbe79SDavid van Moolenbroek */
412*5d5fbe79SDavid van Moolenbroek static char *
413*5d5fbe79SDavid van Moolenbroek llv6_ntoa(eui64_t ifaceid)
414*5d5fbe79SDavid van Moolenbroek {
415*5d5fbe79SDavid van Moolenbroek static char b[26];
416*5d5fbe79SDavid van Moolenbroek
417*5d5fbe79SDavid van Moolenbroek sprintf(b, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x",
418*5d5fbe79SDavid van Moolenbroek ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3],
419*5d5fbe79SDavid van Moolenbroek ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]);
420*5d5fbe79SDavid van Moolenbroek
421*5d5fbe79SDavid van Moolenbroek return b;
422*5d5fbe79SDavid van Moolenbroek }
423*5d5fbe79SDavid van Moolenbroek
424*5d5fbe79SDavid van Moolenbroek
425*5d5fbe79SDavid van Moolenbroek /*
426*5d5fbe79SDavid van Moolenbroek * ipv6cp_init - Initialize IPV6CP.
427*5d5fbe79SDavid van Moolenbroek */
428*5d5fbe79SDavid van Moolenbroek static void ipv6cp_init(ppp_pcb *pcb) {
429*5d5fbe79SDavid van Moolenbroek fsm *f = &pcb->ipv6cp_fsm;
430*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
431*5d5fbe79SDavid van Moolenbroek ipv6cp_options *ao = &pcb->ipv6cp_allowoptions;
432*5d5fbe79SDavid van Moolenbroek
433*5d5fbe79SDavid van Moolenbroek f->pcb = pcb;
434*5d5fbe79SDavid van Moolenbroek f->protocol = PPP_IPV6CP;
435*5d5fbe79SDavid van Moolenbroek f->callbacks = &ipv6cp_callbacks;
436*5d5fbe79SDavid van Moolenbroek fsm_init(f);
437*5d5fbe79SDavid van Moolenbroek
438*5d5fbe79SDavid van Moolenbroek #if 0 /* Not necessary, everything is cleared in ppp_new() */
439*5d5fbe79SDavid van Moolenbroek memset(wo, 0, sizeof(*wo));
440*5d5fbe79SDavid van Moolenbroek memset(ao, 0, sizeof(*ao));
441*5d5fbe79SDavid van Moolenbroek #endif /* 0 */
442*5d5fbe79SDavid van Moolenbroek
443*5d5fbe79SDavid van Moolenbroek wo->accept_local = 1;
444*5d5fbe79SDavid van Moolenbroek wo->neg_ifaceid = 1;
445*5d5fbe79SDavid van Moolenbroek ao->neg_ifaceid = 1;
446*5d5fbe79SDavid van Moolenbroek
447*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
448*5d5fbe79SDavid van Moolenbroek wo->neg_vj = 1;
449*5d5fbe79SDavid van Moolenbroek ao->neg_vj = 1;
450*5d5fbe79SDavid van Moolenbroek wo->vj_protocol = IPV6CP_COMP;
451*5d5fbe79SDavid van Moolenbroek #endif
452*5d5fbe79SDavid van Moolenbroek
453*5d5fbe79SDavid van Moolenbroek }
454*5d5fbe79SDavid van Moolenbroek
455*5d5fbe79SDavid van Moolenbroek
456*5d5fbe79SDavid van Moolenbroek /*
457*5d5fbe79SDavid van Moolenbroek * ipv6cp_open - IPV6CP is allowed to come up.
458*5d5fbe79SDavid van Moolenbroek */
459*5d5fbe79SDavid van Moolenbroek static void ipv6cp_open(ppp_pcb *pcb) {
460*5d5fbe79SDavid van Moolenbroek fsm_open(&pcb->ipv6cp_fsm);
461*5d5fbe79SDavid van Moolenbroek }
462*5d5fbe79SDavid van Moolenbroek
463*5d5fbe79SDavid van Moolenbroek
464*5d5fbe79SDavid van Moolenbroek /*
465*5d5fbe79SDavid van Moolenbroek * ipv6cp_close - Take IPV6CP down.
466*5d5fbe79SDavid van Moolenbroek */
467*5d5fbe79SDavid van Moolenbroek static void ipv6cp_close(ppp_pcb *pcb, const char *reason) {
468*5d5fbe79SDavid van Moolenbroek fsm_close(&pcb->ipv6cp_fsm, reason);
469*5d5fbe79SDavid van Moolenbroek }
470*5d5fbe79SDavid van Moolenbroek
471*5d5fbe79SDavid van Moolenbroek
472*5d5fbe79SDavid van Moolenbroek /*
473*5d5fbe79SDavid van Moolenbroek * ipv6cp_lowerup - The lower layer is up.
474*5d5fbe79SDavid van Moolenbroek */
475*5d5fbe79SDavid van Moolenbroek static void ipv6cp_lowerup(ppp_pcb *pcb) {
476*5d5fbe79SDavid van Moolenbroek fsm_lowerup(&pcb->ipv6cp_fsm);
477*5d5fbe79SDavid van Moolenbroek }
478*5d5fbe79SDavid van Moolenbroek
479*5d5fbe79SDavid van Moolenbroek
480*5d5fbe79SDavid van Moolenbroek /*
481*5d5fbe79SDavid van Moolenbroek * ipv6cp_lowerdown - The lower layer is down.
482*5d5fbe79SDavid van Moolenbroek */
483*5d5fbe79SDavid van Moolenbroek static void ipv6cp_lowerdown(ppp_pcb *pcb) {
484*5d5fbe79SDavid van Moolenbroek fsm_lowerdown(&pcb->ipv6cp_fsm);
485*5d5fbe79SDavid van Moolenbroek }
486*5d5fbe79SDavid van Moolenbroek
487*5d5fbe79SDavid van Moolenbroek
488*5d5fbe79SDavid van Moolenbroek /*
489*5d5fbe79SDavid van Moolenbroek * ipv6cp_input - Input IPV6CP packet.
490*5d5fbe79SDavid van Moolenbroek */
491*5d5fbe79SDavid van Moolenbroek static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) {
492*5d5fbe79SDavid van Moolenbroek fsm_input(&pcb->ipv6cp_fsm, p, len);
493*5d5fbe79SDavid van Moolenbroek }
494*5d5fbe79SDavid van Moolenbroek
495*5d5fbe79SDavid van Moolenbroek
496*5d5fbe79SDavid van Moolenbroek /*
497*5d5fbe79SDavid van Moolenbroek * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP.
498*5d5fbe79SDavid van Moolenbroek *
499*5d5fbe79SDavid van Moolenbroek * Pretend the lower layer went down, so we shut up.
500*5d5fbe79SDavid van Moolenbroek */
501*5d5fbe79SDavid van Moolenbroek static void ipv6cp_protrej(ppp_pcb *pcb) {
502*5d5fbe79SDavid van Moolenbroek fsm_lowerdown(&pcb->ipv6cp_fsm);
503*5d5fbe79SDavid van Moolenbroek }
504*5d5fbe79SDavid van Moolenbroek
505*5d5fbe79SDavid van Moolenbroek
506*5d5fbe79SDavid van Moolenbroek /*
507*5d5fbe79SDavid van Moolenbroek * ipv6cp_resetci - Reset our CI.
508*5d5fbe79SDavid van Moolenbroek */
509*5d5fbe79SDavid van Moolenbroek static void ipv6cp_resetci(fsm *f) {
510*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
511*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
512*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
513*5d5fbe79SDavid van Moolenbroek ipv6cp_options *ao = &pcb->ipv6cp_allowoptions;
514*5d5fbe79SDavid van Moolenbroek
515*5d5fbe79SDavid van Moolenbroek wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid;
516*5d5fbe79SDavid van Moolenbroek
517*5d5fbe79SDavid van Moolenbroek if (!wo->opt_local) {
518*5d5fbe79SDavid van Moolenbroek eui64_magic_nz(wo->ourid);
519*5d5fbe79SDavid van Moolenbroek }
520*5d5fbe79SDavid van Moolenbroek
521*5d5fbe79SDavid van Moolenbroek *go = *wo;
522*5d5fbe79SDavid van Moolenbroek eui64_zero(go->hisid); /* last proposed interface identifier */
523*5d5fbe79SDavid van Moolenbroek }
524*5d5fbe79SDavid van Moolenbroek
525*5d5fbe79SDavid van Moolenbroek
526*5d5fbe79SDavid van Moolenbroek /*
527*5d5fbe79SDavid van Moolenbroek * ipv6cp_cilen - Return length of our CI.
528*5d5fbe79SDavid van Moolenbroek */
529*5d5fbe79SDavid van Moolenbroek static int ipv6cp_cilen(fsm *f) {
530*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
531*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
532*5d5fbe79SDavid van Moolenbroek
533*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
534*5d5fbe79SDavid van Moolenbroek #define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0)
535*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
536*5d5fbe79SDavid van Moolenbroek #define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0)
537*5d5fbe79SDavid van Moolenbroek
538*5d5fbe79SDavid van Moolenbroek return (LENCIIFACEID(go->neg_ifaceid) +
539*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
540*5d5fbe79SDavid van Moolenbroek LENCIVJ(go->neg_vj) +
541*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
542*5d5fbe79SDavid van Moolenbroek 0);
543*5d5fbe79SDavid van Moolenbroek }
544*5d5fbe79SDavid van Moolenbroek
545*5d5fbe79SDavid van Moolenbroek
546*5d5fbe79SDavid van Moolenbroek /*
547*5d5fbe79SDavid van Moolenbroek * ipv6cp_addci - Add our desired CIs to a packet.
548*5d5fbe79SDavid van Moolenbroek */
549*5d5fbe79SDavid van Moolenbroek static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) {
550*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
551*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
552*5d5fbe79SDavid van Moolenbroek int len = *lenp;
553*5d5fbe79SDavid van Moolenbroek
554*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
555*5d5fbe79SDavid van Moolenbroek #define ADDCIVJ(opt, neg, val) \
556*5d5fbe79SDavid van Moolenbroek if (neg) { \
557*5d5fbe79SDavid van Moolenbroek int vjlen = CILEN_COMPRESS; \
558*5d5fbe79SDavid van Moolenbroek if (len >= vjlen) { \
559*5d5fbe79SDavid van Moolenbroek PUTCHAR(opt, ucp); \
560*5d5fbe79SDavid van Moolenbroek PUTCHAR(vjlen, ucp); \
561*5d5fbe79SDavid van Moolenbroek PUTSHORT(val, ucp); \
562*5d5fbe79SDavid van Moolenbroek len -= vjlen; \
563*5d5fbe79SDavid van Moolenbroek } else \
564*5d5fbe79SDavid van Moolenbroek neg = 0; \
565*5d5fbe79SDavid van Moolenbroek }
566*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
567*5d5fbe79SDavid van Moolenbroek
568*5d5fbe79SDavid van Moolenbroek #define ADDCIIFACEID(opt, neg, val1) \
569*5d5fbe79SDavid van Moolenbroek if (neg) { \
570*5d5fbe79SDavid van Moolenbroek int idlen = CILEN_IFACEID; \
571*5d5fbe79SDavid van Moolenbroek if (len >= idlen) { \
572*5d5fbe79SDavid van Moolenbroek PUTCHAR(opt, ucp); \
573*5d5fbe79SDavid van Moolenbroek PUTCHAR(idlen, ucp); \
574*5d5fbe79SDavid van Moolenbroek eui64_put(val1, ucp); \
575*5d5fbe79SDavid van Moolenbroek len -= idlen; \
576*5d5fbe79SDavid van Moolenbroek } else \
577*5d5fbe79SDavid van Moolenbroek neg = 0; \
578*5d5fbe79SDavid van Moolenbroek }
579*5d5fbe79SDavid van Moolenbroek
580*5d5fbe79SDavid van Moolenbroek ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid);
581*5d5fbe79SDavid van Moolenbroek
582*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
583*5d5fbe79SDavid van Moolenbroek ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol);
584*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
585*5d5fbe79SDavid van Moolenbroek
586*5d5fbe79SDavid van Moolenbroek *lenp -= len;
587*5d5fbe79SDavid van Moolenbroek }
588*5d5fbe79SDavid van Moolenbroek
589*5d5fbe79SDavid van Moolenbroek
590*5d5fbe79SDavid van Moolenbroek /*
591*5d5fbe79SDavid van Moolenbroek * ipv6cp_ackci - Ack our CIs.
592*5d5fbe79SDavid van Moolenbroek *
593*5d5fbe79SDavid van Moolenbroek * Returns:
594*5d5fbe79SDavid van Moolenbroek * 0 - Ack was bad.
595*5d5fbe79SDavid van Moolenbroek * 1 - Ack was good.
596*5d5fbe79SDavid van Moolenbroek */
597*5d5fbe79SDavid van Moolenbroek static int ipv6cp_ackci(fsm *f, u_char *p, int len) {
598*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
599*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
600*5d5fbe79SDavid van Moolenbroek u_short cilen, citype;
601*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
602*5d5fbe79SDavid van Moolenbroek u_short cishort;
603*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
604*5d5fbe79SDavid van Moolenbroek eui64_t ifaceid;
605*5d5fbe79SDavid van Moolenbroek
606*5d5fbe79SDavid van Moolenbroek /*
607*5d5fbe79SDavid van Moolenbroek * CIs must be in exactly the same order that we sent...
608*5d5fbe79SDavid van Moolenbroek * Check packet length and CI length at each step.
609*5d5fbe79SDavid van Moolenbroek * If we find any deviations, then this packet is bad.
610*5d5fbe79SDavid van Moolenbroek */
611*5d5fbe79SDavid van Moolenbroek
612*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
613*5d5fbe79SDavid van Moolenbroek #define ACKCIVJ(opt, neg, val) \
614*5d5fbe79SDavid van Moolenbroek if (neg) { \
615*5d5fbe79SDavid van Moolenbroek int vjlen = CILEN_COMPRESS; \
616*5d5fbe79SDavid van Moolenbroek if ((len -= vjlen) < 0) \
617*5d5fbe79SDavid van Moolenbroek goto bad; \
618*5d5fbe79SDavid van Moolenbroek GETCHAR(citype, p); \
619*5d5fbe79SDavid van Moolenbroek GETCHAR(cilen, p); \
620*5d5fbe79SDavid van Moolenbroek if (cilen != vjlen || \
621*5d5fbe79SDavid van Moolenbroek citype != opt) \
622*5d5fbe79SDavid van Moolenbroek goto bad; \
623*5d5fbe79SDavid van Moolenbroek GETSHORT(cishort, p); \
624*5d5fbe79SDavid van Moolenbroek if (cishort != val) \
625*5d5fbe79SDavid van Moolenbroek goto bad; \
626*5d5fbe79SDavid van Moolenbroek }
627*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
628*5d5fbe79SDavid van Moolenbroek
629*5d5fbe79SDavid van Moolenbroek #define ACKCIIFACEID(opt, neg, val1) \
630*5d5fbe79SDavid van Moolenbroek if (neg) { \
631*5d5fbe79SDavid van Moolenbroek int idlen = CILEN_IFACEID; \
632*5d5fbe79SDavid van Moolenbroek if ((len -= idlen) < 0) \
633*5d5fbe79SDavid van Moolenbroek goto bad; \
634*5d5fbe79SDavid van Moolenbroek GETCHAR(citype, p); \
635*5d5fbe79SDavid van Moolenbroek GETCHAR(cilen, p); \
636*5d5fbe79SDavid van Moolenbroek if (cilen != idlen || \
637*5d5fbe79SDavid van Moolenbroek citype != opt) \
638*5d5fbe79SDavid van Moolenbroek goto bad; \
639*5d5fbe79SDavid van Moolenbroek eui64_get(ifaceid, p); \
640*5d5fbe79SDavid van Moolenbroek if (! eui64_equals(val1, ifaceid)) \
641*5d5fbe79SDavid van Moolenbroek goto bad; \
642*5d5fbe79SDavid van Moolenbroek }
643*5d5fbe79SDavid van Moolenbroek
644*5d5fbe79SDavid van Moolenbroek ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid);
645*5d5fbe79SDavid van Moolenbroek
646*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
647*5d5fbe79SDavid van Moolenbroek ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol);
648*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
649*5d5fbe79SDavid van Moolenbroek
650*5d5fbe79SDavid van Moolenbroek /*
651*5d5fbe79SDavid van Moolenbroek * If there are any remaining CIs, then this packet is bad.
652*5d5fbe79SDavid van Moolenbroek */
653*5d5fbe79SDavid van Moolenbroek if (len != 0)
654*5d5fbe79SDavid van Moolenbroek goto bad;
655*5d5fbe79SDavid van Moolenbroek return (1);
656*5d5fbe79SDavid van Moolenbroek
657*5d5fbe79SDavid van Moolenbroek bad:
658*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!"));
659*5d5fbe79SDavid van Moolenbroek return (0);
660*5d5fbe79SDavid van Moolenbroek }
661*5d5fbe79SDavid van Moolenbroek
662*5d5fbe79SDavid van Moolenbroek /*
663*5d5fbe79SDavid van Moolenbroek * ipv6cp_nakci - Peer has sent a NAK for some of our CIs.
664*5d5fbe79SDavid van Moolenbroek * This should not modify any state if the Nak is bad
665*5d5fbe79SDavid van Moolenbroek * or if IPV6CP is in the OPENED state.
666*5d5fbe79SDavid van Moolenbroek *
667*5d5fbe79SDavid van Moolenbroek * Returns:
668*5d5fbe79SDavid van Moolenbroek * 0 - Nak was bad.
669*5d5fbe79SDavid van Moolenbroek * 1 - Nak was good.
670*5d5fbe79SDavid van Moolenbroek */
671*5d5fbe79SDavid van Moolenbroek static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) {
672*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
673*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
674*5d5fbe79SDavid van Moolenbroek u_char citype, cilen, *next;
675*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
676*5d5fbe79SDavid van Moolenbroek u_short cishort;
677*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
678*5d5fbe79SDavid van Moolenbroek eui64_t ifaceid;
679*5d5fbe79SDavid van Moolenbroek ipv6cp_options no; /* options we've seen Naks for */
680*5d5fbe79SDavid van Moolenbroek ipv6cp_options try_; /* options to request next time */
681*5d5fbe79SDavid van Moolenbroek
682*5d5fbe79SDavid van Moolenbroek BZERO(&no, sizeof(no));
683*5d5fbe79SDavid van Moolenbroek try_ = *go;
684*5d5fbe79SDavid van Moolenbroek
685*5d5fbe79SDavid van Moolenbroek /*
686*5d5fbe79SDavid van Moolenbroek * Any Nak'd CIs must be in exactly the same order that we sent.
687*5d5fbe79SDavid van Moolenbroek * Check packet length and CI length at each step.
688*5d5fbe79SDavid van Moolenbroek * If we find any deviations, then this packet is bad.
689*5d5fbe79SDavid van Moolenbroek */
690*5d5fbe79SDavid van Moolenbroek #define NAKCIIFACEID(opt, neg, code) \
691*5d5fbe79SDavid van Moolenbroek if (go->neg && \
692*5d5fbe79SDavid van Moolenbroek len >= (cilen = CILEN_IFACEID) && \
693*5d5fbe79SDavid van Moolenbroek p[1] == cilen && \
694*5d5fbe79SDavid van Moolenbroek p[0] == opt) { \
695*5d5fbe79SDavid van Moolenbroek len -= cilen; \
696*5d5fbe79SDavid van Moolenbroek INCPTR(2, p); \
697*5d5fbe79SDavid van Moolenbroek eui64_get(ifaceid, p); \
698*5d5fbe79SDavid van Moolenbroek no.neg = 1; \
699*5d5fbe79SDavid van Moolenbroek code \
700*5d5fbe79SDavid van Moolenbroek }
701*5d5fbe79SDavid van Moolenbroek
702*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
703*5d5fbe79SDavid van Moolenbroek #define NAKCIVJ(opt, neg, code) \
704*5d5fbe79SDavid van Moolenbroek if (go->neg && \
705*5d5fbe79SDavid van Moolenbroek ((cilen = p[1]) == CILEN_COMPRESS) && \
706*5d5fbe79SDavid van Moolenbroek len >= cilen && \
707*5d5fbe79SDavid van Moolenbroek p[0] == opt) { \
708*5d5fbe79SDavid van Moolenbroek len -= cilen; \
709*5d5fbe79SDavid van Moolenbroek INCPTR(2, p); \
710*5d5fbe79SDavid van Moolenbroek GETSHORT(cishort, p); \
711*5d5fbe79SDavid van Moolenbroek no.neg = 1; \
712*5d5fbe79SDavid van Moolenbroek code \
713*5d5fbe79SDavid van Moolenbroek }
714*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
715*5d5fbe79SDavid van Moolenbroek
716*5d5fbe79SDavid van Moolenbroek /*
717*5d5fbe79SDavid van Moolenbroek * Accept the peer's idea of {our,his} interface identifier, if different
718*5d5fbe79SDavid van Moolenbroek * from our idea, only if the accept_{local,remote} flag is set.
719*5d5fbe79SDavid van Moolenbroek */
720*5d5fbe79SDavid van Moolenbroek NAKCIIFACEID(CI_IFACEID, neg_ifaceid,
721*5d5fbe79SDavid van Moolenbroek if (treat_as_reject) {
722*5d5fbe79SDavid van Moolenbroek try_.neg_ifaceid = 0;
723*5d5fbe79SDavid van Moolenbroek } else if (go->accept_local) {
724*5d5fbe79SDavid van Moolenbroek while (eui64_iszero(ifaceid) ||
725*5d5fbe79SDavid van Moolenbroek eui64_equals(ifaceid, go->hisid)) /* bad luck */
726*5d5fbe79SDavid van Moolenbroek eui64_magic(ifaceid);
727*5d5fbe79SDavid van Moolenbroek try_.ourid = ifaceid;
728*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid)));
729*5d5fbe79SDavid van Moolenbroek }
730*5d5fbe79SDavid van Moolenbroek );
731*5d5fbe79SDavid van Moolenbroek
732*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
733*5d5fbe79SDavid van Moolenbroek NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
734*5d5fbe79SDavid van Moolenbroek {
735*5d5fbe79SDavid van Moolenbroek if (cishort == IPV6CP_COMP && !treat_as_reject) {
736*5d5fbe79SDavid van Moolenbroek try_.vj_protocol = cishort;
737*5d5fbe79SDavid van Moolenbroek } else {
738*5d5fbe79SDavid van Moolenbroek try_.neg_vj = 0;
739*5d5fbe79SDavid van Moolenbroek }
740*5d5fbe79SDavid van Moolenbroek }
741*5d5fbe79SDavid van Moolenbroek );
742*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
743*5d5fbe79SDavid van Moolenbroek
744*5d5fbe79SDavid van Moolenbroek /*
745*5d5fbe79SDavid van Moolenbroek * There may be remaining CIs, if the peer is requesting negotiation
746*5d5fbe79SDavid van Moolenbroek * on an option that we didn't include in our request packet.
747*5d5fbe79SDavid van Moolenbroek * If they want to negotiate about interface identifier, we comply.
748*5d5fbe79SDavid van Moolenbroek * If they want us to ask for compression, we refuse.
749*5d5fbe79SDavid van Moolenbroek */
750*5d5fbe79SDavid van Moolenbroek while (len >= CILEN_VOID) {
751*5d5fbe79SDavid van Moolenbroek GETCHAR(citype, p);
752*5d5fbe79SDavid van Moolenbroek GETCHAR(cilen, p);
753*5d5fbe79SDavid van Moolenbroek if ( cilen < CILEN_VOID || (len -= cilen) < 0 )
754*5d5fbe79SDavid van Moolenbroek goto bad;
755*5d5fbe79SDavid van Moolenbroek next = p + cilen - 2;
756*5d5fbe79SDavid van Moolenbroek
757*5d5fbe79SDavid van Moolenbroek switch (citype) {
758*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
759*5d5fbe79SDavid van Moolenbroek case CI_COMPRESSTYPE:
760*5d5fbe79SDavid van Moolenbroek if (go->neg_vj || no.neg_vj ||
761*5d5fbe79SDavid van Moolenbroek (cilen != CILEN_COMPRESS))
762*5d5fbe79SDavid van Moolenbroek goto bad;
763*5d5fbe79SDavid van Moolenbroek no.neg_vj = 1;
764*5d5fbe79SDavid van Moolenbroek break;
765*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
766*5d5fbe79SDavid van Moolenbroek case CI_IFACEID:
767*5d5fbe79SDavid van Moolenbroek if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID)
768*5d5fbe79SDavid van Moolenbroek goto bad;
769*5d5fbe79SDavid van Moolenbroek try_.neg_ifaceid = 1;
770*5d5fbe79SDavid van Moolenbroek eui64_get(ifaceid, p);
771*5d5fbe79SDavid van Moolenbroek if (go->accept_local) {
772*5d5fbe79SDavid van Moolenbroek while (eui64_iszero(ifaceid) ||
773*5d5fbe79SDavid van Moolenbroek eui64_equals(ifaceid, go->hisid)) /* bad luck */
774*5d5fbe79SDavid van Moolenbroek eui64_magic(ifaceid);
775*5d5fbe79SDavid van Moolenbroek try_.ourid = ifaceid;
776*5d5fbe79SDavid van Moolenbroek }
777*5d5fbe79SDavid van Moolenbroek no.neg_ifaceid = 1;
778*5d5fbe79SDavid van Moolenbroek break;
779*5d5fbe79SDavid van Moolenbroek default:
780*5d5fbe79SDavid van Moolenbroek break;
781*5d5fbe79SDavid van Moolenbroek }
782*5d5fbe79SDavid van Moolenbroek p = next;
783*5d5fbe79SDavid van Moolenbroek }
784*5d5fbe79SDavid van Moolenbroek
785*5d5fbe79SDavid van Moolenbroek /* If there is still anything left, this packet is bad. */
786*5d5fbe79SDavid van Moolenbroek if (len != 0)
787*5d5fbe79SDavid van Moolenbroek goto bad;
788*5d5fbe79SDavid van Moolenbroek
789*5d5fbe79SDavid van Moolenbroek /*
790*5d5fbe79SDavid van Moolenbroek * OK, the Nak is good. Now we can update state.
791*5d5fbe79SDavid van Moolenbroek */
792*5d5fbe79SDavid van Moolenbroek if (f->state != PPP_FSM_OPENED)
793*5d5fbe79SDavid van Moolenbroek *go = try_;
794*5d5fbe79SDavid van Moolenbroek
795*5d5fbe79SDavid van Moolenbroek return 1;
796*5d5fbe79SDavid van Moolenbroek
797*5d5fbe79SDavid van Moolenbroek bad:
798*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!"));
799*5d5fbe79SDavid van Moolenbroek return 0;
800*5d5fbe79SDavid van Moolenbroek }
801*5d5fbe79SDavid van Moolenbroek
802*5d5fbe79SDavid van Moolenbroek
803*5d5fbe79SDavid van Moolenbroek /*
804*5d5fbe79SDavid van Moolenbroek * ipv6cp_rejci - Reject some of our CIs.
805*5d5fbe79SDavid van Moolenbroek */
806*5d5fbe79SDavid van Moolenbroek static int ipv6cp_rejci(fsm *f, u_char *p, int len) {
807*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
808*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
809*5d5fbe79SDavid van Moolenbroek u_char cilen;
810*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
811*5d5fbe79SDavid van Moolenbroek u_short cishort;
812*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
813*5d5fbe79SDavid van Moolenbroek eui64_t ifaceid;
814*5d5fbe79SDavid van Moolenbroek ipv6cp_options try_; /* options to request next time */
815*5d5fbe79SDavid van Moolenbroek
816*5d5fbe79SDavid van Moolenbroek try_ = *go;
817*5d5fbe79SDavid van Moolenbroek /*
818*5d5fbe79SDavid van Moolenbroek * Any Rejected CIs must be in exactly the same order that we sent.
819*5d5fbe79SDavid van Moolenbroek * Check packet length and CI length at each step.
820*5d5fbe79SDavid van Moolenbroek * If we find any deviations, then this packet is bad.
821*5d5fbe79SDavid van Moolenbroek */
822*5d5fbe79SDavid van Moolenbroek #define REJCIIFACEID(opt, neg, val1) \
823*5d5fbe79SDavid van Moolenbroek if (go->neg && \
824*5d5fbe79SDavid van Moolenbroek len >= (cilen = CILEN_IFACEID) && \
825*5d5fbe79SDavid van Moolenbroek p[1] == cilen && \
826*5d5fbe79SDavid van Moolenbroek p[0] == opt) { \
827*5d5fbe79SDavid van Moolenbroek len -= cilen; \
828*5d5fbe79SDavid van Moolenbroek INCPTR(2, p); \
829*5d5fbe79SDavid van Moolenbroek eui64_get(ifaceid, p); \
830*5d5fbe79SDavid van Moolenbroek /* Check rejected value. */ \
831*5d5fbe79SDavid van Moolenbroek if (! eui64_equals(ifaceid, val1)) \
832*5d5fbe79SDavid van Moolenbroek goto bad; \
833*5d5fbe79SDavid van Moolenbroek try_.neg = 0; \
834*5d5fbe79SDavid van Moolenbroek }
835*5d5fbe79SDavid van Moolenbroek
836*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
837*5d5fbe79SDavid van Moolenbroek #define REJCIVJ(opt, neg, val) \
838*5d5fbe79SDavid van Moolenbroek if (go->neg && \
839*5d5fbe79SDavid van Moolenbroek p[1] == CILEN_COMPRESS && \
840*5d5fbe79SDavid van Moolenbroek len >= p[1] && \
841*5d5fbe79SDavid van Moolenbroek p[0] == opt) { \
842*5d5fbe79SDavid van Moolenbroek len -= p[1]; \
843*5d5fbe79SDavid van Moolenbroek INCPTR(2, p); \
844*5d5fbe79SDavid van Moolenbroek GETSHORT(cishort, p); \
845*5d5fbe79SDavid van Moolenbroek /* Check rejected value. */ \
846*5d5fbe79SDavid van Moolenbroek if (cishort != val) \
847*5d5fbe79SDavid van Moolenbroek goto bad; \
848*5d5fbe79SDavid van Moolenbroek try_.neg = 0; \
849*5d5fbe79SDavid van Moolenbroek }
850*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
851*5d5fbe79SDavid van Moolenbroek
852*5d5fbe79SDavid van Moolenbroek REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid);
853*5d5fbe79SDavid van Moolenbroek
854*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
855*5d5fbe79SDavid van Moolenbroek REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol);
856*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
857*5d5fbe79SDavid van Moolenbroek
858*5d5fbe79SDavid van Moolenbroek /*
859*5d5fbe79SDavid van Moolenbroek * If there are any remaining CIs, then this packet is bad.
860*5d5fbe79SDavid van Moolenbroek */
861*5d5fbe79SDavid van Moolenbroek if (len != 0)
862*5d5fbe79SDavid van Moolenbroek goto bad;
863*5d5fbe79SDavid van Moolenbroek /*
864*5d5fbe79SDavid van Moolenbroek * Now we can update state.
865*5d5fbe79SDavid van Moolenbroek */
866*5d5fbe79SDavid van Moolenbroek if (f->state != PPP_FSM_OPENED)
867*5d5fbe79SDavid van Moolenbroek *go = try_;
868*5d5fbe79SDavid van Moolenbroek return 1;
869*5d5fbe79SDavid van Moolenbroek
870*5d5fbe79SDavid van Moolenbroek bad:
871*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!"));
872*5d5fbe79SDavid van Moolenbroek return 0;
873*5d5fbe79SDavid van Moolenbroek }
874*5d5fbe79SDavid van Moolenbroek
875*5d5fbe79SDavid van Moolenbroek
876*5d5fbe79SDavid van Moolenbroek /*
877*5d5fbe79SDavid van Moolenbroek * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response.
878*5d5fbe79SDavid van Moolenbroek *
879*5d5fbe79SDavid van Moolenbroek * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
880*5d5fbe79SDavid van Moolenbroek * appropriately. If reject_if_disagree is non-zero, doesn't return
881*5d5fbe79SDavid van Moolenbroek * CONFNAK; returns CONFREJ if it can't return CONFACK.
882*5d5fbe79SDavid van Moolenbroek *
883*5d5fbe79SDavid van Moolenbroek * inp = Requested CIs
884*5d5fbe79SDavid van Moolenbroek * len = Length of requested CIs
885*5d5fbe79SDavid van Moolenbroek *
886*5d5fbe79SDavid van Moolenbroek */
887*5d5fbe79SDavid van Moolenbroek static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) {
888*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
889*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
890*5d5fbe79SDavid van Moolenbroek ipv6cp_options *ho = &pcb->ipv6cp_hisoptions;
891*5d5fbe79SDavid van Moolenbroek ipv6cp_options *ao = &pcb->ipv6cp_allowoptions;
892*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
893*5d5fbe79SDavid van Moolenbroek u_char *cip, *next; /* Pointer to current and next CIs */
894*5d5fbe79SDavid van Moolenbroek u_short cilen, citype; /* Parsed len, type */
895*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
896*5d5fbe79SDavid van Moolenbroek u_short cishort; /* Parsed short value */
897*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
898*5d5fbe79SDavid van Moolenbroek eui64_t ifaceid; /* Parsed interface identifier */
899*5d5fbe79SDavid van Moolenbroek int rc = CONFACK; /* Final packet return code */
900*5d5fbe79SDavid van Moolenbroek int orc; /* Individual option return code */
901*5d5fbe79SDavid van Moolenbroek u_char *p; /* Pointer to next char to parse */
902*5d5fbe79SDavid van Moolenbroek u_char *ucp = inp; /* Pointer to current output char */
903*5d5fbe79SDavid van Moolenbroek int l = *len; /* Length left */
904*5d5fbe79SDavid van Moolenbroek
905*5d5fbe79SDavid van Moolenbroek /*
906*5d5fbe79SDavid van Moolenbroek * Reset all his options.
907*5d5fbe79SDavid van Moolenbroek */
908*5d5fbe79SDavid van Moolenbroek BZERO(ho, sizeof(*ho));
909*5d5fbe79SDavid van Moolenbroek
910*5d5fbe79SDavid van Moolenbroek /*
911*5d5fbe79SDavid van Moolenbroek * Process all his options.
912*5d5fbe79SDavid van Moolenbroek */
913*5d5fbe79SDavid van Moolenbroek next = inp;
914*5d5fbe79SDavid van Moolenbroek while (l) {
915*5d5fbe79SDavid van Moolenbroek orc = CONFACK; /* Assume success */
916*5d5fbe79SDavid van Moolenbroek cip = p = next; /* Remember begining of CI */
917*5d5fbe79SDavid van Moolenbroek if (l < 2 || /* Not enough data for CI header or */
918*5d5fbe79SDavid van Moolenbroek p[1] < 2 || /* CI length too small or */
919*5d5fbe79SDavid van Moolenbroek p[1] > l) { /* CI length too big? */
920*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!"));
921*5d5fbe79SDavid van Moolenbroek orc = CONFREJ; /* Reject bad CI */
922*5d5fbe79SDavid van Moolenbroek cilen = l; /* Reject till end of packet */
923*5d5fbe79SDavid van Moolenbroek l = 0; /* Don't loop again */
924*5d5fbe79SDavid van Moolenbroek goto endswitch;
925*5d5fbe79SDavid van Moolenbroek }
926*5d5fbe79SDavid van Moolenbroek GETCHAR(citype, p); /* Parse CI type */
927*5d5fbe79SDavid van Moolenbroek GETCHAR(cilen, p); /* Parse CI length */
928*5d5fbe79SDavid van Moolenbroek l -= cilen; /* Adjust remaining length */
929*5d5fbe79SDavid van Moolenbroek next += cilen; /* Step to next CI */
930*5d5fbe79SDavid van Moolenbroek
931*5d5fbe79SDavid van Moolenbroek switch (citype) { /* Check CI type */
932*5d5fbe79SDavid van Moolenbroek case CI_IFACEID:
933*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp: received interface identifier "));
934*5d5fbe79SDavid van Moolenbroek
935*5d5fbe79SDavid van Moolenbroek if (!ao->neg_ifaceid ||
936*5d5fbe79SDavid van Moolenbroek cilen != CILEN_IFACEID) { /* Check CI length */
937*5d5fbe79SDavid van Moolenbroek orc = CONFREJ; /* Reject CI */
938*5d5fbe79SDavid van Moolenbroek break;
939*5d5fbe79SDavid van Moolenbroek }
940*5d5fbe79SDavid van Moolenbroek
941*5d5fbe79SDavid van Moolenbroek /*
942*5d5fbe79SDavid van Moolenbroek * If he has no interface identifier, or if we both have same
943*5d5fbe79SDavid van Moolenbroek * identifier then NAK it with new idea.
944*5d5fbe79SDavid van Moolenbroek * In particular, if we don't know his identifier, but he does,
945*5d5fbe79SDavid van Moolenbroek * then accept it.
946*5d5fbe79SDavid van Moolenbroek */
947*5d5fbe79SDavid van Moolenbroek eui64_get(ifaceid, p);
948*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid)));
949*5d5fbe79SDavid van Moolenbroek if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) {
950*5d5fbe79SDavid van Moolenbroek orc = CONFREJ; /* Reject CI */
951*5d5fbe79SDavid van Moolenbroek break;
952*5d5fbe79SDavid van Moolenbroek }
953*5d5fbe79SDavid van Moolenbroek if (!eui64_iszero(wo->hisid) &&
954*5d5fbe79SDavid van Moolenbroek !eui64_equals(ifaceid, wo->hisid) &&
955*5d5fbe79SDavid van Moolenbroek eui64_iszero(go->hisid)) {
956*5d5fbe79SDavid van Moolenbroek
957*5d5fbe79SDavid van Moolenbroek orc = CONFNAK;
958*5d5fbe79SDavid van Moolenbroek ifaceid = wo->hisid;
959*5d5fbe79SDavid van Moolenbroek go->hisid = ifaceid;
960*5d5fbe79SDavid van Moolenbroek DECPTR(sizeof(ifaceid), p);
961*5d5fbe79SDavid van Moolenbroek eui64_put(ifaceid, p);
962*5d5fbe79SDavid van Moolenbroek } else
963*5d5fbe79SDavid van Moolenbroek if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) {
964*5d5fbe79SDavid van Moolenbroek orc = CONFNAK;
965*5d5fbe79SDavid van Moolenbroek if (eui64_iszero(go->hisid)) /* first time, try option */
966*5d5fbe79SDavid van Moolenbroek ifaceid = wo->hisid;
967*5d5fbe79SDavid van Moolenbroek while (eui64_iszero(ifaceid) ||
968*5d5fbe79SDavid van Moolenbroek eui64_equals(ifaceid, go->ourid)) /* bad luck */
969*5d5fbe79SDavid van Moolenbroek eui64_magic(ifaceid);
970*5d5fbe79SDavid van Moolenbroek go->hisid = ifaceid;
971*5d5fbe79SDavid van Moolenbroek DECPTR(sizeof(ifaceid), p);
972*5d5fbe79SDavid van Moolenbroek eui64_put(ifaceid, p);
973*5d5fbe79SDavid van Moolenbroek }
974*5d5fbe79SDavid van Moolenbroek
975*5d5fbe79SDavid van Moolenbroek ho->neg_ifaceid = 1;
976*5d5fbe79SDavid van Moolenbroek ho->hisid = ifaceid;
977*5d5fbe79SDavid van Moolenbroek break;
978*5d5fbe79SDavid van Moolenbroek
979*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
980*5d5fbe79SDavid van Moolenbroek case CI_COMPRESSTYPE:
981*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE "));
982*5d5fbe79SDavid van Moolenbroek if (!ao->neg_vj ||
983*5d5fbe79SDavid van Moolenbroek (cilen != CILEN_COMPRESS)) {
984*5d5fbe79SDavid van Moolenbroek orc = CONFREJ;
985*5d5fbe79SDavid van Moolenbroek break;
986*5d5fbe79SDavid van Moolenbroek }
987*5d5fbe79SDavid van Moolenbroek GETSHORT(cishort, p);
988*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("(%d)", cishort));
989*5d5fbe79SDavid van Moolenbroek
990*5d5fbe79SDavid van Moolenbroek if (!(cishort == IPV6CP_COMP)) {
991*5d5fbe79SDavid van Moolenbroek orc = CONFREJ;
992*5d5fbe79SDavid van Moolenbroek break;
993*5d5fbe79SDavid van Moolenbroek }
994*5d5fbe79SDavid van Moolenbroek
995*5d5fbe79SDavid van Moolenbroek ho->neg_vj = 1;
996*5d5fbe79SDavid van Moolenbroek ho->vj_protocol = cishort;
997*5d5fbe79SDavid van Moolenbroek break;
998*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
999*5d5fbe79SDavid van Moolenbroek
1000*5d5fbe79SDavid van Moolenbroek default:
1001*5d5fbe79SDavid van Moolenbroek orc = CONFREJ;
1002*5d5fbe79SDavid van Moolenbroek break;
1003*5d5fbe79SDavid van Moolenbroek }
1004*5d5fbe79SDavid van Moolenbroek
1005*5d5fbe79SDavid van Moolenbroek endswitch:
1006*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG((" (%s)\n", CODENAME(orc)));
1007*5d5fbe79SDavid van Moolenbroek
1008*5d5fbe79SDavid van Moolenbroek if (orc == CONFACK && /* Good CI */
1009*5d5fbe79SDavid van Moolenbroek rc != CONFACK) /* but prior CI wasnt? */
1010*5d5fbe79SDavid van Moolenbroek continue; /* Don't send this one */
1011*5d5fbe79SDavid van Moolenbroek
1012*5d5fbe79SDavid van Moolenbroek if (orc == CONFNAK) { /* Nak this CI? */
1013*5d5fbe79SDavid van Moolenbroek if (reject_if_disagree) /* Getting fed up with sending NAKs? */
1014*5d5fbe79SDavid van Moolenbroek orc = CONFREJ; /* Get tough if so */
1015*5d5fbe79SDavid van Moolenbroek else {
1016*5d5fbe79SDavid van Moolenbroek if (rc == CONFREJ) /* Rejecting prior CI? */
1017*5d5fbe79SDavid van Moolenbroek continue; /* Don't send this one */
1018*5d5fbe79SDavid van Moolenbroek if (rc == CONFACK) { /* Ack'd all prior CIs? */
1019*5d5fbe79SDavid van Moolenbroek rc = CONFNAK; /* Not anymore... */
1020*5d5fbe79SDavid van Moolenbroek ucp = inp; /* Backup */
1021*5d5fbe79SDavid van Moolenbroek }
1022*5d5fbe79SDavid van Moolenbroek }
1023*5d5fbe79SDavid van Moolenbroek }
1024*5d5fbe79SDavid van Moolenbroek
1025*5d5fbe79SDavid van Moolenbroek if (orc == CONFREJ && /* Reject this CI */
1026*5d5fbe79SDavid van Moolenbroek rc != CONFREJ) { /* but no prior ones? */
1027*5d5fbe79SDavid van Moolenbroek rc = CONFREJ;
1028*5d5fbe79SDavid van Moolenbroek ucp = inp; /* Backup */
1029*5d5fbe79SDavid van Moolenbroek }
1030*5d5fbe79SDavid van Moolenbroek
1031*5d5fbe79SDavid van Moolenbroek /* Need to move CI? */
1032*5d5fbe79SDavid van Moolenbroek if (ucp != cip)
1033*5d5fbe79SDavid van Moolenbroek MEMCPY(ucp, cip, cilen); /* Move it */
1034*5d5fbe79SDavid van Moolenbroek
1035*5d5fbe79SDavid van Moolenbroek /* Update output pointer */
1036*5d5fbe79SDavid van Moolenbroek INCPTR(cilen, ucp);
1037*5d5fbe79SDavid van Moolenbroek }
1038*5d5fbe79SDavid van Moolenbroek
1039*5d5fbe79SDavid van Moolenbroek /*
1040*5d5fbe79SDavid van Moolenbroek * If we aren't rejecting this packet, and we want to negotiate
1041*5d5fbe79SDavid van Moolenbroek * their identifier and they didn't send their identifier, then we
1042*5d5fbe79SDavid van Moolenbroek * send a NAK with a CI_IFACEID option appended. We assume the
1043*5d5fbe79SDavid van Moolenbroek * input buffer is long enough that we can append the extra
1044*5d5fbe79SDavid van Moolenbroek * option safely.
1045*5d5fbe79SDavid van Moolenbroek */
1046*5d5fbe79SDavid van Moolenbroek if (rc != CONFREJ && !ho->neg_ifaceid &&
1047*5d5fbe79SDavid van Moolenbroek wo->req_ifaceid && !reject_if_disagree) {
1048*5d5fbe79SDavid van Moolenbroek if (rc == CONFACK) {
1049*5d5fbe79SDavid van Moolenbroek rc = CONFNAK;
1050*5d5fbe79SDavid van Moolenbroek ucp = inp; /* reset pointer */
1051*5d5fbe79SDavid van Moolenbroek wo->req_ifaceid = 0; /* don't ask again */
1052*5d5fbe79SDavid van Moolenbroek }
1053*5d5fbe79SDavid van Moolenbroek PUTCHAR(CI_IFACEID, ucp);
1054*5d5fbe79SDavid van Moolenbroek PUTCHAR(CILEN_IFACEID, ucp);
1055*5d5fbe79SDavid van Moolenbroek eui64_put(wo->hisid, ucp);
1056*5d5fbe79SDavid van Moolenbroek }
1057*5d5fbe79SDavid van Moolenbroek
1058*5d5fbe79SDavid van Moolenbroek *len = ucp - inp; /* Compute output length */
1059*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc)));
1060*5d5fbe79SDavid van Moolenbroek return (rc); /* Return final code */
1061*5d5fbe79SDavid van Moolenbroek }
1062*5d5fbe79SDavid van Moolenbroek
1063*5d5fbe79SDavid van Moolenbroek #if PPP_OPTIONS
1064*5d5fbe79SDavid van Moolenbroek /*
1065*5d5fbe79SDavid van Moolenbroek * ipv6_check_options - check that any IP-related options are OK,
1066*5d5fbe79SDavid van Moolenbroek * and assign appropriate defaults.
1067*5d5fbe79SDavid van Moolenbroek */
1068*5d5fbe79SDavid van Moolenbroek static void ipv6_check_options() {
1069*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &ipv6cp_wantoptions[0];
1070*5d5fbe79SDavid van Moolenbroek
1071*5d5fbe79SDavid van Moolenbroek if (!ipv6cp_protent.enabled_flag)
1072*5d5fbe79SDavid van Moolenbroek return;
1073*5d5fbe79SDavid van Moolenbroek
1074*5d5fbe79SDavid van Moolenbroek /*
1075*5d5fbe79SDavid van Moolenbroek * Persistent link-local id is only used when user has not explicitly
1076*5d5fbe79SDavid van Moolenbroek * configure/hard-code the id
1077*5d5fbe79SDavid van Moolenbroek */
1078*5d5fbe79SDavid van Moolenbroek if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) {
1079*5d5fbe79SDavid van Moolenbroek
1080*5d5fbe79SDavid van Moolenbroek /*
1081*5d5fbe79SDavid van Moolenbroek * On systems where there are no Ethernet interfaces used, there
1082*5d5fbe79SDavid van Moolenbroek * may be other ways to obtain a persistent id. Right now, it
1083*5d5fbe79SDavid van Moolenbroek * will fall back to using magic [see eui64_magic] below when
1084*5d5fbe79SDavid van Moolenbroek * an EUI-48 from MAC address can't be obtained. Other possibilities
1085*5d5fbe79SDavid van Moolenbroek * include obtaining EEPROM serial numbers, or some other unique
1086*5d5fbe79SDavid van Moolenbroek * yet persistent number. On Sparc platforms, this is possible,
1087*5d5fbe79SDavid van Moolenbroek * but too bad there's no standards yet for x86 machines.
1088*5d5fbe79SDavid van Moolenbroek */
1089*5d5fbe79SDavid van Moolenbroek if (ether_to_eui64(&wo->ourid)) {
1090*5d5fbe79SDavid van Moolenbroek wo->opt_local = 1;
1091*5d5fbe79SDavid van Moolenbroek }
1092*5d5fbe79SDavid van Moolenbroek }
1093*5d5fbe79SDavid van Moolenbroek
1094*5d5fbe79SDavid van Moolenbroek if (!wo->opt_local) { /* init interface identifier */
1095*5d5fbe79SDavid van Moolenbroek if (wo->use_ip && eui64_iszero(wo->ourid)) {
1096*5d5fbe79SDavid van Moolenbroek eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr));
1097*5d5fbe79SDavid van Moolenbroek if (!eui64_iszero(wo->ourid))
1098*5d5fbe79SDavid van Moolenbroek wo->opt_local = 1;
1099*5d5fbe79SDavid van Moolenbroek }
1100*5d5fbe79SDavid van Moolenbroek
1101*5d5fbe79SDavid van Moolenbroek while (eui64_iszero(wo->ourid))
1102*5d5fbe79SDavid van Moolenbroek eui64_magic(wo->ourid);
1103*5d5fbe79SDavid van Moolenbroek }
1104*5d5fbe79SDavid van Moolenbroek
1105*5d5fbe79SDavid van Moolenbroek if (!wo->opt_remote) {
1106*5d5fbe79SDavid van Moolenbroek if (wo->use_ip && eui64_iszero(wo->hisid)) {
1107*5d5fbe79SDavid van Moolenbroek eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr));
1108*5d5fbe79SDavid van Moolenbroek if (!eui64_iszero(wo->hisid))
1109*5d5fbe79SDavid van Moolenbroek wo->opt_remote = 1;
1110*5d5fbe79SDavid van Moolenbroek }
1111*5d5fbe79SDavid van Moolenbroek }
1112*5d5fbe79SDavid van Moolenbroek
1113*5d5fbe79SDavid van Moolenbroek if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) {
1114*5d5fbe79SDavid van Moolenbroek option_error("local/remote LL address required for demand-dialling\n");
1115*5d5fbe79SDavid van Moolenbroek exit(1);
1116*5d5fbe79SDavid van Moolenbroek }
1117*5d5fbe79SDavid van Moolenbroek }
1118*5d5fbe79SDavid van Moolenbroek #endif /* PPP_OPTIONS */
1119*5d5fbe79SDavid van Moolenbroek
1120*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
1121*5d5fbe79SDavid van Moolenbroek /*
1122*5d5fbe79SDavid van Moolenbroek * ipv6_demand_conf - configure the interface as though
1123*5d5fbe79SDavid van Moolenbroek * IPV6CP were up, for use with dial-on-demand.
1124*5d5fbe79SDavid van Moolenbroek */
1125*5d5fbe79SDavid van Moolenbroek static int ipv6_demand_conf(int u) {
1126*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &ipv6cp_wantoptions[u];
1127*5d5fbe79SDavid van Moolenbroek
1128*5d5fbe79SDavid van Moolenbroek if (!sif6up(u))
1129*5d5fbe79SDavid van Moolenbroek return 0;
1130*5d5fbe79SDavid van Moolenbroek
1131*5d5fbe79SDavid van Moolenbroek if (!sif6addr(u, wo->ourid, wo->hisid))
1132*5d5fbe79SDavid van Moolenbroek return 0;
1133*5d5fbe79SDavid van Moolenbroek
1134*5d5fbe79SDavid van Moolenbroek if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
1135*5d5fbe79SDavid van Moolenbroek return 0;
1136*5d5fbe79SDavid van Moolenbroek
1137*5d5fbe79SDavid van Moolenbroek ppp_notice("ipv6_demand_conf");
1138*5d5fbe79SDavid van Moolenbroek ppp_notice("local LL address %s", llv6_ntoa(wo->ourid));
1139*5d5fbe79SDavid van Moolenbroek ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid));
1140*5d5fbe79SDavid van Moolenbroek
1141*5d5fbe79SDavid van Moolenbroek return 1;
1142*5d5fbe79SDavid van Moolenbroek }
1143*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
1144*5d5fbe79SDavid van Moolenbroek
1145*5d5fbe79SDavid van Moolenbroek
1146*5d5fbe79SDavid van Moolenbroek /*
1147*5d5fbe79SDavid van Moolenbroek * ipv6cp_up - IPV6CP has come UP.
1148*5d5fbe79SDavid van Moolenbroek *
1149*5d5fbe79SDavid van Moolenbroek * Configure the IPv6 network interface appropriately and bring it up.
1150*5d5fbe79SDavid van Moolenbroek */
1151*5d5fbe79SDavid van Moolenbroek static void ipv6cp_up(fsm *f) {
1152*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
1153*5d5fbe79SDavid van Moolenbroek ipv6cp_options *wo = &pcb->ipv6cp_wantoptions;
1154*5d5fbe79SDavid van Moolenbroek ipv6cp_options *ho = &pcb->ipv6cp_hisoptions;
1155*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
1156*5d5fbe79SDavid van Moolenbroek
1157*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp: up"));
1158*5d5fbe79SDavid van Moolenbroek
1159*5d5fbe79SDavid van Moolenbroek /*
1160*5d5fbe79SDavid van Moolenbroek * We must have a non-zero LL address for both ends of the link.
1161*5d5fbe79SDavid van Moolenbroek */
1162*5d5fbe79SDavid van Moolenbroek if (!ho->neg_ifaceid)
1163*5d5fbe79SDavid van Moolenbroek ho->hisid = wo->hisid;
1164*5d5fbe79SDavid van Moolenbroek
1165*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
1166*5d5fbe79SDavid van Moolenbroek if(!no_ifaceid_neg) {
1167*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
1168*5d5fbe79SDavid van Moolenbroek if (eui64_iszero(ho->hisid)) {
1169*5d5fbe79SDavid van Moolenbroek ppp_error("Could not determine remote LL address");
1170*5d5fbe79SDavid van Moolenbroek ipv6cp_close(f->pcb, "Could not determine remote LL address");
1171*5d5fbe79SDavid van Moolenbroek return;
1172*5d5fbe79SDavid van Moolenbroek }
1173*5d5fbe79SDavid van Moolenbroek if (eui64_iszero(go->ourid)) {
1174*5d5fbe79SDavid van Moolenbroek ppp_error("Could not determine local LL address");
1175*5d5fbe79SDavid van Moolenbroek ipv6cp_close(f->pcb, "Could not determine local LL address");
1176*5d5fbe79SDavid van Moolenbroek return;
1177*5d5fbe79SDavid van Moolenbroek }
1178*5d5fbe79SDavid van Moolenbroek if (eui64_equals(go->ourid, ho->hisid)) {
1179*5d5fbe79SDavid van Moolenbroek ppp_error("local and remote LL addresses are equal");
1180*5d5fbe79SDavid van Moolenbroek ipv6cp_close(f->pcb, "local and remote LL addresses are equal");
1181*5d5fbe79SDavid van Moolenbroek return;
1182*5d5fbe79SDavid van Moolenbroek }
1183*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
1184*5d5fbe79SDavid van Moolenbroek }
1185*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
1186*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
1187*5d5fbe79SDavid van Moolenbroek script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0);
1188*5d5fbe79SDavid van Moolenbroek script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0);
1189*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
1190*5d5fbe79SDavid van Moolenbroek
1191*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
1192*5d5fbe79SDavid van Moolenbroek /* set tcp compression */
1193*5d5fbe79SDavid van Moolenbroek sif6comp(f->unit, ho->neg_vj);
1194*5d5fbe79SDavid van Moolenbroek #endif
1195*5d5fbe79SDavid van Moolenbroek
1196*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
1197*5d5fbe79SDavid van Moolenbroek /*
1198*5d5fbe79SDavid van Moolenbroek * If we are doing dial-on-demand, the interface is already
1199*5d5fbe79SDavid van Moolenbroek * configured, so we put out any saved-up packets, then set the
1200*5d5fbe79SDavid van Moolenbroek * interface to pass IPv6 packets.
1201*5d5fbe79SDavid van Moolenbroek */
1202*5d5fbe79SDavid van Moolenbroek if (demand) {
1203*5d5fbe79SDavid van Moolenbroek if (! eui64_equals(go->ourid, wo->ourid) ||
1204*5d5fbe79SDavid van Moolenbroek ! eui64_equals(ho->hisid, wo->hisid)) {
1205*5d5fbe79SDavid van Moolenbroek if (! eui64_equals(go->ourid, wo->ourid))
1206*5d5fbe79SDavid van Moolenbroek warn("Local LL address changed to %s",
1207*5d5fbe79SDavid van Moolenbroek llv6_ntoa(go->ourid));
1208*5d5fbe79SDavid van Moolenbroek if (! eui64_equals(ho->hisid, wo->hisid))
1209*5d5fbe79SDavid van Moolenbroek warn("Remote LL address changed to %s",
1210*5d5fbe79SDavid van Moolenbroek llv6_ntoa(ho->hisid));
1211*5d5fbe79SDavid van Moolenbroek ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid);
1212*5d5fbe79SDavid van Moolenbroek
1213*5d5fbe79SDavid van Moolenbroek /* Set the interface to the new addresses */
1214*5d5fbe79SDavid van Moolenbroek if (!sif6addr(f->pcb, go->ourid, ho->hisid)) {
1215*5d5fbe79SDavid van Moolenbroek if (debug)
1216*5d5fbe79SDavid van Moolenbroek warn("sif6addr failed");
1217*5d5fbe79SDavid van Moolenbroek ipv6cp_close(f->unit, "Interface configuration failed");
1218*5d5fbe79SDavid van Moolenbroek return;
1219*5d5fbe79SDavid van Moolenbroek }
1220*5d5fbe79SDavid van Moolenbroek
1221*5d5fbe79SDavid van Moolenbroek }
1222*5d5fbe79SDavid van Moolenbroek demand_rexmit(PPP_IPV6);
1223*5d5fbe79SDavid van Moolenbroek sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
1224*5d5fbe79SDavid van Moolenbroek
1225*5d5fbe79SDavid van Moolenbroek } else
1226*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
1227*5d5fbe79SDavid van Moolenbroek {
1228*5d5fbe79SDavid van Moolenbroek /*
1229*5d5fbe79SDavid van Moolenbroek * Set LL addresses
1230*5d5fbe79SDavid van Moolenbroek */
1231*5d5fbe79SDavid van Moolenbroek if (!sif6addr(f->pcb, go->ourid, ho->hisid)) {
1232*5d5fbe79SDavid van Moolenbroek PPPDEBUG(LOG_DEBUG, ("sif6addr failed"));
1233*5d5fbe79SDavid van Moolenbroek ipv6cp_close(f->pcb, "Interface configuration failed");
1234*5d5fbe79SDavid van Moolenbroek return;
1235*5d5fbe79SDavid van Moolenbroek }
1236*5d5fbe79SDavid van Moolenbroek
1237*5d5fbe79SDavid van Moolenbroek /* bring the interface up for IPv6 */
1238*5d5fbe79SDavid van Moolenbroek if (!sif6up(f->pcb)) {
1239*5d5fbe79SDavid van Moolenbroek PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)"));
1240*5d5fbe79SDavid van Moolenbroek ipv6cp_close(f->pcb, "Interface configuration failed");
1241*5d5fbe79SDavid van Moolenbroek return;
1242*5d5fbe79SDavid van Moolenbroek }
1243*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
1244*5d5fbe79SDavid van Moolenbroek sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS);
1245*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
1246*5d5fbe79SDavid van Moolenbroek
1247*5d5fbe79SDavid van Moolenbroek ppp_notice("local LL address %s", llv6_ntoa(go->ourid));
1248*5d5fbe79SDavid van Moolenbroek ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid));
1249*5d5fbe79SDavid van Moolenbroek }
1250*5d5fbe79SDavid van Moolenbroek
1251*5d5fbe79SDavid van Moolenbroek np_up(f->pcb, PPP_IPV6);
1252*5d5fbe79SDavid van Moolenbroek pcb->ipv6cp_is_up = 1;
1253*5d5fbe79SDavid van Moolenbroek
1254*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
1255*5d5fbe79SDavid van Moolenbroek /*
1256*5d5fbe79SDavid van Moolenbroek * Execute the ipv6-up script, like this:
1257*5d5fbe79SDavid van Moolenbroek * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL
1258*5d5fbe79SDavid van Moolenbroek */
1259*5d5fbe79SDavid van Moolenbroek if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) {
1260*5d5fbe79SDavid van Moolenbroek ipv6cp_script_state = s_up;
1261*5d5fbe79SDavid van Moolenbroek ipv6cp_script(_PATH_IPV6UP);
1262*5d5fbe79SDavid van Moolenbroek }
1263*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
1264*5d5fbe79SDavid van Moolenbroek }
1265*5d5fbe79SDavid van Moolenbroek
1266*5d5fbe79SDavid van Moolenbroek
1267*5d5fbe79SDavid van Moolenbroek /*
1268*5d5fbe79SDavid van Moolenbroek * ipv6cp_down - IPV6CP has gone DOWN.
1269*5d5fbe79SDavid van Moolenbroek *
1270*5d5fbe79SDavid van Moolenbroek * Take the IPv6 network interface down, clear its addresses
1271*5d5fbe79SDavid van Moolenbroek * and delete routes through it.
1272*5d5fbe79SDavid van Moolenbroek */
1273*5d5fbe79SDavid van Moolenbroek static void ipv6cp_down(fsm *f) {
1274*5d5fbe79SDavid van Moolenbroek ppp_pcb *pcb = f->pcb;
1275*5d5fbe79SDavid van Moolenbroek ipv6cp_options *go = &pcb->ipv6cp_gotoptions;
1276*5d5fbe79SDavid van Moolenbroek ipv6cp_options *ho = &pcb->ipv6cp_hisoptions;
1277*5d5fbe79SDavid van Moolenbroek
1278*5d5fbe79SDavid van Moolenbroek IPV6CPDEBUG(("ipv6cp: down"));
1279*5d5fbe79SDavid van Moolenbroek #if PPP_STATS_SUPPORT
1280*5d5fbe79SDavid van Moolenbroek update_link_stats(f->unit);
1281*5d5fbe79SDavid van Moolenbroek #endif /* PPP_STATS_SUPPORT */
1282*5d5fbe79SDavid van Moolenbroek if (pcb->ipv6cp_is_up) {
1283*5d5fbe79SDavid van Moolenbroek pcb->ipv6cp_is_up = 0;
1284*5d5fbe79SDavid van Moolenbroek np_down(f->pcb, PPP_IPV6);
1285*5d5fbe79SDavid van Moolenbroek }
1286*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
1287*5d5fbe79SDavid van Moolenbroek sif6comp(f->unit, 0);
1288*5d5fbe79SDavid van Moolenbroek #endif
1289*5d5fbe79SDavid van Moolenbroek
1290*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
1291*5d5fbe79SDavid van Moolenbroek /*
1292*5d5fbe79SDavid van Moolenbroek * If we are doing dial-on-demand, set the interface
1293*5d5fbe79SDavid van Moolenbroek * to queue up outgoing packets (for now).
1294*5d5fbe79SDavid van Moolenbroek */
1295*5d5fbe79SDavid van Moolenbroek if (demand) {
1296*5d5fbe79SDavid van Moolenbroek sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE);
1297*5d5fbe79SDavid van Moolenbroek } else
1298*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
1299*5d5fbe79SDavid van Moolenbroek {
1300*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
1301*5d5fbe79SDavid van Moolenbroek sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP);
1302*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
1303*5d5fbe79SDavid van Moolenbroek ipv6cp_clear_addrs(f->pcb,
1304*5d5fbe79SDavid van Moolenbroek go->ourid,
1305*5d5fbe79SDavid van Moolenbroek ho->hisid);
1306*5d5fbe79SDavid van Moolenbroek sif6down(f->pcb);
1307*5d5fbe79SDavid van Moolenbroek }
1308*5d5fbe79SDavid van Moolenbroek
1309*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
1310*5d5fbe79SDavid van Moolenbroek /* Execute the ipv6-down script */
1311*5d5fbe79SDavid van Moolenbroek if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) {
1312*5d5fbe79SDavid van Moolenbroek ipv6cp_script_state = s_down;
1313*5d5fbe79SDavid van Moolenbroek ipv6cp_script(_PATH_IPV6DOWN);
1314*5d5fbe79SDavid van Moolenbroek }
1315*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
1316*5d5fbe79SDavid van Moolenbroek }
1317*5d5fbe79SDavid van Moolenbroek
1318*5d5fbe79SDavid van Moolenbroek
1319*5d5fbe79SDavid van Moolenbroek /*
1320*5d5fbe79SDavid van Moolenbroek * ipv6cp_clear_addrs() - clear the interface addresses, routes,
1321*5d5fbe79SDavid van Moolenbroek * proxy neighbour discovery entries, etc.
1322*5d5fbe79SDavid van Moolenbroek */
1323*5d5fbe79SDavid van Moolenbroek static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) {
1324*5d5fbe79SDavid van Moolenbroek cif6addr(pcb, ourid, hisid);
1325*5d5fbe79SDavid van Moolenbroek }
1326*5d5fbe79SDavid van Moolenbroek
1327*5d5fbe79SDavid van Moolenbroek
1328*5d5fbe79SDavid van Moolenbroek /*
1329*5d5fbe79SDavid van Moolenbroek * ipv6cp_finished - possibly shut down the lower layers.
1330*5d5fbe79SDavid van Moolenbroek */
1331*5d5fbe79SDavid van Moolenbroek static void ipv6cp_finished(fsm *f) {
1332*5d5fbe79SDavid van Moolenbroek np_finished(f->pcb, PPP_IPV6);
1333*5d5fbe79SDavid van Moolenbroek }
1334*5d5fbe79SDavid van Moolenbroek
1335*5d5fbe79SDavid van Moolenbroek
1336*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
1337*5d5fbe79SDavid van Moolenbroek /*
1338*5d5fbe79SDavid van Moolenbroek * ipv6cp_script_done - called when the ipv6-up or ipv6-down script
1339*5d5fbe79SDavid van Moolenbroek * has finished.
1340*5d5fbe79SDavid van Moolenbroek */
1341*5d5fbe79SDavid van Moolenbroek static void
1342*5d5fbe79SDavid van Moolenbroek ipv6cp_script_done(arg)
1343*5d5fbe79SDavid van Moolenbroek void *arg;
1344*5d5fbe79SDavid van Moolenbroek {
1345*5d5fbe79SDavid van Moolenbroek ipv6cp_script_pid = 0;
1346*5d5fbe79SDavid van Moolenbroek switch (ipv6cp_script_state) {
1347*5d5fbe79SDavid van Moolenbroek case s_up:
1348*5d5fbe79SDavid van Moolenbroek if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) {
1349*5d5fbe79SDavid van Moolenbroek ipv6cp_script_state = s_down;
1350*5d5fbe79SDavid van Moolenbroek ipv6cp_script(_PATH_IPV6DOWN);
1351*5d5fbe79SDavid van Moolenbroek }
1352*5d5fbe79SDavid van Moolenbroek break;
1353*5d5fbe79SDavid van Moolenbroek case s_down:
1354*5d5fbe79SDavid van Moolenbroek if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) {
1355*5d5fbe79SDavid van Moolenbroek ipv6cp_script_state = s_up;
1356*5d5fbe79SDavid van Moolenbroek ipv6cp_script(_PATH_IPV6UP);
1357*5d5fbe79SDavid van Moolenbroek }
1358*5d5fbe79SDavid van Moolenbroek break;
1359*5d5fbe79SDavid van Moolenbroek }
1360*5d5fbe79SDavid van Moolenbroek }
1361*5d5fbe79SDavid van Moolenbroek
1362*5d5fbe79SDavid van Moolenbroek
1363*5d5fbe79SDavid van Moolenbroek /*
1364*5d5fbe79SDavid van Moolenbroek * ipv6cp_script - Execute a script with arguments
1365*5d5fbe79SDavid van Moolenbroek * interface-name tty-name speed local-LL remote-LL.
1366*5d5fbe79SDavid van Moolenbroek */
1367*5d5fbe79SDavid van Moolenbroek static void
1368*5d5fbe79SDavid van Moolenbroek ipv6cp_script(script)
1369*5d5fbe79SDavid van Moolenbroek char *script;
1370*5d5fbe79SDavid van Moolenbroek {
1371*5d5fbe79SDavid van Moolenbroek char strspeed[32], strlocal[32], strremote[32];
1372*5d5fbe79SDavid van Moolenbroek char *argv[8];
1373*5d5fbe79SDavid van Moolenbroek
1374*5d5fbe79SDavid van Moolenbroek sprintf(strspeed, "%d", baud_rate);
1375*5d5fbe79SDavid van Moolenbroek strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid));
1376*5d5fbe79SDavid van Moolenbroek strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid));
1377*5d5fbe79SDavid van Moolenbroek
1378*5d5fbe79SDavid van Moolenbroek argv[0] = script;
1379*5d5fbe79SDavid van Moolenbroek argv[1] = ifname;
1380*5d5fbe79SDavid van Moolenbroek argv[2] = devnam;
1381*5d5fbe79SDavid van Moolenbroek argv[3] = strspeed;
1382*5d5fbe79SDavid van Moolenbroek argv[4] = strlocal;
1383*5d5fbe79SDavid van Moolenbroek argv[5] = strremote;
1384*5d5fbe79SDavid van Moolenbroek argv[6] = ipparam;
1385*5d5fbe79SDavid van Moolenbroek argv[7] = NULL;
1386*5d5fbe79SDavid van Moolenbroek
1387*5d5fbe79SDavid van Moolenbroek ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done,
1388*5d5fbe79SDavid van Moolenbroek NULL, 0);
1389*5d5fbe79SDavid van Moolenbroek }
1390*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
1391*5d5fbe79SDavid van Moolenbroek
1392*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
1393*5d5fbe79SDavid van Moolenbroek /*
1394*5d5fbe79SDavid van Moolenbroek * ipv6cp_printpkt - print the contents of an IPV6CP packet.
1395*5d5fbe79SDavid van Moolenbroek */
1396*5d5fbe79SDavid van Moolenbroek static const char* const ipv6cp_codenames[] = {
1397*5d5fbe79SDavid van Moolenbroek "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1398*5d5fbe79SDavid van Moolenbroek "TermReq", "TermAck", "CodeRej"
1399*5d5fbe79SDavid van Moolenbroek };
1400*5d5fbe79SDavid van Moolenbroek
1401*5d5fbe79SDavid van Moolenbroek static int ipv6cp_printpkt(const u_char *p, int plen,
1402*5d5fbe79SDavid van Moolenbroek void (*printer)(void *, const char *, ...), void *arg) {
1403*5d5fbe79SDavid van Moolenbroek int code, id, len, olen;
1404*5d5fbe79SDavid van Moolenbroek const u_char *pstart, *optend;
1405*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
1406*5d5fbe79SDavid van Moolenbroek u_short cishort;
1407*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
1408*5d5fbe79SDavid van Moolenbroek eui64_t ifaceid;
1409*5d5fbe79SDavid van Moolenbroek
1410*5d5fbe79SDavid van Moolenbroek if (plen < HEADERLEN)
1411*5d5fbe79SDavid van Moolenbroek return 0;
1412*5d5fbe79SDavid van Moolenbroek pstart = p;
1413*5d5fbe79SDavid van Moolenbroek GETCHAR(code, p);
1414*5d5fbe79SDavid van Moolenbroek GETCHAR(id, p);
1415*5d5fbe79SDavid van Moolenbroek GETSHORT(len, p);
1416*5d5fbe79SDavid van Moolenbroek if (len < HEADERLEN || len > plen)
1417*5d5fbe79SDavid van Moolenbroek return 0;
1418*5d5fbe79SDavid van Moolenbroek
1419*5d5fbe79SDavid van Moolenbroek if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipv6cp_codenames))
1420*5d5fbe79SDavid van Moolenbroek printer(arg, " %s", ipv6cp_codenames[code-1]);
1421*5d5fbe79SDavid van Moolenbroek else
1422*5d5fbe79SDavid van Moolenbroek printer(arg, " code=0x%x", code);
1423*5d5fbe79SDavid van Moolenbroek printer(arg, " id=0x%x", id);
1424*5d5fbe79SDavid van Moolenbroek len -= HEADERLEN;
1425*5d5fbe79SDavid van Moolenbroek switch (code) {
1426*5d5fbe79SDavid van Moolenbroek case CONFREQ:
1427*5d5fbe79SDavid van Moolenbroek case CONFACK:
1428*5d5fbe79SDavid van Moolenbroek case CONFNAK:
1429*5d5fbe79SDavid van Moolenbroek case CONFREJ:
1430*5d5fbe79SDavid van Moolenbroek /* print option list */
1431*5d5fbe79SDavid van Moolenbroek while (len >= 2) {
1432*5d5fbe79SDavid van Moolenbroek GETCHAR(code, p);
1433*5d5fbe79SDavid van Moolenbroek GETCHAR(olen, p);
1434*5d5fbe79SDavid van Moolenbroek p -= 2;
1435*5d5fbe79SDavid van Moolenbroek if (olen < 2 || olen > len) {
1436*5d5fbe79SDavid van Moolenbroek break;
1437*5d5fbe79SDavid van Moolenbroek }
1438*5d5fbe79SDavid van Moolenbroek printer(arg, " <");
1439*5d5fbe79SDavid van Moolenbroek len -= olen;
1440*5d5fbe79SDavid van Moolenbroek optend = p + olen;
1441*5d5fbe79SDavid van Moolenbroek switch (code) {
1442*5d5fbe79SDavid van Moolenbroek #ifdef IPV6CP_COMP
1443*5d5fbe79SDavid van Moolenbroek case CI_COMPRESSTYPE:
1444*5d5fbe79SDavid van Moolenbroek if (olen >= CILEN_COMPRESS) {
1445*5d5fbe79SDavid van Moolenbroek p += 2;
1446*5d5fbe79SDavid van Moolenbroek GETSHORT(cishort, p);
1447*5d5fbe79SDavid van Moolenbroek printer(arg, "compress ");
1448*5d5fbe79SDavid van Moolenbroek printer(arg, "0x%x", cishort);
1449*5d5fbe79SDavid van Moolenbroek }
1450*5d5fbe79SDavid van Moolenbroek break;
1451*5d5fbe79SDavid van Moolenbroek #endif /* IPV6CP_COMP */
1452*5d5fbe79SDavid van Moolenbroek case CI_IFACEID:
1453*5d5fbe79SDavid van Moolenbroek if (olen == CILEN_IFACEID) {
1454*5d5fbe79SDavid van Moolenbroek p += 2;
1455*5d5fbe79SDavid van Moolenbroek eui64_get(ifaceid, p);
1456*5d5fbe79SDavid van Moolenbroek printer(arg, "addr %s", llv6_ntoa(ifaceid));
1457*5d5fbe79SDavid van Moolenbroek }
1458*5d5fbe79SDavid van Moolenbroek break;
1459*5d5fbe79SDavid van Moolenbroek default:
1460*5d5fbe79SDavid van Moolenbroek break;
1461*5d5fbe79SDavid van Moolenbroek }
1462*5d5fbe79SDavid van Moolenbroek while (p < optend) {
1463*5d5fbe79SDavid van Moolenbroek GETCHAR(code, p);
1464*5d5fbe79SDavid van Moolenbroek printer(arg, " %.2x", code);
1465*5d5fbe79SDavid van Moolenbroek }
1466*5d5fbe79SDavid van Moolenbroek printer(arg, ">");
1467*5d5fbe79SDavid van Moolenbroek }
1468*5d5fbe79SDavid van Moolenbroek break;
1469*5d5fbe79SDavid van Moolenbroek
1470*5d5fbe79SDavid van Moolenbroek case TERMACK:
1471*5d5fbe79SDavid van Moolenbroek case TERMREQ:
1472*5d5fbe79SDavid van Moolenbroek if (len > 0 && *p >= ' ' && *p < 0x7f) {
1473*5d5fbe79SDavid van Moolenbroek printer(arg, " ");
1474*5d5fbe79SDavid van Moolenbroek ppp_print_string(p, len, printer, arg);
1475*5d5fbe79SDavid van Moolenbroek p += len;
1476*5d5fbe79SDavid van Moolenbroek len = 0;
1477*5d5fbe79SDavid van Moolenbroek }
1478*5d5fbe79SDavid van Moolenbroek break;
1479*5d5fbe79SDavid van Moolenbroek default:
1480*5d5fbe79SDavid van Moolenbroek break;
1481*5d5fbe79SDavid van Moolenbroek }
1482*5d5fbe79SDavid van Moolenbroek
1483*5d5fbe79SDavid van Moolenbroek /* print the rest of the bytes in the packet */
1484*5d5fbe79SDavid van Moolenbroek for (; len > 0; --len) {
1485*5d5fbe79SDavid van Moolenbroek GETCHAR(code, p);
1486*5d5fbe79SDavid van Moolenbroek printer(arg, " %.2x", code);
1487*5d5fbe79SDavid van Moolenbroek }
1488*5d5fbe79SDavid van Moolenbroek
1489*5d5fbe79SDavid van Moolenbroek return p - pstart;
1490*5d5fbe79SDavid van Moolenbroek }
1491*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
1492*5d5fbe79SDavid van Moolenbroek
1493*5d5fbe79SDavid van Moolenbroek #if DEMAND_SUPPORT
1494*5d5fbe79SDavid van Moolenbroek /*
1495*5d5fbe79SDavid van Moolenbroek * ipv6_active_pkt - see if this IP packet is worth bringing the link up for.
1496*5d5fbe79SDavid van Moolenbroek * We don't bring the link up for IP fragments or for TCP FIN packets
1497*5d5fbe79SDavid van Moolenbroek * with no data.
1498*5d5fbe79SDavid van Moolenbroek */
1499*5d5fbe79SDavid van Moolenbroek #define IP6_HDRLEN 40 /* bytes */
1500*5d5fbe79SDavid van Moolenbroek #define IP6_NHDR_FRAG 44 /* fragment IPv6 header */
1501*5d5fbe79SDavid van Moolenbroek #define TCP_HDRLEN 20
1502*5d5fbe79SDavid van Moolenbroek #define TH_FIN 0x01
1503*5d5fbe79SDavid van Moolenbroek
1504*5d5fbe79SDavid van Moolenbroek /*
1505*5d5fbe79SDavid van Moolenbroek * We use these macros because the IP header may be at an odd address,
1506*5d5fbe79SDavid van Moolenbroek * and some compilers might use word loads to get th_off or ip_hl.
1507*5d5fbe79SDavid van Moolenbroek */
1508*5d5fbe79SDavid van Moolenbroek
1509*5d5fbe79SDavid van Moolenbroek #define get_ip6nh(x) (((unsigned char *)(x))[6])
1510*5d5fbe79SDavid van Moolenbroek #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
1511*5d5fbe79SDavid van Moolenbroek #define get_tcpflags(x) (((unsigned char *)(x))[13])
1512*5d5fbe79SDavid van Moolenbroek
1513*5d5fbe79SDavid van Moolenbroek static int ipv6_active_pkt(u_char *pkt, int len) {
1514*5d5fbe79SDavid van Moolenbroek u_char *tcp;
1515*5d5fbe79SDavid van Moolenbroek
1516*5d5fbe79SDavid van Moolenbroek len -= PPP_HDRLEN;
1517*5d5fbe79SDavid van Moolenbroek pkt += PPP_HDRLEN;
1518*5d5fbe79SDavid van Moolenbroek if (len < IP6_HDRLEN)
1519*5d5fbe79SDavid van Moolenbroek return 0;
1520*5d5fbe79SDavid van Moolenbroek if (get_ip6nh(pkt) == IP6_NHDR_FRAG)
1521*5d5fbe79SDavid van Moolenbroek return 0;
1522*5d5fbe79SDavid van Moolenbroek if (get_ip6nh(pkt) != IPPROTO_TCP)
1523*5d5fbe79SDavid van Moolenbroek return 1;
1524*5d5fbe79SDavid van Moolenbroek if (len < IP6_HDRLEN + TCP_HDRLEN)
1525*5d5fbe79SDavid van Moolenbroek return 0;
1526*5d5fbe79SDavid van Moolenbroek tcp = pkt + IP6_HDRLEN;
1527*5d5fbe79SDavid van Moolenbroek if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4)
1528*5d5fbe79SDavid van Moolenbroek return 0;
1529*5d5fbe79SDavid van Moolenbroek return 1;
1530*5d5fbe79SDavid van Moolenbroek }
1531*5d5fbe79SDavid van Moolenbroek #endif /* DEMAND_SUPPORT */
1532*5d5fbe79SDavid van Moolenbroek
1533*5d5fbe79SDavid van Moolenbroek #endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */
1534