17c478bd9Sstevel@tonic-gate /* 2f53eecf5SJames Carlson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*48bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved. 5*48bbca81SDaniel Hoffman * 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate ipv6cp.c - PPP IPV6 Control Protocol. 87c478bd9Sstevel@tonic-gate Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi> 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate Redistribution and use in source and binary forms are permitted 117c478bd9Sstevel@tonic-gate provided that the above copyright notice and this paragraph are 127c478bd9Sstevel@tonic-gate duplicated in all such forms. The name of the author may not be 137c478bd9Sstevel@tonic-gate used to endorse or promote products derived from this software 147c478bd9Sstevel@tonic-gate without specific prior written permission. 157c478bd9Sstevel@tonic-gate THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 167c478bd9Sstevel@tonic-gate IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 177c478bd9Sstevel@tonic-gate WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 187c478bd9Sstevel@tonic-gate */ 197c478bd9Sstevel@tonic-gate 207c478bd9Sstevel@tonic-gate /* Original version, based on RFC2023 : 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, 237c478bd9Sstevel@tonic-gate Alain.Durand@imag.fr, IMAG, 247c478bd9Sstevel@tonic-gate Jean-Luc.Richier@imag.fr, IMAG-LSR. 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, 277c478bd9Sstevel@tonic-gate Alain.Durand@imag.fr, IMAG, 287c478bd9Sstevel@tonic-gate Jean-Luc.Richier@imag.fr, IMAG-LSR. 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate Ce travail a �t� fait au sein du GIE DYADE (Groupement d'Int�r�t 317c478bd9Sstevel@tonic-gate �conomique ayant pour membres BULL S.A. et l'INRIA). 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate Ce logiciel informatique est disponible aux conditions 347c478bd9Sstevel@tonic-gate usuelles dans la recherche, c'est-�-dire qu'il peut 357c478bd9Sstevel@tonic-gate �tre utilis�, copi�, modifi�, distribu� � l'unique 367c478bd9Sstevel@tonic-gate condition que ce texte soit conserv� afin que 377c478bd9Sstevel@tonic-gate l'origine de ce logiciel soit reconnue. 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate Le nom de l'Institut National de Recherche en Informatique 407c478bd9Sstevel@tonic-gate et en Automatique (INRIA), de l'IMAG, ou d'une personne morale 417c478bd9Sstevel@tonic-gate ou physique ayant particip� � l'�laboration de ce logiciel ne peut 427c478bd9Sstevel@tonic-gate �tre utilis� sans son accord pr�alable explicite. 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate Ce logiciel est fourni tel quel sans aucune garantie, 457c478bd9Sstevel@tonic-gate support ou responsabilit� d'aucune sorte. 467c478bd9Sstevel@tonic-gate Ce logiciel est d�riv� de sources d'origine 477c478bd9Sstevel@tonic-gate "University of California at Berkeley" et 487c478bd9Sstevel@tonic-gate "Digital Equipment Corporation" couvertes par des copyrights. 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate L'Institut d'Informatique et de Math�matiques Appliqu�es de Grenoble (IMAG) 517c478bd9Sstevel@tonic-gate est une f�d�ration d'unit�s mixtes de recherche du CNRS, de l'Institut National 527c478bd9Sstevel@tonic-gate Polytechnique de Grenoble et de l'Universit� Joseph Fourier regroupant 537c478bd9Sstevel@tonic-gate sept laboratoires dont le laboratoire Logiciels, Syst�mes, R�seaux (LSR). 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate This work has been done in the context of GIE DYADE (joint R & D venture 567c478bd9Sstevel@tonic-gate between BULL S.A. and INRIA). 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate This software is available with usual "research" terms 59*48bbca81SDaniel Hoffman with the aim of retain credits of the software. 607c478bd9Sstevel@tonic-gate Permission to use, copy, modify and distribute this software for any 617c478bd9Sstevel@tonic-gate purpose and without fee is hereby granted, provided that the above 627c478bd9Sstevel@tonic-gate copyright notice and this permission notice appear in all copies, 637c478bd9Sstevel@tonic-gate and the name of INRIA, IMAG, or any contributor not be used in advertising 647c478bd9Sstevel@tonic-gate or publicity pertaining to this material without the prior explicit 657c478bd9Sstevel@tonic-gate permission. The software is provided "as is" without any 667c478bd9Sstevel@tonic-gate warranties, support or liabilities of any kind. 677c478bd9Sstevel@tonic-gate This software is derived from source code from 687c478bd9Sstevel@tonic-gate "University of California at Berkeley" and 697c478bd9Sstevel@tonic-gate "Digital Equipment Corporation" protected by copyrights. 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) 727c478bd9Sstevel@tonic-gate is a federation of seven research units funded by the CNRS, National 737c478bd9Sstevel@tonic-gate Polytechnic Institute of Grenoble and University Joseph Fourier. 747c478bd9Sstevel@tonic-gate The research unit in Software, Systems, Networks (LSR) is member of IMAG. 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Derived from : 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * 817c478bd9Sstevel@tonic-gate * ipcp.c - PPP IP Control Protocol. 827c478bd9Sstevel@tonic-gate * 837c478bd9Sstevel@tonic-gate * Copyright (c) 1989 Carnegie Mellon University. 847c478bd9Sstevel@tonic-gate * All rights reserved. 857c478bd9Sstevel@tonic-gate * 867c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 877c478bd9Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are 887c478bd9Sstevel@tonic-gate * duplicated in all such forms and that any documentation, 897c478bd9Sstevel@tonic-gate * advertising materials, and other materials related to such 907c478bd9Sstevel@tonic-gate * distribution and use acknowledge that the software was developed 917c478bd9Sstevel@tonic-gate * by Carnegie Mellon University. The name of the 927c478bd9Sstevel@tonic-gate * University may not be used to endorse or promote products derived 937c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 947c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 957c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 967c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 977c478bd9Sstevel@tonic-gate * 98*48bbca81SDaniel Hoffman * $Id: ipv6cp.c,v 1.9 2000/04/15 01:27:11 masputra Exp $ 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate #define RCSID "$Id: ipv6cp.c,v 1.9 2000/04/15 01:27:11 masputra Exp $" 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 104*48bbca81SDaniel Hoffman * TODO: 1057c478bd9Sstevel@tonic-gate * 1067c478bd9Sstevel@tonic-gate * Proxy Neighbour Discovery. 1077c478bd9Sstevel@tonic-gate * 1087c478bd9Sstevel@tonic-gate * Better defines for selecting the ordering of 1097c478bd9Sstevel@tonic-gate * interface up / set address. (currently checks for __linux__, 1107c478bd9Sstevel@tonic-gate * since SVR4 && (SNI || __USLC__) didn't work properly) 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate #include <stdio.h> 1147c478bd9Sstevel@tonic-gate #include <string.h> 1157c478bd9Sstevel@tonic-gate #include <stdlib.h> 1167c478bd9Sstevel@tonic-gate #include <unistd.h> 1177c478bd9Sstevel@tonic-gate #include <netdb.h> 1187c478bd9Sstevel@tonic-gate #include <sys/param.h> 1197c478bd9Sstevel@tonic-gate #include <sys/types.h> 1207c478bd9Sstevel@tonic-gate #include <sys/socket.h> 1217c478bd9Sstevel@tonic-gate #include <netinet/in.h> 1227c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate #include "pppd.h" 1257c478bd9Sstevel@tonic-gate #include "eui64.h" 1267c478bd9Sstevel@tonic-gate #include "fsm.h" 1277c478bd9Sstevel@tonic-gate #include "ipcp.h" 1287c478bd9Sstevel@tonic-gate #include "ipv6cp.h" 1297c478bd9Sstevel@tonic-gate #include "magic.h" 1307c478bd9Sstevel@tonic-gate #include "pathnames.h" 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 1337c478bd9Sstevel@tonic-gate static const char rcsid[] = RCSID; 1347c478bd9Sstevel@tonic-gate #endif 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* global vars */ 1377c478bd9Sstevel@tonic-gate ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */ 1387c478bd9Sstevel@tonic-gate ipv6cp_options ipv6cp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 1397c478bd9Sstevel@tonic-gate ipv6cp_options ipv6cp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 1407c478bd9Sstevel@tonic-gate ipv6cp_options ipv6cp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 1417c478bd9Sstevel@tonic-gate int no_ifaceid_neg = 0; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* local vars */ 1447c478bd9Sstevel@tonic-gate static bool ipv6cp_is_up; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * Callbacks for fsm code. (CI = Configuration Information) 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate static void ipv6cp_resetci __P((fsm *)); /* Reset our CI */ 1507c478bd9Sstevel@tonic-gate static int ipv6cp_cilen __P((fsm *)); /* Return length of our CI */ 1517c478bd9Sstevel@tonic-gate static void ipv6cp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ 1527c478bd9Sstevel@tonic-gate static int ipv6cp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ 1537c478bd9Sstevel@tonic-gate static int ipv6cp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ 1547c478bd9Sstevel@tonic-gate static int ipv6cp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ 1557c478bd9Sstevel@tonic-gate static int ipv6cp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ 1567c478bd9Sstevel@tonic-gate static void ipv6cp_up __P((fsm *)); /* We're UP */ 1577c478bd9Sstevel@tonic-gate static void ipv6cp_down __P((fsm *)); /* We're DOWN */ 1587c478bd9Sstevel@tonic-gate static void ipv6cp_finished __P((fsm *)); /* Don't need lower layer */ 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate fsm ipv6cp_fsm[NUM_PPP]; /* IPV6CP fsm structure */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ 1637c478bd9Sstevel@tonic-gate ipv6cp_resetci, /* Reset our Configuration Information */ 1647c478bd9Sstevel@tonic-gate ipv6cp_cilen, /* Length of our Configuration Information */ 1657c478bd9Sstevel@tonic-gate ipv6cp_addci, /* Add our Configuration Information */ 1667c478bd9Sstevel@tonic-gate ipv6cp_ackci, /* ACK our Configuration Information */ 1677c478bd9Sstevel@tonic-gate ipv6cp_nakci, /* NAK our Configuration Information */ 1687c478bd9Sstevel@tonic-gate ipv6cp_rejci, /* Reject our Configuration Information */ 1697c478bd9Sstevel@tonic-gate ipv6cp_reqci, /* Request peer's Configuration Information */ 1707c478bd9Sstevel@tonic-gate ipv6cp_up, /* Called when fsm reaches OPENED state */ 1717c478bd9Sstevel@tonic-gate ipv6cp_down, /* Called when fsm leaves OPENED state */ 1727c478bd9Sstevel@tonic-gate NULL, /* Called when we want the lower layer up */ 1737c478bd9Sstevel@tonic-gate ipv6cp_finished, /* Called when we want the lower layer down */ 1747c478bd9Sstevel@tonic-gate NULL, /* Retransmission is necessary */ 1757c478bd9Sstevel@tonic-gate NULL, /* Called to handle protocol-specific codes */ 1767c478bd9Sstevel@tonic-gate "IPV6CP", /* String name of protocol */ 1777c478bd9Sstevel@tonic-gate NULL /* Peer rejected a code number */ 1787c478bd9Sstevel@tonic-gate }; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate static int setifaceid __P((char **arg, option_t *)); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * Command-line options. 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate static option_t ipv6cp_option_list[] = { 1867c478bd9Sstevel@tonic-gate { "ipv6", o_special, (void *)setifaceid, 1877c478bd9Sstevel@tonic-gate "Set interface identifiers for IPV6" }, 1887c478bd9Sstevel@tonic-gate { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, 1897c478bd9Sstevel@tonic-gate "Disable IPv6 and IPv6CP" }, 1907c478bd9Sstevel@tonic-gate { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, 1917c478bd9Sstevel@tonic-gate "Disable IPv6 and IPv6CP" }, 1927c478bd9Sstevel@tonic-gate { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, 1937c478bd9Sstevel@tonic-gate "Enable IPv6 and IPv6CP", 1 }, 1947c478bd9Sstevel@tonic-gate { "ipv6cp-accept-local", o_bool, &ipv6cp_wantoptions[0].accept_local, 1957c478bd9Sstevel@tonic-gate "Accept peer's interface identifier for us", 1 }, 1967c478bd9Sstevel@tonic-gate { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_wantoptions[0].use_ip, 1977c478bd9Sstevel@tonic-gate "Use (default) IPv4 address as interface identifier", 1 }, 1987c478bd9Sstevel@tonic-gate #if defined(SOL2) 1997c478bd9Sstevel@tonic-gate { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, 2007c478bd9Sstevel@tonic-gate "Use unique persistent value for link local address", 1 }, 2017c478bd9Sstevel@tonic-gate #endif /* defined(SOL2) */ 2027c478bd9Sstevel@tonic-gate { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, 2037c478bd9Sstevel@tonic-gate "Set timeout for IPv6CP" }, 2047c478bd9Sstevel@tonic-gate { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, 2057c478bd9Sstevel@tonic-gate "Maximum number of IPV6CP Terminate-Request" }, 2067c478bd9Sstevel@tonic-gate { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, 2077c478bd9Sstevel@tonic-gate "Maximum number of IPV6CP Configure-Request" }, 2087c478bd9Sstevel@tonic-gate { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, 2097c478bd9Sstevel@tonic-gate "Maximum number of IPV6CP Configure-Nak" }, 2107c478bd9Sstevel@tonic-gate { NULL } 2117c478bd9Sstevel@tonic-gate }; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Protocol entry points from main code. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate static void ipv6cp_init __P((int)); 2187c478bd9Sstevel@tonic-gate static void ipv6cp_open __P((int)); 2197c478bd9Sstevel@tonic-gate static void ipv6cp_close __P((int, char *)); 2207c478bd9Sstevel@tonic-gate static void ipv6cp_lowerup __P((int)); 2217c478bd9Sstevel@tonic-gate static void ipv6cp_lowerdown __P((int)); 2227c478bd9Sstevel@tonic-gate static void ipv6cp_input __P((int, u_char *, int)); 2237c478bd9Sstevel@tonic-gate static void ipv6cp_protrej __P((int)); 2247c478bd9Sstevel@tonic-gate static int ipv6cp_printpkt __P((u_char *, int, 2257c478bd9Sstevel@tonic-gate void (*) __P((void *, const char *, ...)), void *)); 2267c478bd9Sstevel@tonic-gate static void ipv6_check_options __P((void)); 2277c478bd9Sstevel@tonic-gate static int ipv6_demand_conf __P((int)); 2287c478bd9Sstevel@tonic-gate static int ipv6_active_pkt __P((u_char *, int)); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate struct protent ipv6cp_protent = { 2317c478bd9Sstevel@tonic-gate PPP_IPV6CP, /* Protocol Number for IPV6CP */ 2327c478bd9Sstevel@tonic-gate ipv6cp_init, /* Initializes IPV6CP */ 2337c478bd9Sstevel@tonic-gate ipv6cp_input, /* Processes a received IPV6CP packet */ 2347c478bd9Sstevel@tonic-gate ipv6cp_protrej, /* Process a received Protocol-reject */ 2357c478bd9Sstevel@tonic-gate ipv6cp_lowerup, /* Called when LCP is brought up */ 2367c478bd9Sstevel@tonic-gate ipv6cp_lowerdown, /* Called when LCP has gone down */ 2377c478bd9Sstevel@tonic-gate ipv6cp_open, /* Called when link is established */ 2387c478bd9Sstevel@tonic-gate ipv6cp_close, /* Called when link has gone down */ 2397c478bd9Sstevel@tonic-gate ipv6cp_printpkt, /* Print a packet in human readable form */ 2407c478bd9Sstevel@tonic-gate NULL, /* Process a received data packet */ 2417c478bd9Sstevel@tonic-gate 0, /* IPV6CP is disabled by default */ 2427c478bd9Sstevel@tonic-gate "IPV6CP", /* Name of the protocol */ 2437c478bd9Sstevel@tonic-gate "IPV6", /* Name of the corresponding data protocol */ 2447c478bd9Sstevel@tonic-gate ipv6cp_option_list, /* List of IPV6CP command-line options */ 2457c478bd9Sstevel@tonic-gate ipv6_check_options, /* Assigns default values for options */ 2467c478bd9Sstevel@tonic-gate ipv6_demand_conf, /* Configures demand-dial */ 2477c478bd9Sstevel@tonic-gate ipv6_active_pkt /* Bring up the link for this packet? */ 2487c478bd9Sstevel@tonic-gate }; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * Local forward function declarations. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate static void ipv6cp_clear_addrs __P((int, eui64_t, eui64_t)); 2547c478bd9Sstevel@tonic-gate static void ipv6cp_script __P((char *)); 2557c478bd9Sstevel@tonic-gate static void ipv6cp_script_done __P((void *, int)); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* 2587c478bd9Sstevel@tonic-gate * Lengths of configuration options. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate #define CILEN_VOID 2 2617c478bd9Sstevel@tonic-gate #define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ 2627c478bd9Sstevel@tonic-gate #define CILEN_IFACEID 10 /* RFC2472, interface identifier */ 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate #define CODENAME(x) ((x) == CODE_CONFACK ? "ACK" : \ 2657c478bd9Sstevel@tonic-gate (x) == CODE_CONFNAK ? "NAK" : "REJ") 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * This state variable is used to ensure that we don't 2697c478bd9Sstevel@tonic-gate * run an ipcp-up/down script while one is already running. 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate static enum script_state { 2727c478bd9Sstevel@tonic-gate s_down, 2737c478bd9Sstevel@tonic-gate s_up 2747c478bd9Sstevel@tonic-gate } ipv6cp_script_state; 2757c478bd9Sstevel@tonic-gate static pid_t ipv6cp_script_pid; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * setifaceid - set the interface identifiers manually 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2817c478bd9Sstevel@tonic-gate static int 2827c478bd9Sstevel@tonic-gate setifaceid(argv, opt) 2837c478bd9Sstevel@tonic-gate char **argv; 2847c478bd9Sstevel@tonic-gate option_t *opt; 2857c478bd9Sstevel@tonic-gate { 2867c478bd9Sstevel@tonic-gate char *comma, *arg; 2877c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[0]; 2887c478bd9Sstevel@tonic-gate struct in6_addr addr; 289*48bbca81SDaniel Hoffman 2907c478bd9Sstevel@tonic-gate #define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ 2917c478bd9Sstevel@tonic-gate (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) 292*48bbca81SDaniel Hoffman 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate arg = *argv; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate comma = strchr(arg, ','); 297*48bbca81SDaniel Hoffman 298*48bbca81SDaniel Hoffman /* 2997c478bd9Sstevel@tonic-gate * If comma first character, then no local identifier 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate if (comma != arg) { 3027c478bd9Sstevel@tonic-gate if (comma != NULL) 3037c478bd9Sstevel@tonic-gate *comma = '\0'; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET6, arg, &addr) != 1 || !VALIDID(addr)) { 3067c478bd9Sstevel@tonic-gate option_error("Illegal interface identifier (local): %s", arg); 3077c478bd9Sstevel@tonic-gate return 0; 3087c478bd9Sstevel@tonic-gate } 309*48bbca81SDaniel Hoffman 3107c478bd9Sstevel@tonic-gate eui64_copy(addr.s6_addr32[2], wo->ourid); 3117c478bd9Sstevel@tonic-gate wo->opt_local = 1; 3127c478bd9Sstevel@tonic-gate } 313*48bbca81SDaniel Hoffman 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * If comma last character, then no remote identifier 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate if (comma != NULL && *++comma != '\0') { 3187c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET6, comma, &addr) != 1 || !VALIDID(addr)) { 3197c478bd9Sstevel@tonic-gate option_error("Illegal interface identifier (remote): %s", comma); 3207c478bd9Sstevel@tonic-gate return 0; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate eui64_copy(addr.s6_addr32[2], wo->hisid); 3237c478bd9Sstevel@tonic-gate wo->opt_remote = 1; 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate ipv6cp_protent.enabled_flag = 1; 3277c478bd9Sstevel@tonic-gate return 1; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Given an interface identifier, return a string representation of the 3327c478bd9Sstevel@tonic-gate * link local address associated with that identifier. 3337c478bd9Sstevel@tonic-gate * string will be at most 26 characters (including null terminator). 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate static char * 3367c478bd9Sstevel@tonic-gate llv6_ntoa(ifaceid) 3377c478bd9Sstevel@tonic-gate eui64_t ifaceid; 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate struct in6_addr addr; 3407c478bd9Sstevel@tonic-gate static char addrstr[26]; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate BZERO(&addr, sizeof (addr)); 3437c478bd9Sstevel@tonic-gate addr.s6_addr[0] = 0xfe; 3447c478bd9Sstevel@tonic-gate addr.s6_addr[1] = 0x80; 3457c478bd9Sstevel@tonic-gate eui64_copy(ifaceid, addr.s6_addr[8]); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET6, &addr, addrstr, 26); 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate return addrstr; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * ipv6cp_init - Initialize IPV6CP. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate static void 3577c478bd9Sstevel@tonic-gate ipv6cp_init(unit) 3587c478bd9Sstevel@tonic-gate int unit; 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate fsm *f = &ipv6cp_fsm[unit]; 3617c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[unit]; 3627c478bd9Sstevel@tonic-gate ipv6cp_options *ao = &ipv6cp_allowoptions[unit]; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate f->unit = unit; 3657c478bd9Sstevel@tonic-gate f->protocol = PPP_IPV6CP; 3667c478bd9Sstevel@tonic-gate f->callbacks = &ipv6cp_callbacks; 3677c478bd9Sstevel@tonic-gate fsm_init(&ipv6cp_fsm[unit]); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate BZERO(wo, sizeof(*wo)); 3707c478bd9Sstevel@tonic-gate BZERO(ao, sizeof(*ao)); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate wo->neg_ifaceid = 1; 3737c478bd9Sstevel@tonic-gate ao->neg_ifaceid = 1; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate #ifdef IPV6CP_COMP 3767c478bd9Sstevel@tonic-gate wo->neg_vj = 1; 3777c478bd9Sstevel@tonic-gate ao->neg_vj = 1; 3787c478bd9Sstevel@tonic-gate wo->vj_protocol = IPV6CP_COMP; 3797c478bd9Sstevel@tonic-gate #endif 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* 3857c478bd9Sstevel@tonic-gate * ipv6cp_open - IPV6CP is allowed to come up. 3867c478bd9Sstevel@tonic-gate */ 3877c478bd9Sstevel@tonic-gate static void 3887c478bd9Sstevel@tonic-gate ipv6cp_open(unit) 3897c478bd9Sstevel@tonic-gate int unit; 3907c478bd9Sstevel@tonic-gate { 3917c478bd9Sstevel@tonic-gate fsm_open(&ipv6cp_fsm[unit]); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* 3967c478bd9Sstevel@tonic-gate * ipv6cp_close - Take IPV6CP down. 3977c478bd9Sstevel@tonic-gate */ 3987c478bd9Sstevel@tonic-gate static void 3997c478bd9Sstevel@tonic-gate ipv6cp_close(unit, reason) 4007c478bd9Sstevel@tonic-gate int unit; 4017c478bd9Sstevel@tonic-gate char *reason; 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate fsm_close(&ipv6cp_fsm[unit], reason); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * ipv6cp_lowerup - The lower layer is up. 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate static void 4117c478bd9Sstevel@tonic-gate ipv6cp_lowerup(unit) 4127c478bd9Sstevel@tonic-gate int unit; 4137c478bd9Sstevel@tonic-gate { 4147c478bd9Sstevel@tonic-gate fsm_lowerup(&ipv6cp_fsm[unit]); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * ipv6cp_lowerdown - The lower layer is down. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate static void 4227c478bd9Sstevel@tonic-gate ipv6cp_lowerdown(unit) 4237c478bd9Sstevel@tonic-gate int unit; 4247c478bd9Sstevel@tonic-gate { 4257c478bd9Sstevel@tonic-gate fsm_lowerdown(&ipv6cp_fsm[unit]); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * ipv6cp_input - Input IPV6CP packet. 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate static void 4337c478bd9Sstevel@tonic-gate ipv6cp_input(unit, p, len) 4347c478bd9Sstevel@tonic-gate int unit; 4357c478bd9Sstevel@tonic-gate u_char *p; 4367c478bd9Sstevel@tonic-gate int len; 4377c478bd9Sstevel@tonic-gate { 4387c478bd9Sstevel@tonic-gate fsm_input(&ipv6cp_fsm[unit], p, len); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate static void 4467c478bd9Sstevel@tonic-gate ipv6cp_protrej(unit) 4477c478bd9Sstevel@tonic-gate int unit; 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate fsm_protreject(&ipv6cp_fsm[unit]); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * ipv6cp_resetci - Reset our CI. 4557c478bd9Sstevel@tonic-gate */ 4567c478bd9Sstevel@tonic-gate static void 4577c478bd9Sstevel@tonic-gate ipv6cp_resetci(f) 4587c478bd9Sstevel@tonic-gate fsm *f; 4597c478bd9Sstevel@tonic-gate { 4607c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; 4617c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate wo->req_ifaceid = wo->neg_ifaceid && ipv6cp_allowoptions[f->unit].neg_ifaceid; 464*48bbca81SDaniel Hoffman 4657c478bd9Sstevel@tonic-gate if (!wo->opt_local) { 4667c478bd9Sstevel@tonic-gate eui64_magic_nz(wo->ourid); 4677c478bd9Sstevel@tonic-gate } 468*48bbca81SDaniel Hoffman 4697c478bd9Sstevel@tonic-gate *go = *wo; 4707c478bd9Sstevel@tonic-gate eui64_zero(go->hisid); /* last proposed interface identifier */ 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * ipv6cp_cilen - Return length of our CI. 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate static int 4787c478bd9Sstevel@tonic-gate ipv6cp_cilen(f) 4797c478bd9Sstevel@tonic-gate fsm *f; 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate #define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) 4847c478bd9Sstevel@tonic-gate #define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate return (LENCIIFACEID(go->neg_ifaceid) + 4877c478bd9Sstevel@tonic-gate LENCIVJ(go->neg_vj)); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* 4927c478bd9Sstevel@tonic-gate * ipv6cp_addci - Add our desired CIs to a packet. 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate static void 4957c478bd9Sstevel@tonic-gate ipv6cp_addci(f, ucp, lenp) 4967c478bd9Sstevel@tonic-gate fsm *f; 4977c478bd9Sstevel@tonic-gate u_char *ucp; 4987c478bd9Sstevel@tonic-gate int *lenp; 4997c478bd9Sstevel@tonic-gate { 5007c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 5017c478bd9Sstevel@tonic-gate int len = *lenp; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate #define ADDCIVJ(opt, neg, val) \ 5047c478bd9Sstevel@tonic-gate if (neg) { \ 5057c478bd9Sstevel@tonic-gate int vjlen = CILEN_COMPRESS; \ 5067c478bd9Sstevel@tonic-gate if (len >= vjlen) { \ 5077c478bd9Sstevel@tonic-gate PUTCHAR(opt, ucp); \ 5087c478bd9Sstevel@tonic-gate PUTCHAR(vjlen, ucp); \ 5097c478bd9Sstevel@tonic-gate PUTSHORT(val, ucp); \ 5107c478bd9Sstevel@tonic-gate len -= vjlen; \ 5117c478bd9Sstevel@tonic-gate } else \ 5127c478bd9Sstevel@tonic-gate neg = 0; \ 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate #define ADDCIIFACEID(opt, neg, val1) \ 5167c478bd9Sstevel@tonic-gate if (neg) { \ 5177c478bd9Sstevel@tonic-gate int idlen = CILEN_IFACEID; \ 5187c478bd9Sstevel@tonic-gate if (len >= idlen) { \ 5197c478bd9Sstevel@tonic-gate PUTCHAR(opt, ucp); \ 5207c478bd9Sstevel@tonic-gate PUTCHAR(idlen, ucp); \ 5217c478bd9Sstevel@tonic-gate eui64_put(val1, ucp); \ 5227c478bd9Sstevel@tonic-gate len -= idlen; \ 5237c478bd9Sstevel@tonic-gate } else \ 5247c478bd9Sstevel@tonic-gate neg = 0; \ 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate *lenp -= len; 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* 5367c478bd9Sstevel@tonic-gate * ipv6cp_ackci - Ack our CIs. 5377c478bd9Sstevel@tonic-gate * 5387c478bd9Sstevel@tonic-gate * Returns: 5397c478bd9Sstevel@tonic-gate * 0 - Ack was bad. 5407c478bd9Sstevel@tonic-gate * 1 - Ack was good. 5417c478bd9Sstevel@tonic-gate */ 5427c478bd9Sstevel@tonic-gate static int 5437c478bd9Sstevel@tonic-gate ipv6cp_ackci(f, p, len) 5447c478bd9Sstevel@tonic-gate fsm *f; 5457c478bd9Sstevel@tonic-gate u_char *p; 5467c478bd9Sstevel@tonic-gate int len; 5477c478bd9Sstevel@tonic-gate { 5487c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 5497c478bd9Sstevel@tonic-gate u_short cilen, citype, cishort; 5507c478bd9Sstevel@tonic-gate eui64_t ifaceid; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 5537c478bd9Sstevel@tonic-gate * CIs must be in exactly the same order that we sent... 5547c478bd9Sstevel@tonic-gate * Check packet length and CI length at each step. 5557c478bd9Sstevel@tonic-gate * If we find any deviations, then this packet is bad. 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate #define ACKCIVJ(opt, neg, val) \ 5597c478bd9Sstevel@tonic-gate if (neg) { \ 5607c478bd9Sstevel@tonic-gate int vjlen = CILEN_COMPRESS; \ 5617c478bd9Sstevel@tonic-gate if ((len -= vjlen) < 0) \ 5627c478bd9Sstevel@tonic-gate goto bad; \ 5637c478bd9Sstevel@tonic-gate GETCHAR(citype, p); \ 5647c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); \ 5657c478bd9Sstevel@tonic-gate if (cilen != vjlen || \ 5667c478bd9Sstevel@tonic-gate citype != opt) \ 5677c478bd9Sstevel@tonic-gate goto bad; \ 5687c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); \ 5697c478bd9Sstevel@tonic-gate if (cishort != val) \ 5707c478bd9Sstevel@tonic-gate goto bad; \ 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate #define ACKCIIFACEID(opt, neg, val1) \ 5747c478bd9Sstevel@tonic-gate if (neg) { \ 5757c478bd9Sstevel@tonic-gate int idlen = CILEN_IFACEID; \ 5767c478bd9Sstevel@tonic-gate if ((len -= idlen) < 0) \ 5777c478bd9Sstevel@tonic-gate goto bad; \ 5787c478bd9Sstevel@tonic-gate GETCHAR(citype, p); \ 5797c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); \ 5807c478bd9Sstevel@tonic-gate if (cilen != idlen || \ 5817c478bd9Sstevel@tonic-gate citype != opt) \ 5827c478bd9Sstevel@tonic-gate goto bad; \ 5837c478bd9Sstevel@tonic-gate eui64_get(ifaceid, p); \ 5847c478bd9Sstevel@tonic-gate if (! eui64_equals(val1, ifaceid)) \ 5857c478bd9Sstevel@tonic-gate goto bad; \ 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* 5937c478bd9Sstevel@tonic-gate * If there are any remaining CIs, then this packet is bad. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate if (len != 0) 5967c478bd9Sstevel@tonic-gate goto bad; 5977c478bd9Sstevel@tonic-gate return (1); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate bad: 6007c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); 6017c478bd9Sstevel@tonic-gate return (0); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* 6057c478bd9Sstevel@tonic-gate * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. 6067c478bd9Sstevel@tonic-gate * This should not modify any state if the Nak is bad 6077c478bd9Sstevel@tonic-gate * or if IPV6CP is in the OPENED state. 6087c478bd9Sstevel@tonic-gate * 6097c478bd9Sstevel@tonic-gate * Returns: 6107c478bd9Sstevel@tonic-gate * 0 - Nak was bad. 6117c478bd9Sstevel@tonic-gate * 1 - Nak was good. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate static int 6147c478bd9Sstevel@tonic-gate ipv6cp_nakci(f, p, len) 6157c478bd9Sstevel@tonic-gate fsm *f; 6167c478bd9Sstevel@tonic-gate u_char *p; 6177c478bd9Sstevel@tonic-gate int len; 6187c478bd9Sstevel@tonic-gate { 6197c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 6207c478bd9Sstevel@tonic-gate u_char citype, cilen, *next; 6217c478bd9Sstevel@tonic-gate u_short cishort; 6227c478bd9Sstevel@tonic-gate eui64_t ifaceid; 6237c478bd9Sstevel@tonic-gate ipv6cp_options no; /* options we've seen Naks for */ 6247c478bd9Sstevel@tonic-gate ipv6cp_options try; /* options to request next time */ 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate BZERO(&no, sizeof(no)); 6277c478bd9Sstevel@tonic-gate try = *go; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * Any Nak'd CIs must be in exactly the same order that we sent. 6317c478bd9Sstevel@tonic-gate * Check packet length and CI length at each step. 6327c478bd9Sstevel@tonic-gate * If we find any deviations, then this packet is bad. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate #define NAKCIIFACEID(opt, neg, code) \ 6357c478bd9Sstevel@tonic-gate if (go->neg && \ 6367c478bd9Sstevel@tonic-gate len >= (cilen = CILEN_IFACEID) && \ 6377c478bd9Sstevel@tonic-gate p[1] == cilen && \ 6387c478bd9Sstevel@tonic-gate p[0] == opt) { \ 6397c478bd9Sstevel@tonic-gate len -= cilen; \ 6407c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 6417c478bd9Sstevel@tonic-gate eui64_get(ifaceid, p); \ 6427c478bd9Sstevel@tonic-gate no.neg = 1; \ 6437c478bd9Sstevel@tonic-gate code \ 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate #define NAKCIVJ(opt, neg, code) \ 6477c478bd9Sstevel@tonic-gate if (go->neg && \ 6487c478bd9Sstevel@tonic-gate ((cilen = p[1]) == CILEN_COMPRESS) && \ 6497c478bd9Sstevel@tonic-gate len >= cilen && \ 6507c478bd9Sstevel@tonic-gate p[0] == opt) { \ 6517c478bd9Sstevel@tonic-gate len -= cilen; \ 6527c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 6537c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); \ 6547c478bd9Sstevel@tonic-gate no.neg = 1; \ 6557c478bd9Sstevel@tonic-gate code \ 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* 659*48bbca81SDaniel Hoffman * Accept the peer's idea of {our,its} interface identifier, if different 6607c478bd9Sstevel@tonic-gate * from our idea, only if the accept_{local,remote} flag is set. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate NAKCIIFACEID(CI_IFACEID, neg_ifaceid, 6637c478bd9Sstevel@tonic-gate if (go->accept_local) { 664*48bbca81SDaniel Hoffman while (eui64_iszero(ifaceid) || 6657c478bd9Sstevel@tonic-gate eui64_equals(ifaceid, go->hisid)) /* bad luck */ 6667c478bd9Sstevel@tonic-gate eui64_magic(ifaceid); 6677c478bd9Sstevel@tonic-gate try.ourid = ifaceid; 6687c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate ); 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate #ifdef IPV6CP_COMP 6737c478bd9Sstevel@tonic-gate NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 6747c478bd9Sstevel@tonic-gate { 6757c478bd9Sstevel@tonic-gate if (cishort == IPV6CP_COMP) { 6767c478bd9Sstevel@tonic-gate try.vj_protocol = cishort; 6777c478bd9Sstevel@tonic-gate } else { 6787c478bd9Sstevel@tonic-gate try.neg_vj = 0; 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate ); 6827c478bd9Sstevel@tonic-gate #else 6837c478bd9Sstevel@tonic-gate NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate try.neg_vj = 0; 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate ); 6887c478bd9Sstevel@tonic-gate #endif 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * There may be remaining CIs, if the peer is requesting negotiation 6927c478bd9Sstevel@tonic-gate * on an option that we didn't include in our request packet. 6937c478bd9Sstevel@tonic-gate * If they want to negotiate about interface identifier, we comply. 6947c478bd9Sstevel@tonic-gate * If they want us to ask for compression, we refuse. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate while (len > CILEN_VOID) { 6977c478bd9Sstevel@tonic-gate GETCHAR(citype, p); 6987c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); 6997c478bd9Sstevel@tonic-gate if( (len -= cilen) < 0 ) 7007c478bd9Sstevel@tonic-gate goto bad; 7017c478bd9Sstevel@tonic-gate next = p + cilen - 2; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate switch (citype) { 7047c478bd9Sstevel@tonic-gate case CI_COMPRESSTYPE: 7057c478bd9Sstevel@tonic-gate if (go->neg_vj || no.neg_vj || 7067c478bd9Sstevel@tonic-gate (cilen != CILEN_COMPRESS)) 7077c478bd9Sstevel@tonic-gate goto bad; 7087c478bd9Sstevel@tonic-gate no.neg_vj = 1; 7097c478bd9Sstevel@tonic-gate break; 7107c478bd9Sstevel@tonic-gate case CI_IFACEID: 7117c478bd9Sstevel@tonic-gate if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) 7127c478bd9Sstevel@tonic-gate goto bad; 7137c478bd9Sstevel@tonic-gate try.neg_ifaceid = 1; 7147c478bd9Sstevel@tonic-gate eui64_get(ifaceid, p); 7157c478bd9Sstevel@tonic-gate if (go->accept_local) { 716*48bbca81SDaniel Hoffman while (eui64_iszero(ifaceid) || 7177c478bd9Sstevel@tonic-gate eui64_equals(ifaceid, go->hisid)) /* bad luck */ 7187c478bd9Sstevel@tonic-gate eui64_magic(ifaceid); 7197c478bd9Sstevel@tonic-gate try.ourid = ifaceid; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate no.neg_ifaceid = 1; 7227c478bd9Sstevel@tonic-gate break; 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate p = next; 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate /* If there is still anything left, this packet is bad. */ 7287c478bd9Sstevel@tonic-gate if (len != 0) 7297c478bd9Sstevel@tonic-gate goto bad; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * OK, the Nak is good. Now we can update state. 7337c478bd9Sstevel@tonic-gate */ 7347c478bd9Sstevel@tonic-gate if (f->state != OPENED) 7357c478bd9Sstevel@tonic-gate *go = try; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate return 1; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate bad: 7407c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); 7417c478bd9Sstevel@tonic-gate return 0; 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* 7467c478bd9Sstevel@tonic-gate * ipv6cp_rejci - Reject some of our CIs. 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate static int 7497c478bd9Sstevel@tonic-gate ipv6cp_rejci(f, p, len) 7507c478bd9Sstevel@tonic-gate fsm *f; 7517c478bd9Sstevel@tonic-gate u_char *p; 7527c478bd9Sstevel@tonic-gate int len; 7537c478bd9Sstevel@tonic-gate { 7547c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 7557c478bd9Sstevel@tonic-gate u_char cilen; 7567c478bd9Sstevel@tonic-gate u_short cishort; 7577c478bd9Sstevel@tonic-gate eui64_t ifaceid; 7587c478bd9Sstevel@tonic-gate ipv6cp_options try; /* options to request next time */ 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate try = *go; 7617c478bd9Sstevel@tonic-gate /* 7627c478bd9Sstevel@tonic-gate * Any Rejected CIs must be in exactly the same order that we sent. 7637c478bd9Sstevel@tonic-gate * Check packet length and CI length at each step. 7647c478bd9Sstevel@tonic-gate * If we find any deviations, then this packet is bad. 7657c478bd9Sstevel@tonic-gate */ 7667c478bd9Sstevel@tonic-gate #define REJCIIFACEID(opt, neg, val1) \ 7677c478bd9Sstevel@tonic-gate if (go->neg && \ 7687c478bd9Sstevel@tonic-gate len >= (cilen = CILEN_IFACEID) && \ 7697c478bd9Sstevel@tonic-gate p[1] == cilen && \ 7707c478bd9Sstevel@tonic-gate p[0] == opt) { \ 7717c478bd9Sstevel@tonic-gate len -= cilen; \ 7727c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 7737c478bd9Sstevel@tonic-gate eui64_get(ifaceid, p); \ 7747c478bd9Sstevel@tonic-gate /* Check rejected value. */ \ 7757c478bd9Sstevel@tonic-gate if (! eui64_equals(ifaceid, val1)) \ 7767c478bd9Sstevel@tonic-gate goto bad; \ 7777c478bd9Sstevel@tonic-gate try.neg = 0; \ 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate #define REJCIVJ(opt, neg, val) \ 7817c478bd9Sstevel@tonic-gate if (go->neg && \ 7827c478bd9Sstevel@tonic-gate p[1] == CILEN_COMPRESS && \ 7837c478bd9Sstevel@tonic-gate len >= p[1] && \ 7847c478bd9Sstevel@tonic-gate p[0] == opt) { \ 7857c478bd9Sstevel@tonic-gate len -= p[1]; \ 7867c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 7877c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); \ 7887c478bd9Sstevel@tonic-gate /* Check rejected value. */ \ 7897c478bd9Sstevel@tonic-gate if (cishort != val) \ 7907c478bd9Sstevel@tonic-gate goto bad; \ 7917c478bd9Sstevel@tonic-gate try.neg = 0; \ 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate /* 7997c478bd9Sstevel@tonic-gate * If there are any remaining CIs, then this packet is bad. 8007c478bd9Sstevel@tonic-gate */ 8017c478bd9Sstevel@tonic-gate if (len != 0) 8027c478bd9Sstevel@tonic-gate goto bad; 8037c478bd9Sstevel@tonic-gate /* 8047c478bd9Sstevel@tonic-gate * Now we can update state. 8057c478bd9Sstevel@tonic-gate */ 8067c478bd9Sstevel@tonic-gate if (f->state != OPENED) 8077c478bd9Sstevel@tonic-gate *go = try; 8087c478bd9Sstevel@tonic-gate return 1; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate bad: 8117c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); 8127c478bd9Sstevel@tonic-gate return 0; 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /* 8177c478bd9Sstevel@tonic-gate * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. 8187c478bd9Sstevel@tonic-gate * 8197c478bd9Sstevel@tonic-gate * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input packet modified 8207c478bd9Sstevel@tonic-gate * appropriately. If reject_if_disagree is non-zero, doesn't return 8217c478bd9Sstevel@tonic-gate * CODE_CONFNAK; returns CODE_CONFREJ if it can't return CODE_CONFACK. 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate static int 8247c478bd9Sstevel@tonic-gate ipv6cp_reqci(f, p, lenp, dont_nak) 8257c478bd9Sstevel@tonic-gate fsm *f; 8267c478bd9Sstevel@tonic-gate u_char *p; /* Requested CIs */ 8277c478bd9Sstevel@tonic-gate int *lenp; /* Length of requested CIs */ 8287c478bd9Sstevel@tonic-gate int dont_nak; 8297c478bd9Sstevel@tonic-gate { 8307c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; 8317c478bd9Sstevel@tonic-gate ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit]; 8327c478bd9Sstevel@tonic-gate ipv6cp_options *ao = &ipv6cp_allowoptions[f->unit]; 8337c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 8347c478bd9Sstevel@tonic-gate u_char *p0, *nakp, *rejp, *prev; 8357c478bd9Sstevel@tonic-gate int ret, newret; 8367c478bd9Sstevel@tonic-gate int len, cilen, type; 8377c478bd9Sstevel@tonic-gate eui64_t ifaceid; 8387c478bd9Sstevel@tonic-gate u_short cishort; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate ret = CODE_CONFACK; 8417c478bd9Sstevel@tonic-gate rejp = p0 = p; 8427c478bd9Sstevel@tonic-gate nakp = nak_buffer; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* 845*48bbca81SDaniel Hoffman * Reset all its options. 8467c478bd9Sstevel@tonic-gate */ 8477c478bd9Sstevel@tonic-gate BZERO(ho, sizeof(*ho)); 848*48bbca81SDaniel Hoffman 8497c478bd9Sstevel@tonic-gate /* 850*48bbca81SDaniel Hoffman * Process all its options. 8517c478bd9Sstevel@tonic-gate */ 8527c478bd9Sstevel@tonic-gate for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) { 8537c478bd9Sstevel@tonic-gate newret = CODE_CONFACK; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate if ((len < 2) || p[1] > len) { 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * RFC 1661 page 40 -- if the option extends beyond the 8587c478bd9Sstevel@tonic-gate * packet, then discard the entire packet. 8597c478bd9Sstevel@tonic-gate */ 8607c478bd9Sstevel@tonic-gate return (0); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate prev = p; 8647c478bd9Sstevel@tonic-gate GETCHAR(type, p); 8657c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate switch (type) { /* Check CI type */ 8687c478bd9Sstevel@tonic-gate case CI_IFACEID: 8697c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp: received interface identifier ")); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (!ao->neg_ifaceid) { 8727c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 8737c478bd9Sstevel@tonic-gate break; 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (cilen != CILEN_IFACEID) { 8777c478bd9Sstevel@tonic-gate /* 8787c478bd9Sstevel@tonic-gate * rfc1661, page 40 -- a recongnized option with an 8797c478bd9Sstevel@tonic-gate * invalid length should be Nak'ed. 8807c478bd9Sstevel@tonic-gate */ 8817c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 8827c478bd9Sstevel@tonic-gate eui64_copy(wo->hisid, ifaceid); 8837c478bd9Sstevel@tonic-gate } else { 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate /* 886*48bbca81SDaniel Hoffman * If it has no interface identifier, or if we both 8877c478bd9Sstevel@tonic-gate * have same identifier then NAK it with new idea. In 888*48bbca81SDaniel Hoffman * particular, if we don't know his identifier, but it 889*48bbca81SDaniel Hoffman * does, then accept that identifier. 8907c478bd9Sstevel@tonic-gate */ 8917c478bd9Sstevel@tonic-gate eui64_get(ifaceid, p); 8927c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); 8937c478bd9Sstevel@tonic-gate if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { 8947c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; /* Reject CI */ 8957c478bd9Sstevel@tonic-gate break; 8967c478bd9Sstevel@tonic-gate } 897*48bbca81SDaniel Hoffman /* If we don't like its ID, then nak that ID. */ 898*48bbca81SDaniel Hoffman if (!eui64_iszero(wo->hisid) && 899*48bbca81SDaniel Hoffman !eui64_equals(ifaceid, wo->hisid) && 9007c478bd9Sstevel@tonic-gate eui64_iszero(go->hisid)) { 9017c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 9027c478bd9Sstevel@tonic-gate eui64_copy(wo->hisid, ifaceid); 9037c478bd9Sstevel@tonic-gate } else if (eui64_iszero(ifaceid) || 9047c478bd9Sstevel@tonic-gate eui64_equals(ifaceid, go->ourid)) { 9057c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 9067c478bd9Sstevel@tonic-gate /* first time, try option */ 9077c478bd9Sstevel@tonic-gate if (eui64_iszero(go->hisid)) 9087c478bd9Sstevel@tonic-gate eui64_copy(wo->hisid, ifaceid); 909*48bbca81SDaniel Hoffman while (eui64_iszero(ifaceid) || 9107c478bd9Sstevel@tonic-gate eui64_equals(ifaceid, go->ourid)) /* bad luck */ 9117c478bd9Sstevel@tonic-gate eui64_magic(ifaceid); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 9157c478bd9Sstevel@tonic-gate PUTCHAR(type, nakp); 9167c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_IFACEID, nakp); 9177c478bd9Sstevel@tonic-gate eui64_put(ifaceid, nakp); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate ho->neg_ifaceid = 1; 9217c478bd9Sstevel@tonic-gate eui64_copy(ifaceid, ho->hisid); 9227c478bd9Sstevel@tonic-gate break; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate case CI_COMPRESSTYPE: 9257c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate if (!ao->neg_vj) { 9287c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 9297c478bd9Sstevel@tonic-gate break; 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate if (cilen != CILEN_COMPRESS) { 9337c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 9347c478bd9Sstevel@tonic-gate cishort = ao->vj_protocol; 9357c478bd9Sstevel@tonic-gate } else { 9367c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); 9377c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("(%d)", cishort)); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate #ifdef IPV6CP_COMP 9407c478bd9Sstevel@tonic-gate if (cishort != IPV6CP_COMP) { 9417c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 9427c478bd9Sstevel@tonic-gate cishort = IPV6CP_COMP; 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate #else 9457c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 9467c478bd9Sstevel@tonic-gate break; 9477c478bd9Sstevel@tonic-gate #endif 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate ho->neg_vj = 1; 9517c478bd9Sstevel@tonic-gate ho->vj_protocol = cishort; 9527c478bd9Sstevel@tonic-gate break; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate default: 9557c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 9567c478bd9Sstevel@tonic-gate break; 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate IPV6CPDEBUG((" (%s)\n", CODENAME(newret))); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* Cope with confused peers. */ 9627c478bd9Sstevel@tonic-gate if (cilen < 2) 9637c478bd9Sstevel@tonic-gate cilen = 2; 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate /* 9667c478bd9Sstevel@tonic-gate * If this is an Ack'able CI, but we're sending back a Nak, 9677c478bd9Sstevel@tonic-gate * don't include this CI. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate if (newret == CODE_CONFACK && ret != CODE_CONFACK) 9707c478bd9Sstevel@tonic-gate continue; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 9737c478bd9Sstevel@tonic-gate if (dont_nak) { 9747c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 9757c478bd9Sstevel@tonic-gate } else { 9767c478bd9Sstevel@tonic-gate /* Ignore subsequent Nak'able things if rejecting. */ 9777c478bd9Sstevel@tonic-gate if (ret == CODE_CONFREJ) 9787c478bd9Sstevel@tonic-gate continue; 9797c478bd9Sstevel@tonic-gate ret = CODE_CONFNAK; 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate if (newret == CODE_CONFREJ) { 9847c478bd9Sstevel@tonic-gate ret = CODE_CONFREJ; 9857c478bd9Sstevel@tonic-gate if (prev != rejp) 9867c478bd9Sstevel@tonic-gate (void) BCOPY(prev, rejp, cilen); 9877c478bd9Sstevel@tonic-gate rejp += cilen; 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate /* 9927c478bd9Sstevel@tonic-gate * If we aren't rejecting this packet, and we want to negotiate 9937c478bd9Sstevel@tonic-gate * their identifier and they didn't send their identifier, then we 9947c478bd9Sstevel@tonic-gate * send a NAK with a CI_IFACEID option appended. We assume the 9957c478bd9Sstevel@tonic-gate * input buffer is long enough that we can append the extra 9967c478bd9Sstevel@tonic-gate * option safely. 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate if (ret != CODE_CONFREJ && !ho->neg_ifaceid && 9997c478bd9Sstevel@tonic-gate wo->req_ifaceid && !dont_nak) { 10007c478bd9Sstevel@tonic-gate if (ret == CODE_CONFACK) 10017c478bd9Sstevel@tonic-gate wo->req_ifaceid = 0; 10027c478bd9Sstevel@tonic-gate ret = CODE_CONFNAK; 10037c478bd9Sstevel@tonic-gate PUTCHAR(CI_IFACEID, nakp); 10047c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_IFACEID, nakp); 10057c478bd9Sstevel@tonic-gate eui64_put(wo->hisid, nakp); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate switch (ret) { 10097c478bd9Sstevel@tonic-gate case CODE_CONFACK: 10107c478bd9Sstevel@tonic-gate *lenp = p - p0; 1011*48bbca81SDaniel Hoffman sys_block_proto(PPP_IPV6); 10127c478bd9Sstevel@tonic-gate break; 10137c478bd9Sstevel@tonic-gate case CODE_CONFNAK: 10147c478bd9Sstevel@tonic-gate *lenp = nakp - nak_buffer; 10157c478bd9Sstevel@tonic-gate (void) BCOPY(nak_buffer, p0, *lenp); 10167c478bd9Sstevel@tonic-gate break; 10177c478bd9Sstevel@tonic-gate case CODE_CONFREJ: 10187c478bd9Sstevel@tonic-gate *lenp = rejp - p0; 10197c478bd9Sstevel@tonic-gate break; 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(ret))); 10237c478bd9Sstevel@tonic-gate return (ret); /* Return final code */ 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate /* 10287c478bd9Sstevel@tonic-gate * ipv6_check_options - check that any IP-related options are OK, 10297c478bd9Sstevel@tonic-gate * and assign appropriate defaults. 10307c478bd9Sstevel@tonic-gate */ 10317c478bd9Sstevel@tonic-gate static void 10327c478bd9Sstevel@tonic-gate ipv6_check_options() 10337c478bd9Sstevel@tonic-gate { 10347c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[0]; 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate #if defined(SOL2) 10377c478bd9Sstevel@tonic-gate /* 10387c478bd9Sstevel@tonic-gate * Persistent link-local id is only used when user has not explicitly 10397c478bd9Sstevel@tonic-gate * configure/hard-code the id 10407c478bd9Sstevel@tonic-gate */ 10417c478bd9Sstevel@tonic-gate if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { 10427c478bd9Sstevel@tonic-gate 1043*48bbca81SDaniel Hoffman /* 10447c478bd9Sstevel@tonic-gate * On systems where there are no Ethernet interfaces used, there 10457c478bd9Sstevel@tonic-gate * may be other ways to obtain a persistent id. Right now, it 10467c478bd9Sstevel@tonic-gate * will fall back to using magic [see eui64_magic] below when 10477c478bd9Sstevel@tonic-gate * an EUI-48 from MAC address can't be obtained. Other possibilities 10487c478bd9Sstevel@tonic-gate * include obtaining EEPROM serial numbers, or some other unique 10497c478bd9Sstevel@tonic-gate * yet persistent number. On Sparc platforms, this is possible, 10507c478bd9Sstevel@tonic-gate * but too bad there's no standards yet for x86 machines. 10517c478bd9Sstevel@tonic-gate */ 10527c478bd9Sstevel@tonic-gate if (ether_to_eui64(&wo->ourid)) { 10537c478bd9Sstevel@tonic-gate wo->opt_local = 1; 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate #endif 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate /* 10597c478bd9Sstevel@tonic-gate * If ipv6cp-use-ipaddr is used, then both local and remote IPv4 10607c478bd9Sstevel@tonic-gate * addresses should be specified as options. Otherwise, since 10617c478bd9Sstevel@tonic-gate * ipcp has yet to negotiate the IPv4 addresses, the interface 10627c478bd9Sstevel@tonic-gate * identifiers will be based on meaningless values. 10637c478bd9Sstevel@tonic-gate */ 10647c478bd9Sstevel@tonic-gate if (wo->use_ip) { 10657c478bd9Sstevel@tonic-gate if ((ipcp_wantoptions[0].accept_local || 10667c478bd9Sstevel@tonic-gate ipcp_wantoptions[0].ouraddr == 0) && eui64_iszero(wo->ourid)) { 10677c478bd9Sstevel@tonic-gate warn("either IPv4 or IPv6 local address should be non-zero for ipv6cp-use-ipaddr"); 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate if ((ipcp_wantoptions[0].accept_remote || 10707c478bd9Sstevel@tonic-gate ipcp_wantoptions[0].hisaddr == 0) && eui64_iszero(wo->hisid)) { 10717c478bd9Sstevel@tonic-gate warn("either IPv4 or IPv6 remote address should be non-zero for ipv6cp-use-ipaddr"); 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate if (!wo->opt_local) { /* init interface identifier */ 10767c478bd9Sstevel@tonic-gate if (wo->use_ip && eui64_iszero(wo->ourid)) { 10777c478bd9Sstevel@tonic-gate eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr)); 10787c478bd9Sstevel@tonic-gate if (!eui64_iszero(wo->ourid)) 10797c478bd9Sstevel@tonic-gate wo->opt_local = 1; 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate while (eui64_iszero(wo->ourid)) 10837c478bd9Sstevel@tonic-gate eui64_magic(wo->ourid); 10847c478bd9Sstevel@tonic-gate } 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate if (!wo->opt_remote) { 10877c478bd9Sstevel@tonic-gate if (wo->use_ip && eui64_iszero(wo->hisid)) { 10887c478bd9Sstevel@tonic-gate eui64_setlo32(wo->hisid, ntohl(ipcp_wantoptions[0].hisaddr)); 10897c478bd9Sstevel@tonic-gate if (!eui64_iszero(wo->hisid)) 10907c478bd9Sstevel@tonic-gate wo->opt_remote = 1; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { 10957c478bd9Sstevel@tonic-gate fatal("local/remote LL address required for demand-dialling\n"); 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate /* 11017c478bd9Sstevel@tonic-gate * ipv6_demand_conf - configure the interface as though 11027c478bd9Sstevel@tonic-gate * IPV6CP were up, for use with dial-on-demand. 11037c478bd9Sstevel@tonic-gate */ 11047c478bd9Sstevel@tonic-gate static int 11057c478bd9Sstevel@tonic-gate ipv6_demand_conf(u) 11067c478bd9Sstevel@tonic-gate int u; 11077c478bd9Sstevel@tonic-gate { 11087c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[u]; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate #if SIF6UPFIRST 11117c478bd9Sstevel@tonic-gate if (!sif6up(u)) 11127c478bd9Sstevel@tonic-gate return 0; 1113*48bbca81SDaniel Hoffman #endif 11147c478bd9Sstevel@tonic-gate if (!sif6addr(u, wo->ourid, wo->hisid)) 11157c478bd9Sstevel@tonic-gate return 0; 11167c478bd9Sstevel@tonic-gate #if !SIF6UPFIRST 11177c478bd9Sstevel@tonic-gate if (!sif6up(u)) 11187c478bd9Sstevel@tonic-gate return 0; 11197c478bd9Sstevel@tonic-gate #endif 11207c478bd9Sstevel@tonic-gate if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) 11217c478bd9Sstevel@tonic-gate return 0; 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate notice("local LL address %s", llv6_ntoa(wo->ourid)); 11247c478bd9Sstevel@tonic-gate notice("remote LL address %s", llv6_ntoa(wo->hisid)); 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate return 1; 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate /* 11317c478bd9Sstevel@tonic-gate * ipv6cp_up - IPV6CP has come UP. 11327c478bd9Sstevel@tonic-gate * 11337c478bd9Sstevel@tonic-gate * Configure the IPv6 network interface appropriately and bring it up. 11347c478bd9Sstevel@tonic-gate */ 11357c478bd9Sstevel@tonic-gate static void 11367c478bd9Sstevel@tonic-gate ipv6cp_up(f) 11377c478bd9Sstevel@tonic-gate fsm *f; 11387c478bd9Sstevel@tonic-gate { 11397c478bd9Sstevel@tonic-gate ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit]; 11407c478bd9Sstevel@tonic-gate ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; 11417c478bd9Sstevel@tonic-gate ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp: up")); 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate /* 11467c478bd9Sstevel@tonic-gate * We must have a non-zero LL address for both ends of the link. 11477c478bd9Sstevel@tonic-gate */ 11487c478bd9Sstevel@tonic-gate if (!ho->neg_ifaceid) 11497c478bd9Sstevel@tonic-gate ho->hisid = wo->hisid; 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate if(!no_ifaceid_neg) { 11527c478bd9Sstevel@tonic-gate if (eui64_iszero(ho->hisid)) { 11537c478bd9Sstevel@tonic-gate error("Could not determine remote LL address"); 11547c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Could not determine remote LL address"); 11557c478bd9Sstevel@tonic-gate return; 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate if (eui64_iszero(go->ourid)) { 11587c478bd9Sstevel@tonic-gate error("Could not determine local LL address"); 11597c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Could not determine local LL address"); 11607c478bd9Sstevel@tonic-gate return; 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate if (eui64_equals(go->ourid, ho->hisid)) { 11637c478bd9Sstevel@tonic-gate error("local and remote LL addresses are equal"); 11647c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "local and remote LL addresses are equal"); 11657c478bd9Sstevel@tonic-gate return; 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate #ifdef IPV6CP_COMP 11707c478bd9Sstevel@tonic-gate /* set tcp compression */ 11717c478bd9Sstevel@tonic-gate if (sif6comp(f->unit, ho->neg_vj) != 1) { 11727c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Could not enable TCP compression"); 11737c478bd9Sstevel@tonic-gate return; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate #endif 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate /* 11787c478bd9Sstevel@tonic-gate * If we are doing dial-on-demand, the interface is already 11797c478bd9Sstevel@tonic-gate * configured, so we put out any saved-up packets, then set the 11807c478bd9Sstevel@tonic-gate * interface to pass IPv6 packets. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate if (demand) { 11837c478bd9Sstevel@tonic-gate if (! eui64_equals(go->ourid, wo->ourid) || 11847c478bd9Sstevel@tonic-gate ! eui64_equals(ho->hisid, wo->hisid)) { 11857c478bd9Sstevel@tonic-gate if (! eui64_equals(go->ourid, wo->ourid)) 11867c478bd9Sstevel@tonic-gate warn("Local LL address changed to %s", 11877c478bd9Sstevel@tonic-gate llv6_ntoa(go->ourid)); 11887c478bd9Sstevel@tonic-gate if (! eui64_equals(ho->hisid, wo->hisid)) 11897c478bd9Sstevel@tonic-gate warn("Remote LL address changed to %s", 11907c478bd9Sstevel@tonic-gate llv6_ntoa(ho->hisid)); 11917c478bd9Sstevel@tonic-gate ipv6cp_clear_addrs(f->unit, go->ourid, ho->hisid); 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate /* Set the interface to the new addresses */ 11947c478bd9Sstevel@tonic-gate if (!sif6addr(f->unit, go->ourid, ho->hisid)) { 11957c478bd9Sstevel@tonic-gate if (debug) 11967c478bd9Sstevel@tonic-gate warn("sif6addr failed"); 11977c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 11987c478bd9Sstevel@tonic-gate return; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate demand_rexmit(PPP_IPV6); 12037c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS) != 1) { 12047c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 12057c478bd9Sstevel@tonic-gate return; 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate } else { 12097c478bd9Sstevel@tonic-gate /* 12107c478bd9Sstevel@tonic-gate * Set LL addresses 12117c478bd9Sstevel@tonic-gate */ 12127c478bd9Sstevel@tonic-gate #if !SIF6UPFIRST 12137c478bd9Sstevel@tonic-gate if (!sif6addr(f->unit, go->ourid, ho->hisid)) { 12147c478bd9Sstevel@tonic-gate if (debug) 12157c478bd9Sstevel@tonic-gate warn("sif6addr failed"); 12167c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 12177c478bd9Sstevel@tonic-gate return; 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate #endif 12207c478bd9Sstevel@tonic-gate #if defined(SOL2) 12217c478bd9Sstevel@tonic-gate /* bring the interface up for IPv6 */ 12227c478bd9Sstevel@tonic-gate if (!sif6up(f->unit)) { 12237c478bd9Sstevel@tonic-gate if (debug) 12247c478bd9Sstevel@tonic-gate warn("sifup failed (IPV6)"); 12257c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 12267c478bd9Sstevel@tonic-gate return; 12277c478bd9Sstevel@tonic-gate } 12287c478bd9Sstevel@tonic-gate #else 12297c478bd9Sstevel@tonic-gate if (!sifup(f->unit)) { 12307c478bd9Sstevel@tonic-gate if (debug) 12317c478bd9Sstevel@tonic-gate warn("sifup failed (IPV6)"); 12327c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 12337c478bd9Sstevel@tonic-gate return; 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate #endif 12367c478bd9Sstevel@tonic-gate #if SIF6UPFIRST 12377c478bd9Sstevel@tonic-gate if (!sif6addr(f->unit, go->ourid, ho->hisid)) { 12387c478bd9Sstevel@tonic-gate if (debug) 12397c478bd9Sstevel@tonic-gate warn("sif6addr failed"); 12407c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 12417c478bd9Sstevel@tonic-gate return; 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate #endif 12447c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS) != 1) { 12457c478bd9Sstevel@tonic-gate ipv6cp_close(f->unit, "Interface configuration failed"); 12467c478bd9Sstevel@tonic-gate return; 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate notice("local LL address %s", llv6_ntoa(go->ourid)); 12507c478bd9Sstevel@tonic-gate notice("remote LL address %s", llv6_ntoa(ho->hisid)); 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate np_up(f->unit, PPP_IPV6); 12547c478bd9Sstevel@tonic-gate ipv6cp_is_up = 1; 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* 12577c478bd9Sstevel@tonic-gate * Execute the ipv6-up script, like this: 12587c478bd9Sstevel@tonic-gate * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL 12597c478bd9Sstevel@tonic-gate */ 12607c478bd9Sstevel@tonic-gate script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); 12617c478bd9Sstevel@tonic-gate script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); 12627c478bd9Sstevel@tonic-gate if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { 12637c478bd9Sstevel@tonic-gate ipv6cp_script_state = s_up; 12647c478bd9Sstevel@tonic-gate ipv6cp_script(_PATH_IPV6UP); 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate sys_unblock_proto(PPP_IPV6); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate /* 12717c478bd9Sstevel@tonic-gate * ipv6cp_down - IPV6CP has gone DOWN. 12727c478bd9Sstevel@tonic-gate * 12737c478bd9Sstevel@tonic-gate * Take the IPv6 network interface down, clear its addresses 12747c478bd9Sstevel@tonic-gate * and delete routes through it. 12757c478bd9Sstevel@tonic-gate */ 12767c478bd9Sstevel@tonic-gate static void 12777c478bd9Sstevel@tonic-gate ipv6cp_down(f) 12787c478bd9Sstevel@tonic-gate fsm *f; 12797c478bd9Sstevel@tonic-gate { 12807c478bd9Sstevel@tonic-gate IPV6CPDEBUG(("ipv6cp: down")); 12817c478bd9Sstevel@tonic-gate update_link_stats(f->unit); 12827c478bd9Sstevel@tonic-gate if (ipv6cp_is_up) { 12837c478bd9Sstevel@tonic-gate ipv6cp_is_up = 0; 12847c478bd9Sstevel@tonic-gate np_down(f->unit, PPP_IPV6); 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate #ifdef IPV6CP_COMP 12877c478bd9Sstevel@tonic-gate if (sif6comp(f->unit, 0) != 1) { 12887c478bd9Sstevel@tonic-gate if (debug) 12897c478bd9Sstevel@tonic-gate warn("Failed to disable TCP compression."); 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate #endif 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate /* 12947c478bd9Sstevel@tonic-gate * If we are doing dial-on-demand, set the interface 12957c478bd9Sstevel@tonic-gate * to queue up outgoing packets (for now). 12967c478bd9Sstevel@tonic-gate */ 12977c478bd9Sstevel@tonic-gate if (demand) { 12987c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IPV6, NPMODE_QUEUE) != 1) { 12997c478bd9Sstevel@tonic-gate if (debug) 13007c478bd9Sstevel@tonic-gate warn("Failed to enable queueing on outgoing packets."); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate } else { 13037c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IPV6, NPMODE_ERROR) != 1) { 13047c478bd9Sstevel@tonic-gate if (debug) 13057c478bd9Sstevel@tonic-gate warn("Could not set interface to drop packets."); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate #if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC))) 13087c478bd9Sstevel@tonic-gate #if defined(SOL2) 13097c478bd9Sstevel@tonic-gate if (sif6down(f->unit) != 1) 13107c478bd9Sstevel@tonic-gate warn("Couldn not bring interface down."); 13117c478bd9Sstevel@tonic-gate #else 13127c478bd9Sstevel@tonic-gate if (sifdown(f->unit) != 1) 13137c478bd9Sstevel@tonic-gate warn("Could not bring interface down."); 13147c478bd9Sstevel@tonic-gate #endif /* defined(SOL2) */ 13157c478bd9Sstevel@tonic-gate #endif 13167c478bd9Sstevel@tonic-gate ipv6cp_clear_addrs(f->unit, 13177c478bd9Sstevel@tonic-gate ipv6cp_gotoptions[f->unit].ourid, 13187c478bd9Sstevel@tonic-gate ipv6cp_hisoptions[f->unit].hisid); 13197c478bd9Sstevel@tonic-gate #if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC))) 13207c478bd9Sstevel@tonic-gate if (sifdown(f->unit) != 1) 13217c478bd9Sstevel@tonic-gate warn("Could not bring interface down."); 13227c478bd9Sstevel@tonic-gate #endif 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate /* Execute the ipv6-down script */ 13267c478bd9Sstevel@tonic-gate if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { 13277c478bd9Sstevel@tonic-gate ipv6cp_script_state = s_down; 13287c478bd9Sstevel@tonic-gate ipv6cp_script(_PATH_IPV6DOWN); 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate /* 13347c478bd9Sstevel@tonic-gate * ipv6cp_clear_addrs() - clear the interface addresses, routes, 13357c478bd9Sstevel@tonic-gate * proxy neighbour discovery entries, etc. 13367c478bd9Sstevel@tonic-gate */ 13377c478bd9Sstevel@tonic-gate static void 13387c478bd9Sstevel@tonic-gate ipv6cp_clear_addrs(unit, ourid, hisid) 13397c478bd9Sstevel@tonic-gate int unit; 13407c478bd9Sstevel@tonic-gate eui64_t ourid; 13417c478bd9Sstevel@tonic-gate eui64_t hisid; 13427c478bd9Sstevel@tonic-gate { 13437c478bd9Sstevel@tonic-gate if (cif6addr(unit, ourid, hisid) != 1) 13447c478bd9Sstevel@tonic-gate warn("Could not clear addresses"); 13457c478bd9Sstevel@tonic-gate } 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * ipv6cp_finished - possibly shut down the lower layers. 13507c478bd9Sstevel@tonic-gate */ 13517c478bd9Sstevel@tonic-gate static void 13527c478bd9Sstevel@tonic-gate ipv6cp_finished(f) 13537c478bd9Sstevel@tonic-gate fsm *f; 13547c478bd9Sstevel@tonic-gate { 13557c478bd9Sstevel@tonic-gate np_finished(f->unit, PPP_IPV6); 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate /* 13607c478bd9Sstevel@tonic-gate * ipv6cp_script_done - called when the ipv6-up or ipv6-down script 13617c478bd9Sstevel@tonic-gate * has finished. 13627c478bd9Sstevel@tonic-gate */ 13637c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 13647c478bd9Sstevel@tonic-gate static void 13657c478bd9Sstevel@tonic-gate ipv6cp_script_done(arg, status) 13667c478bd9Sstevel@tonic-gate void *arg; 13677c478bd9Sstevel@tonic-gate int status; 13687c478bd9Sstevel@tonic-gate { 13697c478bd9Sstevel@tonic-gate ipv6cp_script_pid = 0; 13707c478bd9Sstevel@tonic-gate switch (ipv6cp_script_state) { 13717c478bd9Sstevel@tonic-gate case s_up: 13727c478bd9Sstevel@tonic-gate if (ipv6cp_fsm[0].state != OPENED) { 13737c478bd9Sstevel@tonic-gate ipv6cp_script_state = s_down; 13747c478bd9Sstevel@tonic-gate ipv6cp_script(_PATH_IPV6DOWN); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate break; 13777c478bd9Sstevel@tonic-gate case s_down: 13787c478bd9Sstevel@tonic-gate if (ipv6cp_fsm[0].state == OPENED) { 13797c478bd9Sstevel@tonic-gate ipv6cp_script_state = s_up; 13807c478bd9Sstevel@tonic-gate ipv6cp_script(_PATH_IPV6UP); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate break; 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate /* 13887c478bd9Sstevel@tonic-gate * ipv6cp_script - Execute a script with arguments 13897c478bd9Sstevel@tonic-gate * interface-name tty-name speed local-LL remote-LL. 13907c478bd9Sstevel@tonic-gate */ 13917c478bd9Sstevel@tonic-gate static void 13927c478bd9Sstevel@tonic-gate ipv6cp_script(script) 13937c478bd9Sstevel@tonic-gate char *script; 13947c478bd9Sstevel@tonic-gate { 13957c478bd9Sstevel@tonic-gate char strspeed[32], strlocal[26], strremote[26]; 13967c478bd9Sstevel@tonic-gate char *argv[8]; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate (void) slprintf(strspeed, sizeof (strspeed), "%d", baud_rate); 13997c478bd9Sstevel@tonic-gate (void) strlcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid), 14007c478bd9Sstevel@tonic-gate sizeof (strlocal)); 14017c478bd9Sstevel@tonic-gate (void) strlcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid), 14027c478bd9Sstevel@tonic-gate sizeof (strremote)); 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate argv[0] = script; 14057c478bd9Sstevel@tonic-gate argv[1] = ifname; 14067c478bd9Sstevel@tonic-gate argv[2] = devnam; 14077c478bd9Sstevel@tonic-gate argv[3] = strspeed; 14087c478bd9Sstevel@tonic-gate argv[4] = strlocal; 14097c478bd9Sstevel@tonic-gate argv[5] = strremote; 14107c478bd9Sstevel@tonic-gate argv[6] = ipparam; 14117c478bd9Sstevel@tonic-gate argv[7] = NULL; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, NULL); 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate static int 14177c478bd9Sstevel@tonic-gate ipv6cp_printpkt(p, plen, printer, arg) 14187c478bd9Sstevel@tonic-gate u_char *p; 14197c478bd9Sstevel@tonic-gate int plen; 14207c478bd9Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)); 14217c478bd9Sstevel@tonic-gate void *arg; 14227c478bd9Sstevel@tonic-gate { 14237c478bd9Sstevel@tonic-gate int code, id, len, olen; 14247c478bd9Sstevel@tonic-gate u_char *pstart, *optend; 14257c478bd9Sstevel@tonic-gate u_short cishort; 14267c478bd9Sstevel@tonic-gate eui64_t ifaceid; 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate if (plen < HEADERLEN) 14297c478bd9Sstevel@tonic-gate return 0; 14307c478bd9Sstevel@tonic-gate pstart = p; 14317c478bd9Sstevel@tonic-gate GETCHAR(code, p); 14327c478bd9Sstevel@tonic-gate GETCHAR(id, p); 14337c478bd9Sstevel@tonic-gate GETSHORT(len, p); 14347c478bd9Sstevel@tonic-gate if (len < HEADERLEN || len > plen) 14357c478bd9Sstevel@tonic-gate return 0; 14367c478bd9Sstevel@tonic-gate 1437*48bbca81SDaniel Hoffman 14387c478bd9Sstevel@tonic-gate printer(arg, " %s id=0x%x", code_name(code, 1), id); 14397c478bd9Sstevel@tonic-gate len -= HEADERLEN; 14407c478bd9Sstevel@tonic-gate switch (code) { 14417c478bd9Sstevel@tonic-gate case CODE_CONFREQ: 14427c478bd9Sstevel@tonic-gate case CODE_CONFACK: 14437c478bd9Sstevel@tonic-gate case CODE_CONFNAK: 14447c478bd9Sstevel@tonic-gate case CODE_CONFREJ: 14457c478bd9Sstevel@tonic-gate /* print option list */ 14467c478bd9Sstevel@tonic-gate while (len >= 2) { 14477c478bd9Sstevel@tonic-gate GETCHAR(code, p); 14487c478bd9Sstevel@tonic-gate GETCHAR(olen, p); 14497c478bd9Sstevel@tonic-gate p -= 2; 14507c478bd9Sstevel@tonic-gate if (olen < 2 || olen > len) { 14517c478bd9Sstevel@tonic-gate break; 14527c478bd9Sstevel@tonic-gate } 14537c478bd9Sstevel@tonic-gate printer(arg, " <"); 14547c478bd9Sstevel@tonic-gate len -= olen; 14557c478bd9Sstevel@tonic-gate optend = p + olen; 14567c478bd9Sstevel@tonic-gate switch (code) { 14577c478bd9Sstevel@tonic-gate case CI_COMPRESSTYPE: 14587c478bd9Sstevel@tonic-gate if (olen >= CILEN_COMPRESS) { 14597c478bd9Sstevel@tonic-gate p += 2; 14607c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); 14617c478bd9Sstevel@tonic-gate printer(arg, "compress 0x%x", cishort); 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate break; 14647c478bd9Sstevel@tonic-gate case CI_IFACEID: 14657c478bd9Sstevel@tonic-gate if (olen == CILEN_IFACEID) { 14667c478bd9Sstevel@tonic-gate p += 2; 14677c478bd9Sstevel@tonic-gate eui64_get(ifaceid, p); 14687c478bd9Sstevel@tonic-gate printer(arg, "addr %s", llv6_ntoa(ifaceid)); 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate break; 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate printer(arg, "%8.*B>", optend-p, p); 14737c478bd9Sstevel@tonic-gate p = optend; 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate break; 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate case CODE_TERMACK: 14787c478bd9Sstevel@tonic-gate case CODE_TERMREQ: 14797c478bd9Sstevel@tonic-gate if (len > 0 && *p >= ' ' && *p < 0x7f) { 14807c478bd9Sstevel@tonic-gate printer(arg, " "); 14817c478bd9Sstevel@tonic-gate print_string((char *)p, len, printer, arg); 14827c478bd9Sstevel@tonic-gate p += len; 14837c478bd9Sstevel@tonic-gate len = 0; 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate break; 14867c478bd9Sstevel@tonic-gate } 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate /* print the rest of the bytes in the packet */ 14897c478bd9Sstevel@tonic-gate printer(arg, " %32.*B", len, p); 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate return p - pstart; 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate /* 14957c478bd9Sstevel@tonic-gate * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. 14967c478bd9Sstevel@tonic-gate * We don't bring the link up for IP fragments or for TCP FIN packets 14977c478bd9Sstevel@tonic-gate * with no data. 14987c478bd9Sstevel@tonic-gate */ 14997c478bd9Sstevel@tonic-gate #define TCP_HDRLEN 20 15007c478bd9Sstevel@tonic-gate #define TH_FIN 0x01 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate static int 15037c478bd9Sstevel@tonic-gate ipv6_active_pkt(pkt, len) 15047c478bd9Sstevel@tonic-gate u_char *pkt; 15057c478bd9Sstevel@tonic-gate int len; 15067c478bd9Sstevel@tonic-gate { 15077c478bd9Sstevel@tonic-gate u_char *tcp; 1508f53eecf5SJames Carlson struct in6_addr addr; 1509f53eecf5SJames Carlson char fromstr[26]; 1510f53eecf5SJames Carlson char tostr[26]; 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate len -= PPP_HDRLEN; 15137c478bd9Sstevel@tonic-gate pkt += PPP_HDRLEN; 1514f53eecf5SJames Carlson if (len < IP6_HDRLEN) { 1515f53eecf5SJames Carlson dbglog("IPv6 packet of length %d is not activity", len); 15167c478bd9Sstevel@tonic-gate return 0; 1517f53eecf5SJames Carlson } 1518f53eecf5SJames Carlson (void) BCOPY(get_ip6src(pkt), &addr, sizeof (addr)); 1519f53eecf5SJames Carlson (void) inet_ntop(AF_INET6, &addr, fromstr, 26); 1520f53eecf5SJames Carlson (void) BCOPY(get_ip6dst(pkt), &addr, sizeof (addr)); 1521f53eecf5SJames Carlson (void) inet_ntop(AF_INET6, &addr, tostr, 26); 1522f53eecf5SJames Carlson if (get_ip6nh(pkt) == IPPROTO_FRAGMENT) { 1523f53eecf5SJames Carlson dbglog("IPv6 fragment from %s->%s is not activity", fromstr, tostr); 15247c478bd9Sstevel@tonic-gate return 0; 1525f53eecf5SJames Carlson } 1526f53eecf5SJames Carlson if (get_ip6nh(pkt) != IPPROTO_TCP) { 1527f53eecf5SJames Carlson info("IPv6 proto %d from %s->%s is activity", get_ip6nh(pkt), fromstr, 1528f53eecf5SJames Carlson tostr); 15297c478bd9Sstevel@tonic-gate return 1; 1530f53eecf5SJames Carlson } 1531f53eecf5SJames Carlson if (len < IP6_HDRLEN + TCP_HDRLEN) { 1532f53eecf5SJames Carlson dbglog("Bad TCP length %d<%d+%d %s->%s is not activity", len, 1533f53eecf5SJames Carlson IP6_HDRLEN, TCP_HDRLEN, fromstr, tostr); 15347c478bd9Sstevel@tonic-gate return 0; 1535f53eecf5SJames Carlson } 15367c478bd9Sstevel@tonic-gate tcp = pkt + IP6_HDRLEN; 15377c478bd9Sstevel@tonic-gate if ((get_tcpflags(tcp) & TH_FIN) != 0 && 1538f53eecf5SJames Carlson len == IP6_HDRLEN + get_tcpoff(tcp) * 4) { 1539f53eecf5SJames Carlson dbglog("Empty TCP FIN %s->%s is not activity", fromstr, tostr); 15407c478bd9Sstevel@tonic-gate return 0; 1541f53eecf5SJames Carlson } 1542f53eecf5SJames Carlson info("TCP %d data %s%s->%s is activity", len - IP6_HDRLEN - TCP_HDRLEN, 1543f53eecf5SJames Carlson tcp_flag_decode(get_tcpflags(tcp)), fromstr, tostr); 15447c478bd9Sstevel@tonic-gate return 1; 15457c478bd9Sstevel@tonic-gate } 1546