1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * ipcp.c - PPP IP Control Protocol. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 5*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * Copyright (c) 1989 Carnegie Mellon University. 8*7c478bd9Sstevel@tonic-gate * All rights reserved. 9*7c478bd9Sstevel@tonic-gate * 10*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 11*7c478bd9Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are 12*7c478bd9Sstevel@tonic-gate * duplicated in all such forms and that any documentation, 13*7c478bd9Sstevel@tonic-gate * advertising materials, and other materials related to such 14*7c478bd9Sstevel@tonic-gate * distribution and use acknowledge that the software was developed 15*7c478bd9Sstevel@tonic-gate * by Carnegie Mellon University. The name of the 16*7c478bd9Sstevel@tonic-gate * University may not be used to endorse or promote products derived 17*7c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 18*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 19*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 20*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 24*7c478bd9Sstevel@tonic-gate #define RCSID "$Id: ipcp.c,v 1.54 2000/04/15 01:27:11 masputra Exp $" 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * TODO: 28*7c478bd9Sstevel@tonic-gate */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <string.h> 32*7c478bd9Sstevel@tonic-gate #include <netdb.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 36*7c478bd9Sstevel@tonic-gate #if defined(_linux_) || defined(__linux__) 37*7c478bd9Sstevel@tonic-gate #define __FAVOR_BSD 38*7c478bd9Sstevel@tonic-gate #endif 39*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 40*7c478bd9Sstevel@tonic-gate #include <netinet/tcp.h> 41*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include "pppd.h" 44*7c478bd9Sstevel@tonic-gate #include "fsm.h" 45*7c478bd9Sstevel@tonic-gate #include "ipcp.h" 46*7c478bd9Sstevel@tonic-gate #include "pathnames.h" 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 49*7c478bd9Sstevel@tonic-gate static const char rcsid[] = RCSID; 50*7c478bd9Sstevel@tonic-gate #endif 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* global vars */ 53*7c478bd9Sstevel@tonic-gate ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ 54*7c478bd9Sstevel@tonic-gate ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 55*7c478bd9Sstevel@tonic-gate ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 56*7c478bd9Sstevel@tonic-gate ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate bool ipcp_from_hostname = 0; /* Local IP address is from hostname lookup */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* Hook for a plugin to know when IP protocol has come up */ 61*7c478bd9Sstevel@tonic-gate void (*ip_up_hook) __P((void)) = NULL; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* Hook for a plugin to know when IP protocol has come down */ 64*7c478bd9Sstevel@tonic-gate void (*ip_down_hook) __P((void)) = NULL; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate /* local vars */ 67*7c478bd9Sstevel@tonic-gate static bool default_route_set[NUM_PPP]; /* Have set up a default route */ 68*7c478bd9Sstevel@tonic-gate static bool proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ 69*7c478bd9Sstevel@tonic-gate static bool ipcp_is_up[NUM_PPP]; /* have called np_up() */ 70*7c478bd9Sstevel@tonic-gate static bool proxy_arp_quiet[NUM_PPP]; /* We should be quiet on error */ 71*7c478bd9Sstevel@tonic-gate static bool disable_defaultip = 0; /* Don't use hostname for IP addr */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Callbacks for fsm code. (CI = Configuration Information) 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate static void ipcp_resetci __P((fsm *)); /* Reset our CI */ 77*7c478bd9Sstevel@tonic-gate static int ipcp_cilen __P((fsm *)); /* Return length of our CI */ 78*7c478bd9Sstevel@tonic-gate static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ 79*7c478bd9Sstevel@tonic-gate static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ 80*7c478bd9Sstevel@tonic-gate static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ 81*7c478bd9Sstevel@tonic-gate static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ 82*7c478bd9Sstevel@tonic-gate static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ 83*7c478bd9Sstevel@tonic-gate static void ipcp_up __P((fsm *)); /* We're UP */ 84*7c478bd9Sstevel@tonic-gate static void ipcp_down __P((fsm *)); /* We're DOWN */ 85*7c478bd9Sstevel@tonic-gate static void ipcp_finished __P((fsm *)); /* Don't need lower layer */ 86*7c478bd9Sstevel@tonic-gate static int setmsservaddr __P((char *, u_int32_t *)); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ 91*7c478bd9Sstevel@tonic-gate ipcp_resetci, /* Reset our Configuration Information */ 92*7c478bd9Sstevel@tonic-gate ipcp_cilen, /* Length of our Configuration Information */ 93*7c478bd9Sstevel@tonic-gate ipcp_addci, /* Add our Configuration Information */ 94*7c478bd9Sstevel@tonic-gate ipcp_ackci, /* ACK our Configuration Information */ 95*7c478bd9Sstevel@tonic-gate ipcp_nakci, /* NAK our Configuration Information */ 96*7c478bd9Sstevel@tonic-gate ipcp_rejci, /* Reject our Configuration Information */ 97*7c478bd9Sstevel@tonic-gate ipcp_reqci, /* Request peer's Configuration Information */ 98*7c478bd9Sstevel@tonic-gate ipcp_up, /* Called when fsm reaches OPENED state */ 99*7c478bd9Sstevel@tonic-gate ipcp_down, /* Called when fsm leaves OPENED state */ 100*7c478bd9Sstevel@tonic-gate NULL, /* Called when we want the lower layer up */ 101*7c478bd9Sstevel@tonic-gate ipcp_finished, /* Called when we want the lower layer down */ 102*7c478bd9Sstevel@tonic-gate NULL, /* Retransmission is necessary */ 103*7c478bd9Sstevel@tonic-gate NULL, /* Called to handle protocol-specific codes */ 104*7c478bd9Sstevel@tonic-gate "IPCP", /* String name of protocol */ 105*7c478bd9Sstevel@tonic-gate NULL /* Peer rejected a code number */ 106*7c478bd9Sstevel@tonic-gate }; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * Command-line options. 110*7c478bd9Sstevel@tonic-gate */ 111*7c478bd9Sstevel@tonic-gate static int setvjslots __P((char **)); 112*7c478bd9Sstevel@tonic-gate static int setdnsaddr __P((char **)); 113*7c478bd9Sstevel@tonic-gate static int setwinsaddr __P((char **)); 114*7c478bd9Sstevel@tonic-gate static int autoproxyarp __P((char **)); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate static option_t ipcp_option_list[] = { 117*7c478bd9Sstevel@tonic-gate { "noip", o_bool, &ipcp_protent.enabled_flag, 118*7c478bd9Sstevel@tonic-gate "Disable IP and IPCP" }, 119*7c478bd9Sstevel@tonic-gate { "-ip", o_bool, &ipcp_protent.enabled_flag, 120*7c478bd9Sstevel@tonic-gate "Disable IP and IPCP" }, 121*7c478bd9Sstevel@tonic-gate { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, 122*7c478bd9Sstevel@tonic-gate "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, 123*7c478bd9Sstevel@tonic-gate { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, 124*7c478bd9Sstevel@tonic-gate "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, 125*7c478bd9Sstevel@tonic-gate { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, 126*7c478bd9Sstevel@tonic-gate "Disable VJ connection-ID compression", OPT_A2COPY, 127*7c478bd9Sstevel@tonic-gate &ipcp_allowoptions[0].cflag }, 128*7c478bd9Sstevel@tonic-gate { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, 129*7c478bd9Sstevel@tonic-gate "Disable VJ connection-ID compression", OPT_A2COPY, 130*7c478bd9Sstevel@tonic-gate &ipcp_allowoptions[0].cflag }, 131*7c478bd9Sstevel@tonic-gate { "vj-max-slots", o_special, (void *)setvjslots, 132*7c478bd9Sstevel@tonic-gate "Set maximum VJ header slots" }, 133*7c478bd9Sstevel@tonic-gate { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, 134*7c478bd9Sstevel@tonic-gate "Accept peer's address for us", 1 }, 135*7c478bd9Sstevel@tonic-gate { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, 136*7c478bd9Sstevel@tonic-gate "Accept peer's address for it", 1 }, 137*7c478bd9Sstevel@tonic-gate { "ipparam", o_string, &ipparam, 138*7c478bd9Sstevel@tonic-gate "Set ip script parameter" }, 139*7c478bd9Sstevel@tonic-gate { "noipdefault", o_bool, &disable_defaultip, 140*7c478bd9Sstevel@tonic-gate "Don't use name for default IP adrs", 1 }, 141*7c478bd9Sstevel@tonic-gate { "ms-dns", o_special, (void *)setdnsaddr, 142*7c478bd9Sstevel@tonic-gate "DNS address for the peer's use" }, 143*7c478bd9Sstevel@tonic-gate { "ms-wins", o_special, (void *)setwinsaddr, 144*7c478bd9Sstevel@tonic-gate "Nameserver for SMB over TCP/IP for peer" }, 145*7c478bd9Sstevel@tonic-gate { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, 146*7c478bd9Sstevel@tonic-gate "Set timeout for IPCP" }, 147*7c478bd9Sstevel@tonic-gate { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, 148*7c478bd9Sstevel@tonic-gate "Set max #xmits for term-reqs" }, 149*7c478bd9Sstevel@tonic-gate { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, 150*7c478bd9Sstevel@tonic-gate "Set max #xmits for conf-reqs" }, 151*7c478bd9Sstevel@tonic-gate { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, 152*7c478bd9Sstevel@tonic-gate "Set max #conf-naks for IPCP" }, 153*7c478bd9Sstevel@tonic-gate { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, 154*7c478bd9Sstevel@tonic-gate "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, 155*7c478bd9Sstevel@tonic-gate { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, 156*7c478bd9Sstevel@tonic-gate "disable defaultroute option", OPT_A2COPY, 157*7c478bd9Sstevel@tonic-gate &ipcp_wantoptions[0].default_route }, 158*7c478bd9Sstevel@tonic-gate { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, 159*7c478bd9Sstevel@tonic-gate "disable defaultroute option", OPT_A2COPY, 160*7c478bd9Sstevel@tonic-gate &ipcp_wantoptions[0].default_route }, 161*7c478bd9Sstevel@tonic-gate { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, 162*7c478bd9Sstevel@tonic-gate "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, 163*7c478bd9Sstevel@tonic-gate { "autoproxyarp", o_special_noarg, (void *)autoproxyarp, 164*7c478bd9Sstevel@tonic-gate "Add proxy ARP entry if needed", OPT_ENABLE, 165*7c478bd9Sstevel@tonic-gate &ipcp_allowoptions[0].proxy_arp }, 166*7c478bd9Sstevel@tonic-gate { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 167*7c478bd9Sstevel@tonic-gate "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp }, 168*7c478bd9Sstevel@tonic-gate { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, 169*7c478bd9Sstevel@tonic-gate "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp }, 170*7c478bd9Sstevel@tonic-gate { "usepeerdns", o_bool, &ipcp_wantoptions[0].req_dns1, 171*7c478bd9Sstevel@tonic-gate "Ask peer for DNS address(es)", OPT_A2COPY|1, 172*7c478bd9Sstevel@tonic-gate &ipcp_wantoptions[0].req_dns2 }, 173*7c478bd9Sstevel@tonic-gate { NULL } 174*7c478bd9Sstevel@tonic-gate }; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Protocol entry points from main code. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate static void ipcp_init __P((int)); 180*7c478bd9Sstevel@tonic-gate static void ipcp_open __P((int)); 181*7c478bd9Sstevel@tonic-gate static void ipcp_close __P((int, char *)); 182*7c478bd9Sstevel@tonic-gate static void ipcp_lowerup __P((int)); 183*7c478bd9Sstevel@tonic-gate static void ipcp_lowerdown __P((int)); 184*7c478bd9Sstevel@tonic-gate static void ipcp_input __P((int, u_char *, int)); 185*7c478bd9Sstevel@tonic-gate static void ipcp_protrej __P((int)); 186*7c478bd9Sstevel@tonic-gate static int ipcp_printpkt __P((u_char *, int, 187*7c478bd9Sstevel@tonic-gate void (*) __P((void *, const char *, ...)), void *)); 188*7c478bd9Sstevel@tonic-gate static void ip_check_options __P((void)); 189*7c478bd9Sstevel@tonic-gate static int ip_demand_conf __P((int)); 190*7c478bd9Sstevel@tonic-gate static int ip_active_pkt __P((u_char *, int)); 191*7c478bd9Sstevel@tonic-gate static void ipcp_print_stat __P((int, FILE *)); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate static void create_resolv __P((u_int32_t, u_int32_t)); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate struct protent ipcp_protent = { 196*7c478bd9Sstevel@tonic-gate PPP_IPCP, 197*7c478bd9Sstevel@tonic-gate ipcp_init, 198*7c478bd9Sstevel@tonic-gate ipcp_input, 199*7c478bd9Sstevel@tonic-gate ipcp_protrej, 200*7c478bd9Sstevel@tonic-gate ipcp_lowerup, 201*7c478bd9Sstevel@tonic-gate ipcp_lowerdown, 202*7c478bd9Sstevel@tonic-gate ipcp_open, 203*7c478bd9Sstevel@tonic-gate ipcp_close, 204*7c478bd9Sstevel@tonic-gate ipcp_printpkt, 205*7c478bd9Sstevel@tonic-gate NULL, 206*7c478bd9Sstevel@tonic-gate 1, 207*7c478bd9Sstevel@tonic-gate "IPCP", 208*7c478bd9Sstevel@tonic-gate "IP", 209*7c478bd9Sstevel@tonic-gate ipcp_option_list, 210*7c478bd9Sstevel@tonic-gate ip_check_options, 211*7c478bd9Sstevel@tonic-gate ip_demand_conf, 212*7c478bd9Sstevel@tonic-gate ip_active_pkt, 213*7c478bd9Sstevel@tonic-gate ipcp_print_stat 214*7c478bd9Sstevel@tonic-gate }; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); 217*7c478bd9Sstevel@tonic-gate static void ipcp_script __P((char *)); /* Run an up/down script */ 218*7c478bd9Sstevel@tonic-gate static void ipcp_script_done __P((void *, int)); 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate /* 221*7c478bd9Sstevel@tonic-gate * Lengths of configuration options. 222*7c478bd9Sstevel@tonic-gate */ 223*7c478bd9Sstevel@tonic-gate #define CILEN_VOID 2 224*7c478bd9Sstevel@tonic-gate #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ 225*7c478bd9Sstevel@tonic-gate #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ 226*7c478bd9Sstevel@tonic-gate #define CILEN_ADDR 6 /* new-style single address option */ 227*7c478bd9Sstevel@tonic-gate #define CILEN_ADDRS 10 /* old-style dual address option */ 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* 231*7c478bd9Sstevel@tonic-gate * This state variable is used to ensure that we don't 232*7c478bd9Sstevel@tonic-gate * run an ipcp-up/down script while one is already running. 233*7c478bd9Sstevel@tonic-gate */ 234*7c478bd9Sstevel@tonic-gate static enum script_state { 235*7c478bd9Sstevel@tonic-gate s_down, 236*7c478bd9Sstevel@tonic-gate s_up 237*7c478bd9Sstevel@tonic-gate } ipcp_script_state; 238*7c478bd9Sstevel@tonic-gate static pid_t ipcp_script_pid; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * Make a string representation of a network IP address. 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate char * 244*7c478bd9Sstevel@tonic-gate ip_ntoa(ipaddr) 245*7c478bd9Sstevel@tonic-gate u_int32_t ipaddr; 246*7c478bd9Sstevel@tonic-gate { 247*7c478bd9Sstevel@tonic-gate static char b[64]; 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate (void) slprintf(b, sizeof(b), "%I", ipaddr); 250*7c478bd9Sstevel@tonic-gate return b; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * Option parsing. 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * setvjslots - set maximum number of connection slots for VJ compression 259*7c478bd9Sstevel@tonic-gate */ 260*7c478bd9Sstevel@tonic-gate static int 261*7c478bd9Sstevel@tonic-gate setvjslots(argv) 262*7c478bd9Sstevel@tonic-gate char **argv; 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate int value; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if (!int_option(*argv, &value)) 267*7c478bd9Sstevel@tonic-gate return 0; 268*7c478bd9Sstevel@tonic-gate if (value < 2 || value > 16) { 269*7c478bd9Sstevel@tonic-gate option_error("vj-max-slots value must be between 2 and 16"); 270*7c478bd9Sstevel@tonic-gate return 0; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate ipcp_wantoptions [0].maxslotindex = 273*7c478bd9Sstevel@tonic-gate ipcp_allowoptions[0].maxslotindex = value - 1; 274*7c478bd9Sstevel@tonic-gate return 1; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate /* 278*7c478bd9Sstevel@tonic-gate * setmsservaddr - Set the primary and secondary server addresses in the 279*7c478bd9Sstevel@tonic-gate * array. setdnsaddr() and setwinsaddr() call this function with either 280*7c478bd9Sstevel@tonic-gate * dnsaddr[] or winsaddr[] as the serverarray argument. 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate static int 283*7c478bd9Sstevel@tonic-gate setmsservaddr(servname, serverarray) 284*7c478bd9Sstevel@tonic-gate char *servname; 285*7c478bd9Sstevel@tonic-gate u_int32_t *serverarray; 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate u_int32_t addr; 288*7c478bd9Sstevel@tonic-gate struct hostent *hp = NULL; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate addr = inet_addr(servname); 291*7c478bd9Sstevel@tonic-gate if (addr == (u_int32_t) -1) { 292*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(servname)) == NULL) 293*7c478bd9Sstevel@tonic-gate return 0; 294*7c478bd9Sstevel@tonic-gate BCOPY(hp->h_addr, &addr, sizeof (u_int32_t)); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* 298*7c478bd9Sstevel@tonic-gate * If there is no primary then this is the first instance of the 299*7c478bd9Sstevel@tonic-gate * option, we must set the primary. In that case, try to set the 300*7c478bd9Sstevel@tonic-gate * secondary to h_addr_list[1]. If the primary is already set, then 301*7c478bd9Sstevel@tonic-gate * this is the second instance of the option, and we must set 302*7c478bd9Sstevel@tonic-gate * the secondary. 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate if (serverarray[0] == 0) { 305*7c478bd9Sstevel@tonic-gate serverarray[0] = addr; 306*7c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_addr_list[1] != NULL) 307*7c478bd9Sstevel@tonic-gate BCOPY(hp->h_addr_list[1], &serverarray[1], sizeof (u_int32_t)); 308*7c478bd9Sstevel@tonic-gate else 309*7c478bd9Sstevel@tonic-gate serverarray[1] = addr; 310*7c478bd9Sstevel@tonic-gate } else { 311*7c478bd9Sstevel@tonic-gate serverarray[1] = addr; 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate return (1); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * setdnsaddr - set the dns address(es) 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate static int 321*7c478bd9Sstevel@tonic-gate setdnsaddr(argv) 322*7c478bd9Sstevel@tonic-gate char **argv; 323*7c478bd9Sstevel@tonic-gate { 324*7c478bd9Sstevel@tonic-gate if (setmsservaddr(*argv, &(ipcp_allowoptions[0].dnsaddr[0])) == 0) { 325*7c478bd9Sstevel@tonic-gate option_error("invalid address parameter '%s' for ms-dns option", *argv); 326*7c478bd9Sstevel@tonic-gate return (0); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate return (1); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * setwinsaddr - set the wins address(es) 334*7c478bd9Sstevel@tonic-gate * This is primrarly used with the Samba package under UNIX or for pointing 335*7c478bd9Sstevel@tonic-gate * the caller to the existing WINS server on a Windows NT platform. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate static int 338*7c478bd9Sstevel@tonic-gate setwinsaddr(argv) 339*7c478bd9Sstevel@tonic-gate char **argv; 340*7c478bd9Sstevel@tonic-gate { 341*7c478bd9Sstevel@tonic-gate if (setmsservaddr(*argv, &(ipcp_allowoptions[0].winsaddr[0])) == 0) { 342*7c478bd9Sstevel@tonic-gate option_error("invalid address parameter '%s' for ms-wins option", 343*7c478bd9Sstevel@tonic-gate *argv); 344*7c478bd9Sstevel@tonic-gate return (0); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate return (1); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * autoproxyarp -- enable proxy ARP but don't emit error messages if 352*7c478bd9Sstevel@tonic-gate * it's not actually needed. 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 355*7c478bd9Sstevel@tonic-gate static int 356*7c478bd9Sstevel@tonic-gate autoproxyarp(argv) 357*7c478bd9Sstevel@tonic-gate char **argv; 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate ipcp_wantoptions[0].proxy_arp = 1; 360*7c478bd9Sstevel@tonic-gate proxy_arp_quiet[0] = 1; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate return (1); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * ipcp_init - Initialize IPCP. 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate static void 370*7c478bd9Sstevel@tonic-gate ipcp_init(unit) 371*7c478bd9Sstevel@tonic-gate int unit; 372*7c478bd9Sstevel@tonic-gate { 373*7c478bd9Sstevel@tonic-gate fsm *f = &ipcp_fsm[unit]; 374*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[unit]; 375*7c478bd9Sstevel@tonic-gate ipcp_options *ao = &ipcp_allowoptions[unit]; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate f->unit = unit; 378*7c478bd9Sstevel@tonic-gate f->protocol = PPP_IPCP; 379*7c478bd9Sstevel@tonic-gate f->callbacks = &ipcp_callbacks; 380*7c478bd9Sstevel@tonic-gate fsm_init(&ipcp_fsm[unit]); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate BZERO(wo, sizeof(*wo)); 383*7c478bd9Sstevel@tonic-gate BZERO(ao, sizeof(*ao)); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate wo->neg_addr = 1; 386*7c478bd9Sstevel@tonic-gate wo->neg_vj = 1; 387*7c478bd9Sstevel@tonic-gate wo->vj_protocol = IPCP_VJ_COMP; 388*7c478bd9Sstevel@tonic-gate wo->maxslotindex = MAX_STATES - 1; /* really max index */ 389*7c478bd9Sstevel@tonic-gate wo->cflag = 1; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate ao->neg_addr = 1; 392*7c478bd9Sstevel@tonic-gate ao->neg_vj = 1; 393*7c478bd9Sstevel@tonic-gate ao->maxslotindex = MAX_STATES - 1; 394*7c478bd9Sstevel@tonic-gate ao->cflag = 1; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* 397*7c478bd9Sstevel@tonic-gate * These aren't actually negotiated. Instead, they control 398*7c478bd9Sstevel@tonic-gate * whether the user may use the proxyarp and defaultroute options. 399*7c478bd9Sstevel@tonic-gate */ 400*7c478bd9Sstevel@tonic-gate ao->proxy_arp = 1; 401*7c478bd9Sstevel@tonic-gate ao->default_route = 1; 402*7c478bd9Sstevel@tonic-gate proxy_arp_quiet[unit] = 0; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate * ipcp_open - IPCP is allowed to come up. 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate static void 410*7c478bd9Sstevel@tonic-gate ipcp_open(unit) 411*7c478bd9Sstevel@tonic-gate int unit; 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate fsm_open(&ipcp_fsm[unit]); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * ipcp_close - Take IPCP down. 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate static void 421*7c478bd9Sstevel@tonic-gate ipcp_close(unit, reason) 422*7c478bd9Sstevel@tonic-gate int unit; 423*7c478bd9Sstevel@tonic-gate char *reason; 424*7c478bd9Sstevel@tonic-gate { 425*7c478bd9Sstevel@tonic-gate fsm_close(&ipcp_fsm[unit], reason); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* 430*7c478bd9Sstevel@tonic-gate * ipcp_lowerup - The lower layer is up. 431*7c478bd9Sstevel@tonic-gate */ 432*7c478bd9Sstevel@tonic-gate static void 433*7c478bd9Sstevel@tonic-gate ipcp_lowerup(unit) 434*7c478bd9Sstevel@tonic-gate int unit; 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate fsm_lowerup(&ipcp_fsm[unit]); 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * ipcp_lowerdown - The lower layer is down. 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate static void 444*7c478bd9Sstevel@tonic-gate ipcp_lowerdown(unit) 445*7c478bd9Sstevel@tonic-gate int unit; 446*7c478bd9Sstevel@tonic-gate { 447*7c478bd9Sstevel@tonic-gate fsm_lowerdown(&ipcp_fsm[unit]); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * ipcp_input - Input IPCP packet. 453*7c478bd9Sstevel@tonic-gate */ 454*7c478bd9Sstevel@tonic-gate static void 455*7c478bd9Sstevel@tonic-gate ipcp_input(unit, p, len) 456*7c478bd9Sstevel@tonic-gate int unit; 457*7c478bd9Sstevel@tonic-gate u_char *p; 458*7c478bd9Sstevel@tonic-gate int len; 459*7c478bd9Sstevel@tonic-gate { 460*7c478bd9Sstevel@tonic-gate fsm_input(&ipcp_fsm[unit], p, len); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate /* 465*7c478bd9Sstevel@tonic-gate * ipcp_protrej - A Protocol-Reject was received for IPCP. 466*7c478bd9Sstevel@tonic-gate */ 467*7c478bd9Sstevel@tonic-gate static void 468*7c478bd9Sstevel@tonic-gate ipcp_protrej(unit) 469*7c478bd9Sstevel@tonic-gate int unit; 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate fsm_protreject(&ipcp_fsm[unit]); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * ipcp_resetci - Reset our CI. 477*7c478bd9Sstevel@tonic-gate * Called by fsm_sconfreq, Send Configure Request. 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate static void 480*7c478bd9Sstevel@tonic-gate ipcp_resetci(f) 481*7c478bd9Sstevel@tonic-gate fsm *f; 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[f->unit]; 484*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; 487*7c478bd9Sstevel@tonic-gate if (wo->ouraddr == 0 || disable_defaultip) 488*7c478bd9Sstevel@tonic-gate wo->accept_local = 1; 489*7c478bd9Sstevel@tonic-gate if (wo->hisaddr == 0) 490*7c478bd9Sstevel@tonic-gate wo->accept_remote = 1; 491*7c478bd9Sstevel@tonic-gate *go = *wo; 492*7c478bd9Sstevel@tonic-gate if (disable_defaultip) 493*7c478bd9Sstevel@tonic-gate go->ouraddr = 0; 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate /* 498*7c478bd9Sstevel@tonic-gate * ipcp_cilen - Return length of our CI. 499*7c478bd9Sstevel@tonic-gate * Called by fsm_sconfreq, Send Configure Request. 500*7c478bd9Sstevel@tonic-gate */ 501*7c478bd9Sstevel@tonic-gate static int 502*7c478bd9Sstevel@tonic-gate ipcp_cilen(f) 503*7c478bd9Sstevel@tonic-gate fsm *f; 504*7c478bd9Sstevel@tonic-gate { 505*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 506*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[f->unit]; 507*7c478bd9Sstevel@tonic-gate ipcp_options *ho = &ipcp_hisoptions[f->unit]; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) 510*7c478bd9Sstevel@tonic-gate #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) 511*7c478bd9Sstevel@tonic-gate #define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate /* 514*7c478bd9Sstevel@tonic-gate * First see if we want to change our options to the old 515*7c478bd9Sstevel@tonic-gate * forms because we have received old forms from the peer. 516*7c478bd9Sstevel@tonic-gate */ 517*7c478bd9Sstevel@tonic-gate if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { 518*7c478bd9Sstevel@tonic-gate /* use the old style of address negotiation */ 519*7c478bd9Sstevel@tonic-gate go->neg_addr = 1; 520*7c478bd9Sstevel@tonic-gate go->old_addrs = 1; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate if (wo->neg_vj && !go->neg_vj && !go->old_vj) { 523*7c478bd9Sstevel@tonic-gate /* try an older style of VJ negotiation */ 524*7c478bd9Sstevel@tonic-gate /* use the old style only if the peer did */ 525*7c478bd9Sstevel@tonic-gate if (ho->neg_vj && ho->old_vj) { 526*7c478bd9Sstevel@tonic-gate go->neg_vj = 1; 527*7c478bd9Sstevel@tonic-gate go->old_vj = 1; 528*7c478bd9Sstevel@tonic-gate go->vj_protocol = ho->vj_protocol; 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate return (LENCIADDR(go->neg_addr, go->old_addrs) + 533*7c478bd9Sstevel@tonic-gate LENCIVJ(go->neg_vj, go->old_vj) + 534*7c478bd9Sstevel@tonic-gate LENCIDNS(go->req_dns1) + 535*7c478bd9Sstevel@tonic-gate LENCIDNS(go->req_dns2)) ; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate /* 540*7c478bd9Sstevel@tonic-gate * ipcp_addci - Add our desired CIs to a packet. 541*7c478bd9Sstevel@tonic-gate * Called by fsm_sconfreq, Send Configure Request. 542*7c478bd9Sstevel@tonic-gate */ 543*7c478bd9Sstevel@tonic-gate static void 544*7c478bd9Sstevel@tonic-gate ipcp_addci(f, ucp, lenp) 545*7c478bd9Sstevel@tonic-gate fsm *f; 546*7c478bd9Sstevel@tonic-gate u_char *ucp; 547*7c478bd9Sstevel@tonic-gate int *lenp; 548*7c478bd9Sstevel@tonic-gate { 549*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 550*7c478bd9Sstevel@tonic-gate int len = *lenp; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 553*7c478bd9Sstevel@tonic-gate if (neg) { \ 554*7c478bd9Sstevel@tonic-gate int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 555*7c478bd9Sstevel@tonic-gate if (len >= vjlen) { \ 556*7c478bd9Sstevel@tonic-gate PUTCHAR(opt, ucp); \ 557*7c478bd9Sstevel@tonic-gate PUTCHAR(vjlen, ucp); \ 558*7c478bd9Sstevel@tonic-gate PUTSHORT(val, ucp); \ 559*7c478bd9Sstevel@tonic-gate if (!old) { \ 560*7c478bd9Sstevel@tonic-gate PUTCHAR(maxslotindex, ucp); \ 561*7c478bd9Sstevel@tonic-gate PUTCHAR(cflag, ucp); \ 562*7c478bd9Sstevel@tonic-gate } \ 563*7c478bd9Sstevel@tonic-gate len -= vjlen; \ 564*7c478bd9Sstevel@tonic-gate } else \ 565*7c478bd9Sstevel@tonic-gate neg = 0; \ 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate #define ADDCIADDR(opt, neg, old, val1, val2) \ 569*7c478bd9Sstevel@tonic-gate if (neg) { \ 570*7c478bd9Sstevel@tonic-gate int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 571*7c478bd9Sstevel@tonic-gate if (len >= addrlen) { \ 572*7c478bd9Sstevel@tonic-gate PUTCHAR(opt, ucp); \ 573*7c478bd9Sstevel@tonic-gate PUTCHAR(addrlen, ucp); \ 574*7c478bd9Sstevel@tonic-gate PUTNLONG(val1, ucp); \ 575*7c478bd9Sstevel@tonic-gate if (old) { \ 576*7c478bd9Sstevel@tonic-gate PUTNLONG(val2, ucp); \ 577*7c478bd9Sstevel@tonic-gate } \ 578*7c478bd9Sstevel@tonic-gate len -= addrlen; \ 579*7c478bd9Sstevel@tonic-gate } else \ 580*7c478bd9Sstevel@tonic-gate neg = 0; \ 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate #define ADDCIDNS(opt, neg, addr) \ 584*7c478bd9Sstevel@tonic-gate if (neg) { \ 585*7c478bd9Sstevel@tonic-gate if (len >= CILEN_ADDR) { \ 586*7c478bd9Sstevel@tonic-gate PUTCHAR(opt, ucp); \ 587*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_ADDR, ucp); \ 588*7c478bd9Sstevel@tonic-gate PUTNLONG(addr, ucp); \ 589*7c478bd9Sstevel@tonic-gate len -= CILEN_ADDR; \ 590*7c478bd9Sstevel@tonic-gate } else \ 591*7c478bd9Sstevel@tonic-gate neg = 0; \ 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 595*7c478bd9Sstevel@tonic-gate go->old_addrs, go->ouraddr, go->hisaddr); 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 598*7c478bd9Sstevel@tonic-gate go->maxslotindex, go->cflag); 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate *lenp -= len; 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * ipcp_ackci - Ack our CIs. 610*7c478bd9Sstevel@tonic-gate * Called by fsm_rconfack, Receive Configure ACK. 611*7c478bd9Sstevel@tonic-gate * 612*7c478bd9Sstevel@tonic-gate * Returns: 613*7c478bd9Sstevel@tonic-gate * 0 - Ack was bad. 614*7c478bd9Sstevel@tonic-gate * 1 - Ack was good. 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate static int 617*7c478bd9Sstevel@tonic-gate ipcp_ackci(f, p, len) 618*7c478bd9Sstevel@tonic-gate fsm *f; 619*7c478bd9Sstevel@tonic-gate u_char *p; 620*7c478bd9Sstevel@tonic-gate int len; 621*7c478bd9Sstevel@tonic-gate { 622*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 623*7c478bd9Sstevel@tonic-gate u_short cilen, citype, cishort; 624*7c478bd9Sstevel@tonic-gate u_int32_t cilong; 625*7c478bd9Sstevel@tonic-gate u_char cimaxslotindex, cicflag; 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate /* 628*7c478bd9Sstevel@tonic-gate * CIs must be in exactly the same order that we sent... 629*7c478bd9Sstevel@tonic-gate * Check packet length and CI length at each step. 630*7c478bd9Sstevel@tonic-gate * If we find any deviations, then this packet is bad. 631*7c478bd9Sstevel@tonic-gate */ 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ 634*7c478bd9Sstevel@tonic-gate if (neg) { \ 635*7c478bd9Sstevel@tonic-gate int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ 636*7c478bd9Sstevel@tonic-gate if ((len -= vjlen) < 0) \ 637*7c478bd9Sstevel@tonic-gate goto bad; \ 638*7c478bd9Sstevel@tonic-gate GETCHAR(citype, p); \ 639*7c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); \ 640*7c478bd9Sstevel@tonic-gate if (cilen != vjlen || \ 641*7c478bd9Sstevel@tonic-gate citype != opt) \ 642*7c478bd9Sstevel@tonic-gate goto bad; \ 643*7c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); \ 644*7c478bd9Sstevel@tonic-gate if (cishort != val) \ 645*7c478bd9Sstevel@tonic-gate goto bad; \ 646*7c478bd9Sstevel@tonic-gate if (!old) { \ 647*7c478bd9Sstevel@tonic-gate GETCHAR(cimaxslotindex, p); \ 648*7c478bd9Sstevel@tonic-gate if (cimaxslotindex != maxslotindex) \ 649*7c478bd9Sstevel@tonic-gate goto bad; \ 650*7c478bd9Sstevel@tonic-gate GETCHAR(cicflag, p); \ 651*7c478bd9Sstevel@tonic-gate if (cicflag != cflag) \ 652*7c478bd9Sstevel@tonic-gate goto bad; \ 653*7c478bd9Sstevel@tonic-gate } \ 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate #define ACKCIADDR(opt, neg, old, val1, val2) \ 657*7c478bd9Sstevel@tonic-gate if (neg) { \ 658*7c478bd9Sstevel@tonic-gate int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ 659*7c478bd9Sstevel@tonic-gate if ((len -= addrlen) < 0) \ 660*7c478bd9Sstevel@tonic-gate goto bad; \ 661*7c478bd9Sstevel@tonic-gate GETCHAR(citype, p); \ 662*7c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); \ 663*7c478bd9Sstevel@tonic-gate if (cilen != addrlen || \ 664*7c478bd9Sstevel@tonic-gate citype != opt) \ 665*7c478bd9Sstevel@tonic-gate goto bad; \ 666*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); \ 667*7c478bd9Sstevel@tonic-gate if (val1 != cilong) \ 668*7c478bd9Sstevel@tonic-gate goto bad; \ 669*7c478bd9Sstevel@tonic-gate if (old) { \ 670*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); \ 671*7c478bd9Sstevel@tonic-gate if (val2 != cilong) \ 672*7c478bd9Sstevel@tonic-gate goto bad; \ 673*7c478bd9Sstevel@tonic-gate } \ 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate #define ACKCIDNS(opt, neg, addr) \ 677*7c478bd9Sstevel@tonic-gate if (neg) { \ 678*7c478bd9Sstevel@tonic-gate if ((len -= CILEN_ADDR) < 0) \ 679*7c478bd9Sstevel@tonic-gate goto bad; \ 680*7c478bd9Sstevel@tonic-gate GETCHAR(citype, p); \ 681*7c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); \ 682*7c478bd9Sstevel@tonic-gate if (cilen != CILEN_ADDR || citype != opt) \ 683*7c478bd9Sstevel@tonic-gate goto bad; \ 684*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); \ 685*7c478bd9Sstevel@tonic-gate if (addr != cilong) \ 686*7c478bd9Sstevel@tonic-gate goto bad; \ 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, 690*7c478bd9Sstevel@tonic-gate go->old_addrs, go->ouraddr, go->hisaddr); 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, 693*7c478bd9Sstevel@tonic-gate go->maxslotindex, go->cflag); 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * If there are any remaining CIs, then this packet is bad. 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate if (len != 0) 703*7c478bd9Sstevel@tonic-gate goto bad; 704*7c478bd9Sstevel@tonic-gate return (1); 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate bad: 707*7c478bd9Sstevel@tonic-gate IPCPDEBUG(("ipcp_ackci: received bad Ack!")); 708*7c478bd9Sstevel@tonic-gate return (0); 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate /* 712*7c478bd9Sstevel@tonic-gate * ipcp_nakci - Peer has sent a NAK for some of our CIs. 713*7c478bd9Sstevel@tonic-gate * This should not modify any state if the Nak is bad 714*7c478bd9Sstevel@tonic-gate * or if IPCP is in the OPENED state. 715*7c478bd9Sstevel@tonic-gate * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. 716*7c478bd9Sstevel@tonic-gate * 717*7c478bd9Sstevel@tonic-gate * Returns: 718*7c478bd9Sstevel@tonic-gate * 0 - Nak was bad. 719*7c478bd9Sstevel@tonic-gate * 1 - Nak was good. 720*7c478bd9Sstevel@tonic-gate */ 721*7c478bd9Sstevel@tonic-gate static int 722*7c478bd9Sstevel@tonic-gate ipcp_nakci(f, p, len) 723*7c478bd9Sstevel@tonic-gate fsm *f; 724*7c478bd9Sstevel@tonic-gate u_char *p; 725*7c478bd9Sstevel@tonic-gate int len; 726*7c478bd9Sstevel@tonic-gate { 727*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 728*7c478bd9Sstevel@tonic-gate u_char cimaxslotindex, cicflag; 729*7c478bd9Sstevel@tonic-gate u_char citype, cilen, *next; 730*7c478bd9Sstevel@tonic-gate u_short cishort; 731*7c478bd9Sstevel@tonic-gate u_int32_t ciaddr1, ciaddr2, cidnsaddr; 732*7c478bd9Sstevel@tonic-gate ipcp_options no; /* options we've seen Naks for */ 733*7c478bd9Sstevel@tonic-gate ipcp_options try; /* options to request next time */ 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate BZERO(&no, sizeof(no)); 736*7c478bd9Sstevel@tonic-gate try = *go; 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate /* 739*7c478bd9Sstevel@tonic-gate * Any Nak'd CIs must be in exactly the same order that we sent. 740*7c478bd9Sstevel@tonic-gate * Check packet length and CI length at each step. 741*7c478bd9Sstevel@tonic-gate * If we find any deviations, then this packet is bad. 742*7c478bd9Sstevel@tonic-gate */ 743*7c478bd9Sstevel@tonic-gate #define NAKCIADDR(opt, neg, old, code) \ 744*7c478bd9Sstevel@tonic-gate if (go->neg && \ 745*7c478bd9Sstevel@tonic-gate len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ 746*7c478bd9Sstevel@tonic-gate p[1] == cilen && \ 747*7c478bd9Sstevel@tonic-gate p[0] == opt) { \ 748*7c478bd9Sstevel@tonic-gate len -= cilen; \ 749*7c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 750*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr1, p); \ 751*7c478bd9Sstevel@tonic-gate if (old) { \ 752*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr2, p); \ 753*7c478bd9Sstevel@tonic-gate no.old_addrs = 1; \ 754*7c478bd9Sstevel@tonic-gate } else \ 755*7c478bd9Sstevel@tonic-gate ciaddr2 = 0; \ 756*7c478bd9Sstevel@tonic-gate no.neg = 1; \ 757*7c478bd9Sstevel@tonic-gate code \ 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate #define NAKCIVJ(opt, neg, code) \ 761*7c478bd9Sstevel@tonic-gate if (go->neg && \ 762*7c478bd9Sstevel@tonic-gate ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ 763*7c478bd9Sstevel@tonic-gate len >= cilen && \ 764*7c478bd9Sstevel@tonic-gate p[0] == opt) { \ 765*7c478bd9Sstevel@tonic-gate len -= cilen; \ 766*7c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 767*7c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); \ 768*7c478bd9Sstevel@tonic-gate no.neg = 1; \ 769*7c478bd9Sstevel@tonic-gate code \ 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate #define NAKCIDNS(opt, neg, code) \ 773*7c478bd9Sstevel@tonic-gate if (go->neg && \ 774*7c478bd9Sstevel@tonic-gate ((cilen = p[1]) == CILEN_ADDR) && \ 775*7c478bd9Sstevel@tonic-gate len >= cilen && \ 776*7c478bd9Sstevel@tonic-gate p[0] == opt) { \ 777*7c478bd9Sstevel@tonic-gate len -= cilen; \ 778*7c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 779*7c478bd9Sstevel@tonic-gate GETNLONG(cidnsaddr, p); \ 780*7c478bd9Sstevel@tonic-gate no.neg = 1; \ 781*7c478bd9Sstevel@tonic-gate code \ 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate /* 785*7c478bd9Sstevel@tonic-gate * Accept the peer's idea of {our,his} address, if different 786*7c478bd9Sstevel@tonic-gate * from our idea, only if the accept_{local,remote} flag is set. 787*7c478bd9Sstevel@tonic-gate */ 788*7c478bd9Sstevel@tonic-gate NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, 789*7c478bd9Sstevel@tonic-gate if (go->accept_local && ciaddr1) { /* Do we know our address? */ 790*7c478bd9Sstevel@tonic-gate try.ouraddr = ciaddr1; 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate if (go->accept_remote && ciaddr2) { /* Does he know his? */ 793*7c478bd9Sstevel@tonic-gate try.hisaddr = ciaddr2; 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate ); 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate /* 798*7c478bd9Sstevel@tonic-gate * Accept the peer's value of maxslotindex provided that it 799*7c478bd9Sstevel@tonic-gate * is less than what we asked for. Turn off slot-ID compression 800*7c478bd9Sstevel@tonic-gate * if the peer wants. Send old-style compress-type option if 801*7c478bd9Sstevel@tonic-gate * the peer wants. 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate NAKCIVJ(CI_COMPRESSTYPE, neg_vj, 804*7c478bd9Sstevel@tonic-gate if (cilen == CILEN_VJ) { 805*7c478bd9Sstevel@tonic-gate GETCHAR(cimaxslotindex, p); 806*7c478bd9Sstevel@tonic-gate GETCHAR(cicflag, p); 807*7c478bd9Sstevel@tonic-gate if (cishort == IPCP_VJ_COMP) { 808*7c478bd9Sstevel@tonic-gate try.old_vj = 0; 809*7c478bd9Sstevel@tonic-gate if (cimaxslotindex < go->maxslotindex) 810*7c478bd9Sstevel@tonic-gate try.maxslotindex = cimaxslotindex; 811*7c478bd9Sstevel@tonic-gate if (!cicflag) 812*7c478bd9Sstevel@tonic-gate try.cflag = 0; 813*7c478bd9Sstevel@tonic-gate } else { 814*7c478bd9Sstevel@tonic-gate try.neg_vj = 0; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate } else { 817*7c478bd9Sstevel@tonic-gate if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { 818*7c478bd9Sstevel@tonic-gate try.old_vj = 1; 819*7c478bd9Sstevel@tonic-gate try.vj_protocol = cishort; 820*7c478bd9Sstevel@tonic-gate } else { 821*7c478bd9Sstevel@tonic-gate try.neg_vj = 0; 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate ); 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate NAKCIDNS(CI_MS_DNS1, req_dns1, 827*7c478bd9Sstevel@tonic-gate try.dnsaddr[0] = cidnsaddr; 828*7c478bd9Sstevel@tonic-gate ); 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate NAKCIDNS(CI_MS_DNS2, req_dns2, 831*7c478bd9Sstevel@tonic-gate try.dnsaddr[1] = cidnsaddr; 832*7c478bd9Sstevel@tonic-gate ); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * There may be remaining CIs, if the peer is requesting negotiation 836*7c478bd9Sstevel@tonic-gate * on an option that we didn't include in our request packet. 837*7c478bd9Sstevel@tonic-gate * If they want to negotiate about IP addresses, we comply. 838*7c478bd9Sstevel@tonic-gate * If they want us to ask for compression, we refuse. 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate while (len > CILEN_VOID) { 841*7c478bd9Sstevel@tonic-gate GETCHAR(citype, p); 842*7c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); 843*7c478bd9Sstevel@tonic-gate if( (len -= cilen) < 0 ) 844*7c478bd9Sstevel@tonic-gate goto bad; 845*7c478bd9Sstevel@tonic-gate next = p + cilen - 2; 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate switch (citype) { 848*7c478bd9Sstevel@tonic-gate case CI_COMPRESSTYPE: 849*7c478bd9Sstevel@tonic-gate if (go->neg_vj || no.neg_vj || 850*7c478bd9Sstevel@tonic-gate (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) 851*7c478bd9Sstevel@tonic-gate goto bad; 852*7c478bd9Sstevel@tonic-gate no.neg_vj = 1; 853*7c478bd9Sstevel@tonic-gate break; 854*7c478bd9Sstevel@tonic-gate case CI_ADDRS: 855*7c478bd9Sstevel@tonic-gate if ((go->neg_addr && go->old_addrs) || no.old_addrs 856*7c478bd9Sstevel@tonic-gate || cilen != CILEN_ADDRS) 857*7c478bd9Sstevel@tonic-gate goto bad; 858*7c478bd9Sstevel@tonic-gate try.neg_addr = 1; 859*7c478bd9Sstevel@tonic-gate try.old_addrs = 1; 860*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr1, p); 861*7c478bd9Sstevel@tonic-gate if (ciaddr1 && go->accept_local) 862*7c478bd9Sstevel@tonic-gate try.ouraddr = ciaddr1; 863*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr2, p); 864*7c478bd9Sstevel@tonic-gate if (ciaddr2 && go->accept_remote) 865*7c478bd9Sstevel@tonic-gate try.hisaddr = ciaddr2; 866*7c478bd9Sstevel@tonic-gate no.old_addrs = 1; 867*7c478bd9Sstevel@tonic-gate break; 868*7c478bd9Sstevel@tonic-gate case CI_ADDR: 869*7c478bd9Sstevel@tonic-gate if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) 870*7c478bd9Sstevel@tonic-gate goto bad; 871*7c478bd9Sstevel@tonic-gate try.old_addrs = 0; 872*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr1, p); 873*7c478bd9Sstevel@tonic-gate if (ciaddr1 && go->accept_local) 874*7c478bd9Sstevel@tonic-gate try.ouraddr = ciaddr1; 875*7c478bd9Sstevel@tonic-gate if (try.ouraddr != 0) 876*7c478bd9Sstevel@tonic-gate try.neg_addr = 1; 877*7c478bd9Sstevel@tonic-gate no.neg_addr = 1; 878*7c478bd9Sstevel@tonic-gate break; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate p = next; 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate /* 884*7c478bd9Sstevel@tonic-gate * OK, the Nak is good. Now we can update state. 885*7c478bd9Sstevel@tonic-gate * If there are any remaining options, we ignore them. 886*7c478bd9Sstevel@tonic-gate */ 887*7c478bd9Sstevel@tonic-gate if (f->state != OPENED) 888*7c478bd9Sstevel@tonic-gate *go = try; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate return 1; 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate bad: 893*7c478bd9Sstevel@tonic-gate IPCPDEBUG(("ipcp_nakci: received bad Nak!")); 894*7c478bd9Sstevel@tonic-gate return 0; 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate /* 899*7c478bd9Sstevel@tonic-gate * ipcp_rejci - Reject some of our CIs. 900*7c478bd9Sstevel@tonic-gate * Callback from fsm_rconfnakrej. 901*7c478bd9Sstevel@tonic-gate */ 902*7c478bd9Sstevel@tonic-gate static int 903*7c478bd9Sstevel@tonic-gate ipcp_rejci(f, p, len) 904*7c478bd9Sstevel@tonic-gate fsm *f; 905*7c478bd9Sstevel@tonic-gate u_char *p; 906*7c478bd9Sstevel@tonic-gate int len; 907*7c478bd9Sstevel@tonic-gate { 908*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 909*7c478bd9Sstevel@tonic-gate u_char cimaxslotindex, ciflag, cilen; 910*7c478bd9Sstevel@tonic-gate u_short cishort; 911*7c478bd9Sstevel@tonic-gate u_int32_t cilong; 912*7c478bd9Sstevel@tonic-gate ipcp_options try; /* options to request next time */ 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate try = *go; 915*7c478bd9Sstevel@tonic-gate /* 916*7c478bd9Sstevel@tonic-gate * Any Rejected CIs must be in exactly the same order that we sent. 917*7c478bd9Sstevel@tonic-gate * Check packet length and CI length at each step. 918*7c478bd9Sstevel@tonic-gate * If we find any deviations, then this packet is bad. 919*7c478bd9Sstevel@tonic-gate */ 920*7c478bd9Sstevel@tonic-gate #define REJCIADDR(opt, neg, old, val1, val2) \ 921*7c478bd9Sstevel@tonic-gate if (go->neg && \ 922*7c478bd9Sstevel@tonic-gate len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ 923*7c478bd9Sstevel@tonic-gate p[1] == cilen && \ 924*7c478bd9Sstevel@tonic-gate p[0] == opt) { \ 925*7c478bd9Sstevel@tonic-gate len -= cilen; \ 926*7c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 927*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); \ 928*7c478bd9Sstevel@tonic-gate /* Check rejected value. */ \ 929*7c478bd9Sstevel@tonic-gate if (cilong != val1) \ 930*7c478bd9Sstevel@tonic-gate goto bad; \ 931*7c478bd9Sstevel@tonic-gate if (old) { \ 932*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); \ 933*7c478bd9Sstevel@tonic-gate /* Check rejected value. */ \ 934*7c478bd9Sstevel@tonic-gate if (cilong != val2) \ 935*7c478bd9Sstevel@tonic-gate goto bad; \ 936*7c478bd9Sstevel@tonic-gate } \ 937*7c478bd9Sstevel@tonic-gate try.neg = 0; \ 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ 941*7c478bd9Sstevel@tonic-gate if (go->neg && \ 942*7c478bd9Sstevel@tonic-gate p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ 943*7c478bd9Sstevel@tonic-gate len >= p[1] && \ 944*7c478bd9Sstevel@tonic-gate p[0] == opt) { \ 945*7c478bd9Sstevel@tonic-gate len -= p[1]; \ 946*7c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 947*7c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); \ 948*7c478bd9Sstevel@tonic-gate /* Check rejected value. */ \ 949*7c478bd9Sstevel@tonic-gate if (cishort != val) \ 950*7c478bd9Sstevel@tonic-gate goto bad; \ 951*7c478bd9Sstevel@tonic-gate if (!old) { \ 952*7c478bd9Sstevel@tonic-gate GETCHAR(cimaxslotindex, p); \ 953*7c478bd9Sstevel@tonic-gate if (cimaxslotindex != maxslot) \ 954*7c478bd9Sstevel@tonic-gate goto bad; \ 955*7c478bd9Sstevel@tonic-gate GETCHAR(ciflag, p); \ 956*7c478bd9Sstevel@tonic-gate if (ciflag != cflag) \ 957*7c478bd9Sstevel@tonic-gate goto bad; \ 958*7c478bd9Sstevel@tonic-gate } \ 959*7c478bd9Sstevel@tonic-gate try.neg = 0; \ 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate #define REJCIDNS(opt, neg, dnsaddr) \ 963*7c478bd9Sstevel@tonic-gate if (go->neg && \ 964*7c478bd9Sstevel@tonic-gate ((cilen = p[1]) == CILEN_ADDR) && \ 965*7c478bd9Sstevel@tonic-gate len >= cilen && \ 966*7c478bd9Sstevel@tonic-gate p[0] == opt) { \ 967*7c478bd9Sstevel@tonic-gate len -= cilen; \ 968*7c478bd9Sstevel@tonic-gate INCPTR(2, p); \ 969*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); \ 970*7c478bd9Sstevel@tonic-gate /* Check rejected value. */ \ 971*7c478bd9Sstevel@tonic-gate if (cilong != dnsaddr) \ 972*7c478bd9Sstevel@tonic-gate goto bad; \ 973*7c478bd9Sstevel@tonic-gate try.neg = 0; \ 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, 978*7c478bd9Sstevel@tonic-gate go->old_addrs, go->ouraddr, go->hisaddr); 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, 981*7c478bd9Sstevel@tonic-gate go->maxslotindex, go->cflag); 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate /* 988*7c478bd9Sstevel@tonic-gate * If there are any remaining CIs, then this packet is bad. 989*7c478bd9Sstevel@tonic-gate */ 990*7c478bd9Sstevel@tonic-gate if (len != 0) 991*7c478bd9Sstevel@tonic-gate goto bad; 992*7c478bd9Sstevel@tonic-gate /* 993*7c478bd9Sstevel@tonic-gate * Now we can update state. 994*7c478bd9Sstevel@tonic-gate */ 995*7c478bd9Sstevel@tonic-gate if (f->state != OPENED) 996*7c478bd9Sstevel@tonic-gate *go = try; 997*7c478bd9Sstevel@tonic-gate return 1; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate bad: 1000*7c478bd9Sstevel@tonic-gate IPCPDEBUG(("ipcp_rejci: received bad Reject!")); 1001*7c478bd9Sstevel@tonic-gate return 0; 1002*7c478bd9Sstevel@tonic-gate } 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate /* 1006*7c478bd9Sstevel@tonic-gate * ipcp_reqci - Check the peer's requested CIs and send appropriate response. 1007*7c478bd9Sstevel@tonic-gate * Callback from fsm_rconfreq, Receive Configure Request 1008*7c478bd9Sstevel@tonic-gate * 1009*7c478bd9Sstevel@tonic-gate * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input 1010*7c478bd9Sstevel@tonic-gate * packet modified appropriately. If reject_if_disagree is non-zero, 1011*7c478bd9Sstevel@tonic-gate * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't 1012*7c478bd9Sstevel@tonic-gate * return CODE_CONFACK. 1013*7c478bd9Sstevel@tonic-gate */ 1014*7c478bd9Sstevel@tonic-gate static int 1015*7c478bd9Sstevel@tonic-gate ipcp_reqci(f, p, lenp, dont_nak) 1016*7c478bd9Sstevel@tonic-gate fsm *f; 1017*7c478bd9Sstevel@tonic-gate u_char *p; /* Requested CIs */ 1018*7c478bd9Sstevel@tonic-gate int *lenp; /* Length of requested CIs */ 1019*7c478bd9Sstevel@tonic-gate bool dont_nak; 1020*7c478bd9Sstevel@tonic-gate { 1021*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[f->unit]; 1022*7c478bd9Sstevel@tonic-gate ipcp_options *ho = &ipcp_hisoptions[f->unit]; 1023*7c478bd9Sstevel@tonic-gate ipcp_options *ao = &ipcp_allowoptions[f->unit]; 1024*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 1025*7c478bd9Sstevel@tonic-gate int ret, newret; 1026*7c478bd9Sstevel@tonic-gate u_char *p0, *nakp, *rejp, *prev; 1027*7c478bd9Sstevel@tonic-gate u_short cishort; 1028*7c478bd9Sstevel@tonic-gate int len, cilen, type; 1029*7c478bd9Sstevel@tonic-gate u_int32_t tl, ciaddr1, ciaddr2; /* Parsed address values */ 1030*7c478bd9Sstevel@tonic-gate u_char maxslotindex, cflag; 1031*7c478bd9Sstevel@tonic-gate int d; 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate ret = CODE_CONFACK; 1034*7c478bd9Sstevel@tonic-gate rejp = p0 = p; 1035*7c478bd9Sstevel@tonic-gate nakp = nak_buffer; 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate /* 1038*7c478bd9Sstevel@tonic-gate * Reset all his options. 1039*7c478bd9Sstevel@tonic-gate */ 1040*7c478bd9Sstevel@tonic-gate BZERO(ho, sizeof(*ho)); 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate /* 1043*7c478bd9Sstevel@tonic-gate * Process all his options. 1044*7c478bd9Sstevel@tonic-gate */ 1045*7c478bd9Sstevel@tonic-gate for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) { 1046*7c478bd9Sstevel@tonic-gate if ((len < 2) || p[1] > len) { 1047*7c478bd9Sstevel@tonic-gate /* 1048*7c478bd9Sstevel@tonic-gate * RFC 1661 page 40 -- if the option extends beyond the 1049*7c478bd9Sstevel@tonic-gate * packet, then discard the entire packet. 1050*7c478bd9Sstevel@tonic-gate */ 1051*7c478bd9Sstevel@tonic-gate return (0); 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate newret = CODE_CONFACK; 1055*7c478bd9Sstevel@tonic-gate prev = p; 1056*7c478bd9Sstevel@tonic-gate GETCHAR(type, p); 1057*7c478bd9Sstevel@tonic-gate GETCHAR(cilen, p); 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate switch (type) { /* Check CI type */ 1060*7c478bd9Sstevel@tonic-gate case CI_ADDRS: 1061*7c478bd9Sstevel@tonic-gate if (!ao->neg_addr) { 1062*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1063*7c478bd9Sstevel@tonic-gate break; 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate if (cilen != CILEN_ADDRS) { 1067*7c478bd9Sstevel@tonic-gate /* 1068*7c478bd9Sstevel@tonic-gate * rfc1661, page 40 -- a recongnized option with an 1069*7c478bd9Sstevel@tonic-gate * invalid length should be Nak'ed. 1070*7c478bd9Sstevel@tonic-gate */ 1071*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1072*7c478bd9Sstevel@tonic-gate ciaddr1 = wo->hisaddr; 1073*7c478bd9Sstevel@tonic-gate ciaddr2 = wo->ouraddr; 1074*7c478bd9Sstevel@tonic-gate } else { 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate /* 1077*7c478bd9Sstevel@tonic-gate * If he has no address, or if we both have his 1078*7c478bd9Sstevel@tonic-gate * address but disagree about it, then NAK it with our 1079*7c478bd9Sstevel@tonic-gate * idea. In particular, if we don't know his address, 1080*7c478bd9Sstevel@tonic-gate * but he does, then accept it. 1081*7c478bd9Sstevel@tonic-gate */ 1082*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr1, p); 1083*7c478bd9Sstevel@tonic-gate if (ciaddr1 != wo->hisaddr && 1084*7c478bd9Sstevel@tonic-gate (ciaddr1 == 0 || !wo->accept_remote)) { 1085*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1086*7c478bd9Sstevel@tonic-gate ciaddr1 = wo->hisaddr; 1087*7c478bd9Sstevel@tonic-gate } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 1088*7c478bd9Sstevel@tonic-gate /* 1089*7c478bd9Sstevel@tonic-gate * If neither we nor he knows his address, reject 1090*7c478bd9Sstevel@tonic-gate * the option. 1091*7c478bd9Sstevel@tonic-gate */ 1092*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1093*7c478bd9Sstevel@tonic-gate wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 1094*7c478bd9Sstevel@tonic-gate break; 1095*7c478bd9Sstevel@tonic-gate } else if (ciaddr1 != 0) { 1096*7c478bd9Sstevel@tonic-gate go->hisaddr = ciaddr1; 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate /* 1100*7c478bd9Sstevel@tonic-gate * If he doesn't know our address, or if we both have 1101*7c478bd9Sstevel@tonic-gate * our address * but disagree about it, then NAK it 1102*7c478bd9Sstevel@tonic-gate * with our idea. 1103*7c478bd9Sstevel@tonic-gate */ 1104*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr2, p); 1105*7c478bd9Sstevel@tonic-gate if (ciaddr2 != wo->ouraddr) { 1106*7c478bd9Sstevel@tonic-gate if (ciaddr2 == 0 || !wo->accept_local) { 1107*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1108*7c478bd9Sstevel@tonic-gate ciaddr2 = wo->ouraddr; 1109*7c478bd9Sstevel@tonic-gate } else { 1110*7c478bd9Sstevel@tonic-gate go->ouraddr = ciaddr2; /* accept peer's idea */ 1111*7c478bd9Sstevel@tonic-gate } 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 1116*7c478bd9Sstevel@tonic-gate PUTCHAR(type, nakp); 1117*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_ADDRS, nakp); 1118*7c478bd9Sstevel@tonic-gate PUTNLONG(ciaddr1, nakp); 1119*7c478bd9Sstevel@tonic-gate PUTNLONG(ciaddr2, nakp); 1120*7c478bd9Sstevel@tonic-gate } 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate ho->neg_addr = 1; 1123*7c478bd9Sstevel@tonic-gate ho->old_addrs = 1; 1124*7c478bd9Sstevel@tonic-gate ho->hisaddr = ciaddr1; 1125*7c478bd9Sstevel@tonic-gate ho->ouraddr = ciaddr2; 1126*7c478bd9Sstevel@tonic-gate break; 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate case CI_ADDR: 1129*7c478bd9Sstevel@tonic-gate if (!ao->neg_addr) { 1130*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1131*7c478bd9Sstevel@tonic-gate break; 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate 1134*7c478bd9Sstevel@tonic-gate if (cilen != CILEN_ADDR) { 1135*7c478bd9Sstevel@tonic-gate /* 1136*7c478bd9Sstevel@tonic-gate * rfc1661, page 40 -- a recongnized option with an 1137*7c478bd9Sstevel@tonic-gate * invalid length should be Nak'ed. 1138*7c478bd9Sstevel@tonic-gate */ 1139*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1140*7c478bd9Sstevel@tonic-gate ciaddr1 = wo->hisaddr; 1141*7c478bd9Sstevel@tonic-gate } else { 1142*7c478bd9Sstevel@tonic-gate 1143*7c478bd9Sstevel@tonic-gate /* 1144*7c478bd9Sstevel@tonic-gate * If he has no address, or if we both have his 1145*7c478bd9Sstevel@tonic-gate * address but disagree about it, then NAK it with our 1146*7c478bd9Sstevel@tonic-gate * idea. In particular, if we don't know his address, 1147*7c478bd9Sstevel@tonic-gate * but he does, then accept it. 1148*7c478bd9Sstevel@tonic-gate */ 1149*7c478bd9Sstevel@tonic-gate GETNLONG(ciaddr1, p); 1150*7c478bd9Sstevel@tonic-gate if (ciaddr1 != wo->hisaddr && 1151*7c478bd9Sstevel@tonic-gate (ciaddr1 == 0 || !wo->accept_remote)) { 1152*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1153*7c478bd9Sstevel@tonic-gate ciaddr1 = wo->hisaddr; 1154*7c478bd9Sstevel@tonic-gate } else if (ciaddr1 == 0 && wo->hisaddr == 0 && 1155*7c478bd9Sstevel@tonic-gate wo->default_route != 0) { 1156*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1157*7c478bd9Sstevel@tonic-gate /* 1158*7c478bd9Sstevel@tonic-gate * If this is a dialup line (default_route is 1159*7c478bd9Sstevel@tonic-gate * set), and neither side knows about his address, 1160*7c478bd9Sstevel@tonic-gate * suggest an arbitrary rfc1918 address. 1161*7c478bd9Sstevel@tonic-gate */ 1162*7c478bd9Sstevel@tonic-gate ciaddr1 = htonl(0xc0a80101 + ifunit); 1163*7c478bd9Sstevel@tonic-gate dbglog("Peer address unknown; suggesting %I", ciaddr1); 1164*7c478bd9Sstevel@tonic-gate } else if (ciaddr1 == 0 && wo->hisaddr == 0) { 1165*7c478bd9Sstevel@tonic-gate /* 1166*7c478bd9Sstevel@tonic-gate * If this is not a dialup line, don't ACK an 1167*7c478bd9Sstevel@tonic-gate * address of 0.0.0.0 - reject it instead. 1168*7c478bd9Sstevel@tonic-gate */ 1169*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1170*7c478bd9Sstevel@tonic-gate wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ 1171*7c478bd9Sstevel@tonic-gate break; 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate } 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 1176*7c478bd9Sstevel@tonic-gate PUTCHAR(type, nakp); 1177*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_ADDR, nakp); 1178*7c478bd9Sstevel@tonic-gate PUTNLONG(ciaddr1, nakp); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate ho->neg_addr = 1; 1182*7c478bd9Sstevel@tonic-gate ho->hisaddr = ciaddr1; 1183*7c478bd9Sstevel@tonic-gate break; 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate case CI_MS_DNS1: 1186*7c478bd9Sstevel@tonic-gate case CI_MS_DNS2: 1187*7c478bd9Sstevel@tonic-gate /* Warning -- these options work backwards. */ 1188*7c478bd9Sstevel@tonic-gate /* Microsoft primary or secondary DNS request */ 1189*7c478bd9Sstevel@tonic-gate d = (type == CI_MS_DNS2 ? 1 : 0); 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate if (ao->dnsaddr[d] == 0) { 1192*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1193*7c478bd9Sstevel@tonic-gate break; 1194*7c478bd9Sstevel@tonic-gate } 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate if (cilen != CILEN_ADDR) { 1197*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1198*7c478bd9Sstevel@tonic-gate } else { 1199*7c478bd9Sstevel@tonic-gate GETNLONG(tl, p); 1200*7c478bd9Sstevel@tonic-gate if (tl != ao->dnsaddr[d]) { 1201*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 1206*7c478bd9Sstevel@tonic-gate PUTCHAR(type, nakp); 1207*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_ADDR, nakp); 1208*7c478bd9Sstevel@tonic-gate PUTNLONG(ao->dnsaddr[d], nakp); 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate break; 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate case CI_MS_WINS1: 1213*7c478bd9Sstevel@tonic-gate case CI_MS_WINS2: 1214*7c478bd9Sstevel@tonic-gate /* Warning -- these options work backwards. */ 1215*7c478bd9Sstevel@tonic-gate /* Microsoft primary or secondary WINS request */ 1216*7c478bd9Sstevel@tonic-gate d = (type == CI_MS_WINS2 ? 1 : 0); 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate if (ao->winsaddr[d] == 0) { 1219*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1220*7c478bd9Sstevel@tonic-gate break; 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate if (cilen != CILEN_ADDR) { 1224*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1225*7c478bd9Sstevel@tonic-gate } else { 1226*7c478bd9Sstevel@tonic-gate GETNLONG(tl, p); 1227*7c478bd9Sstevel@tonic-gate if (tl != ao->winsaddr[d]) { 1228*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1229*7c478bd9Sstevel@tonic-gate } 1230*7c478bd9Sstevel@tonic-gate } 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 1233*7c478bd9Sstevel@tonic-gate PUTCHAR(type, nakp); 1234*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_ADDR, nakp); 1235*7c478bd9Sstevel@tonic-gate PUTNLONG(ao->winsaddr[d], nakp); 1236*7c478bd9Sstevel@tonic-gate } 1237*7c478bd9Sstevel@tonic-gate break; 1238*7c478bd9Sstevel@tonic-gate 1239*7c478bd9Sstevel@tonic-gate case CI_COMPRESSTYPE: 1240*7c478bd9Sstevel@tonic-gate if (!ao->neg_vj) { 1241*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1242*7c478bd9Sstevel@tonic-gate break; 1243*7c478bd9Sstevel@tonic-gate } 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate maxslotindex = ao->maxslotindex; 1246*7c478bd9Sstevel@tonic-gate cflag = ao->cflag; 1247*7c478bd9Sstevel@tonic-gate if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { 1248*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1249*7c478bd9Sstevel@tonic-gate cishort = IPCP_VJ_COMP; 1250*7c478bd9Sstevel@tonic-gate } else { 1251*7c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); 1252*7c478bd9Sstevel@tonic-gate if (cishort != IPCP_VJ_COMP && 1253*7c478bd9Sstevel@tonic-gate (cishort != IPCP_VJ_COMP_OLD || cilen != CILEN_COMPRESS)) { 1254*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1255*7c478bd9Sstevel@tonic-gate cishort = IPCP_VJ_COMP; 1256*7c478bd9Sstevel@tonic-gate } else if (cilen == CILEN_VJ) { 1257*7c478bd9Sstevel@tonic-gate GETCHAR(maxslotindex, p); 1258*7c478bd9Sstevel@tonic-gate if (maxslotindex > ao->maxslotindex) { 1259*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1260*7c478bd9Sstevel@tonic-gate maxslotindex = ao->maxslotindex; 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate GETCHAR(cflag, p); 1263*7c478bd9Sstevel@tonic-gate if (cflag != 0 && ao->cflag == 0) { 1264*7c478bd9Sstevel@tonic-gate newret = CODE_CONFNAK; 1265*7c478bd9Sstevel@tonic-gate cflag = 0; 1266*7c478bd9Sstevel@tonic-gate } 1267*7c478bd9Sstevel@tonic-gate } else { 1268*7c478bd9Sstevel@tonic-gate ho->old_vj = 1; 1269*7c478bd9Sstevel@tonic-gate maxslotindex = MAX_STATES - 1; 1270*7c478bd9Sstevel@tonic-gate cflag = 1; 1271*7c478bd9Sstevel@tonic-gate } 1272*7c478bd9Sstevel@tonic-gate } 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 1275*7c478bd9Sstevel@tonic-gate PUTCHAR(type, nakp); 1276*7c478bd9Sstevel@tonic-gate if (cishort == IPCP_VJ_COMP) { 1277*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_VJ, nakp); 1278*7c478bd9Sstevel@tonic-gate PUTSHORT(cishort, nakp); 1279*7c478bd9Sstevel@tonic-gate PUTCHAR(maxslotindex, nakp); 1280*7c478bd9Sstevel@tonic-gate PUTCHAR(cflag, nakp); 1281*7c478bd9Sstevel@tonic-gate } else { 1282*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_COMPRESS, nakp); 1283*7c478bd9Sstevel@tonic-gate PUTSHORT(cishort, nakp); 1284*7c478bd9Sstevel@tonic-gate } 1285*7c478bd9Sstevel@tonic-gate } 1286*7c478bd9Sstevel@tonic-gate ho->neg_vj = 1; 1287*7c478bd9Sstevel@tonic-gate ho->vj_protocol = cishort; 1288*7c478bd9Sstevel@tonic-gate ho->maxslotindex = maxslotindex; 1289*7c478bd9Sstevel@tonic-gate ho->cflag = cflag; 1290*7c478bd9Sstevel@tonic-gate break; 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate default: 1293*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1294*7c478bd9Sstevel@tonic-gate break; 1295*7c478bd9Sstevel@tonic-gate } 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate /* Cope with confused peers. */ 1298*7c478bd9Sstevel@tonic-gate if (cilen < 2) 1299*7c478bd9Sstevel@tonic-gate cilen = 2; 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate /* 1302*7c478bd9Sstevel@tonic-gate * If this is an Ack'able CI, but we're sending back a Nak, 1303*7c478bd9Sstevel@tonic-gate * don't include this CI. 1304*7c478bd9Sstevel@tonic-gate */ 1305*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFACK && ret != CODE_CONFACK) 1306*7c478bd9Sstevel@tonic-gate continue; 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFNAK) { 1309*7c478bd9Sstevel@tonic-gate if (dont_nak) { 1310*7c478bd9Sstevel@tonic-gate newret = CODE_CONFREJ; 1311*7c478bd9Sstevel@tonic-gate } else { 1312*7c478bd9Sstevel@tonic-gate /* Ignore subsequent Nak'able things if rejecting. */ 1313*7c478bd9Sstevel@tonic-gate if (ret == CODE_CONFREJ) 1314*7c478bd9Sstevel@tonic-gate continue; 1315*7c478bd9Sstevel@tonic-gate ret = CODE_CONFNAK; 1316*7c478bd9Sstevel@tonic-gate } 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate if (newret == CODE_CONFREJ) { 1320*7c478bd9Sstevel@tonic-gate ret = CODE_CONFREJ; 1321*7c478bd9Sstevel@tonic-gate if (prev != rejp) 1322*7c478bd9Sstevel@tonic-gate BCOPY(prev, rejp, cilen); 1323*7c478bd9Sstevel@tonic-gate rejp += cilen; 1324*7c478bd9Sstevel@tonic-gate } 1325*7c478bd9Sstevel@tonic-gate } 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate /* 1328*7c478bd9Sstevel@tonic-gate * If we aren't rejecting this packet, and we want to negotiate 1329*7c478bd9Sstevel@tonic-gate * their address, and they didn't send their address, then we 1330*7c478bd9Sstevel@tonic-gate * send a NAK with a CI_ADDR option appended. We assume the 1331*7c478bd9Sstevel@tonic-gate * input buffer is long enough that we can append the extra 1332*7c478bd9Sstevel@tonic-gate * option safely. 1333*7c478bd9Sstevel@tonic-gate */ 1334*7c478bd9Sstevel@tonic-gate if (ret != CODE_CONFREJ && !ho->neg_addr && wo->req_addr && !dont_nak) { 1335*7c478bd9Sstevel@tonic-gate if (ret == CODE_CONFACK) 1336*7c478bd9Sstevel@tonic-gate wo->req_addr = 0; /* don't ask again */ 1337*7c478bd9Sstevel@tonic-gate ret = CODE_CONFNAK; 1338*7c478bd9Sstevel@tonic-gate PUTCHAR(CI_ADDR, nakp); 1339*7c478bd9Sstevel@tonic-gate PUTCHAR(CILEN_ADDR, nakp); 1340*7c478bd9Sstevel@tonic-gate PUTNLONG(wo->hisaddr, nakp); 1341*7c478bd9Sstevel@tonic-gate } 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate switch (ret) { 1344*7c478bd9Sstevel@tonic-gate case CODE_CONFACK: 1345*7c478bd9Sstevel@tonic-gate *lenp = p - p0; 1346*7c478bd9Sstevel@tonic-gate sys_block_proto(PPP_IP); 1347*7c478bd9Sstevel@tonic-gate break; 1348*7c478bd9Sstevel@tonic-gate case CODE_CONFNAK: 1349*7c478bd9Sstevel@tonic-gate *lenp = nakp - nak_buffer; 1350*7c478bd9Sstevel@tonic-gate BCOPY(nak_buffer, p0, *lenp); 1351*7c478bd9Sstevel@tonic-gate break; 1352*7c478bd9Sstevel@tonic-gate case CODE_CONFREJ: 1353*7c478bd9Sstevel@tonic-gate *lenp = rejp - p0; 1354*7c478bd9Sstevel@tonic-gate break; 1355*7c478bd9Sstevel@tonic-gate } 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate return (ret); /* Return final code */ 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate /* 1362*7c478bd9Sstevel@tonic-gate * ip_check_options - check that any IP-related options are OK, 1363*7c478bd9Sstevel@tonic-gate * and assign appropriate defaults. 1364*7c478bd9Sstevel@tonic-gate */ 1365*7c478bd9Sstevel@tonic-gate static void 1366*7c478bd9Sstevel@tonic-gate ip_check_options() 1367*7c478bd9Sstevel@tonic-gate { 1368*7c478bd9Sstevel@tonic-gate struct hostent *hp; 1369*7c478bd9Sstevel@tonic-gate u_int32_t local; 1370*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[0]; 1371*7c478bd9Sstevel@tonic-gate 1372*7c478bd9Sstevel@tonic-gate /* 1373*7c478bd9Sstevel@tonic-gate * Default our local IP address based on our hostname. 1374*7c478bd9Sstevel@tonic-gate * If local IP address already given, don't bother. 1375*7c478bd9Sstevel@tonic-gate */ 1376*7c478bd9Sstevel@tonic-gate if (wo->ouraddr == 0) { 1377*7c478bd9Sstevel@tonic-gate /* 1378*7c478bd9Sstevel@tonic-gate * Look up our hostname (possibly with domain name appended) 1379*7c478bd9Sstevel@tonic-gate * and take the first IP address as our local IP address. 1380*7c478bd9Sstevel@tonic-gate * If there isn't an IP address for our hostname, too bad. 1381*7c478bd9Sstevel@tonic-gate */ 1382*7c478bd9Sstevel@tonic-gate wo->accept_local = 1; /* don't insist on this default value */ 1383*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(hostname)) != NULL) { 1384*7c478bd9Sstevel@tonic-gate BCOPY(hp->h_addr, &local, sizeof (hp->h_addr)); 1385*7c478bd9Sstevel@tonic-gate if (local != 0 && !bad_ip_adrs(local)) { 1386*7c478bd9Sstevel@tonic-gate wo->ouraddr = local; 1387*7c478bd9Sstevel@tonic-gate ipcp_from_hostname = 1; 1388*7c478bd9Sstevel@tonic-gate } 1389*7c478bd9Sstevel@tonic-gate } 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate /* 1395*7c478bd9Sstevel@tonic-gate * ip_demand_conf - configure the interface as though 1396*7c478bd9Sstevel@tonic-gate * IPCP were up, for use with dial-on-demand. 1397*7c478bd9Sstevel@tonic-gate */ 1398*7c478bd9Sstevel@tonic-gate static int 1399*7c478bd9Sstevel@tonic-gate ip_demand_conf(u) 1400*7c478bd9Sstevel@tonic-gate int u; 1401*7c478bd9Sstevel@tonic-gate { 1402*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[u]; 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate if (wo->hisaddr == 0) { 1405*7c478bd9Sstevel@tonic-gate /* make up an arbitrary address for the peer */ 1406*7c478bd9Sstevel@tonic-gate wo->hisaddr = htonl(0x0a707070 + ifunit); 1407*7c478bd9Sstevel@tonic-gate wo->accept_remote = 1; 1408*7c478bd9Sstevel@tonic-gate } 1409*7c478bd9Sstevel@tonic-gate if (wo->ouraddr == 0) { 1410*7c478bd9Sstevel@tonic-gate /* make up an arbitrary address for us */ 1411*7c478bd9Sstevel@tonic-gate wo->ouraddr = htonl(0x0a404040 + ifunit); 1412*7c478bd9Sstevel@tonic-gate wo->accept_local = 1; 1413*7c478bd9Sstevel@tonic-gate disable_defaultip = 1; /* don't tell the peer this address */ 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr))) 1416*7c478bd9Sstevel@tonic-gate return 0; 1417*7c478bd9Sstevel@tonic-gate if (!sifup(u)) 1418*7c478bd9Sstevel@tonic-gate return 0; 1419*7c478bd9Sstevel@tonic-gate if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) 1420*7c478bd9Sstevel@tonic-gate return 0; 1421*7c478bd9Sstevel@tonic-gate if (wo->default_route && sifdefaultroute(u, wo->ouraddr, wo->hisaddr)) 1422*7c478bd9Sstevel@tonic-gate default_route_set[u] = 1; 1423*7c478bd9Sstevel@tonic-gate if (wo->proxy_arp && sifproxyarp(u, wo->hisaddr, proxy_arp_quiet[u])) 1424*7c478bd9Sstevel@tonic-gate proxy_arp_set[u] = 1; 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate notice("local IP address %I", wo->ouraddr); 1427*7c478bd9Sstevel@tonic-gate notice("remote IP address %I", wo->hisaddr); 1428*7c478bd9Sstevel@tonic-gate 1429*7c478bd9Sstevel@tonic-gate return 1; 1430*7c478bd9Sstevel@tonic-gate } 1431*7c478bd9Sstevel@tonic-gate 1432*7c478bd9Sstevel@tonic-gate 1433*7c478bd9Sstevel@tonic-gate /* 1434*7c478bd9Sstevel@tonic-gate * ipcp_up - IPCP has come UP. 1435*7c478bd9Sstevel@tonic-gate * 1436*7c478bd9Sstevel@tonic-gate * Configure the IP network interface appropriately and bring it up. 1437*7c478bd9Sstevel@tonic-gate */ 1438*7c478bd9Sstevel@tonic-gate static void 1439*7c478bd9Sstevel@tonic-gate ipcp_up(f) 1440*7c478bd9Sstevel@tonic-gate fsm *f; 1441*7c478bd9Sstevel@tonic-gate { 1442*7c478bd9Sstevel@tonic-gate u_int32_t mask; 1443*7c478bd9Sstevel@tonic-gate ipcp_options *ho = &ipcp_hisoptions[f->unit]; 1444*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[f->unit]; 1445*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[f->unit]; 1446*7c478bd9Sstevel@tonic-gate 1447*7c478bd9Sstevel@tonic-gate IPCPDEBUG(("ipcp: up")); 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate /* 1450*7c478bd9Sstevel@tonic-gate * We must have a non-zero IP address for both ends of the link. 1451*7c478bd9Sstevel@tonic-gate */ 1452*7c478bd9Sstevel@tonic-gate if (ho->hisaddr == 0) 1453*7c478bd9Sstevel@tonic-gate ho->hisaddr = wo->hisaddr; 1454*7c478bd9Sstevel@tonic-gate 1455*7c478bd9Sstevel@tonic-gate if (ho->hisaddr == 0) { 1456*7c478bd9Sstevel@tonic-gate if (wo->accept_remote) { 1457*7c478bd9Sstevel@tonic-gate /* Pick some rfc1918 address. */ 1458*7c478bd9Sstevel@tonic-gate ho->hisaddr = htonl(0xc0a80101 + ifunit); 1459*7c478bd9Sstevel@tonic-gate dbglog("Peer refused to provide his address; assuming %I", 1460*7c478bd9Sstevel@tonic-gate ho->hisaddr); 1461*7c478bd9Sstevel@tonic-gate } else { 1462*7c478bd9Sstevel@tonic-gate error("Could not determine remote IP address"); 1463*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Could not determine remote IP address"); 1464*7c478bd9Sstevel@tonic-gate return; 1465*7c478bd9Sstevel@tonic-gate } 1466*7c478bd9Sstevel@tonic-gate } 1467*7c478bd9Sstevel@tonic-gate if (go->ouraddr == 0) { 1468*7c478bd9Sstevel@tonic-gate error("Could not determine local IP address"); 1469*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Could not determine local IP address"); 1470*7c478bd9Sstevel@tonic-gate return; 1471*7c478bd9Sstevel@tonic-gate } 1472*7c478bd9Sstevel@tonic-gate script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); 1473*7c478bd9Sstevel@tonic-gate script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate /* 1476*7c478bd9Sstevel@tonic-gate * Check that the peer is allowed to use the IP address it wants. 1477*7c478bd9Sstevel@tonic-gate */ 1478*7c478bd9Sstevel@tonic-gate if (!auth_ip_addr(f->unit, ho->hisaddr)) { 1479*7c478bd9Sstevel@tonic-gate error("Peer is not authorized to use remote address %I", ho->hisaddr); 1480*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Unauthorized remote IP address"); 1481*7c478bd9Sstevel@tonic-gate return; 1482*7c478bd9Sstevel@tonic-gate } 1483*7c478bd9Sstevel@tonic-gate 1484*7c478bd9Sstevel@tonic-gate if ((go->req_dns1 && go->dnsaddr[0] != 0) || 1485*7c478bd9Sstevel@tonic-gate (go->req_dns2 && go->dnsaddr[1] != 0)) { 1486*7c478bd9Sstevel@tonic-gate script_setenv("USEPEERDNS", "1", 0); 1487*7c478bd9Sstevel@tonic-gate if (go->dnsaddr[0] != 0) 1488*7c478bd9Sstevel@tonic-gate script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); 1489*7c478bd9Sstevel@tonic-gate if (go->dnsaddr[1] != 0) 1490*7c478bd9Sstevel@tonic-gate script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); 1491*7c478bd9Sstevel@tonic-gate create_resolv(go->dnsaddr[0], go->dnsaddr[1]); 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate /* set tcp compression */ 1495*7c478bd9Sstevel@tonic-gate if (sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex) != 1) { 1496*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Could not enable VJ TCP header compression"); 1497*7c478bd9Sstevel@tonic-gate return; 1498*7c478bd9Sstevel@tonic-gate } 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate /* 1501*7c478bd9Sstevel@tonic-gate * If we are doing dial-on-demand, the interface is already 1502*7c478bd9Sstevel@tonic-gate * configured, so we put out any saved-up packets, then set the 1503*7c478bd9Sstevel@tonic-gate * interface to pass IP packets. 1504*7c478bd9Sstevel@tonic-gate */ 1505*7c478bd9Sstevel@tonic-gate if (demand) { 1506*7c478bd9Sstevel@tonic-gate if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { 1507*7c478bd9Sstevel@tonic-gate ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr); 1508*7c478bd9Sstevel@tonic-gate if (go->ouraddr != wo->ouraddr) { 1509*7c478bd9Sstevel@tonic-gate warn("Local IP address changed to %I", go->ouraddr); 1510*7c478bd9Sstevel@tonic-gate script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); 1511*7c478bd9Sstevel@tonic-gate wo->ouraddr = go->ouraddr; 1512*7c478bd9Sstevel@tonic-gate } else 1513*7c478bd9Sstevel@tonic-gate script_unsetenv("OLDIPLOCAL"); 1514*7c478bd9Sstevel@tonic-gate if (ho->hisaddr != wo->hisaddr) { 1515*7c478bd9Sstevel@tonic-gate warn("Remote IP address changed to %I", ho->hisaddr); 1516*7c478bd9Sstevel@tonic-gate script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); 1517*7c478bd9Sstevel@tonic-gate wo->hisaddr = ho->hisaddr; 1518*7c478bd9Sstevel@tonic-gate } else 1519*7c478bd9Sstevel@tonic-gate script_unsetenv("OLDIPREMOTE"); 1520*7c478bd9Sstevel@tonic-gate 1521*7c478bd9Sstevel@tonic-gate /* Set the interface to the new addresses */ 1522*7c478bd9Sstevel@tonic-gate mask = GetMask(go->ouraddr); 1523*7c478bd9Sstevel@tonic-gate if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { 1524*7c478bd9Sstevel@tonic-gate warn("Interface configuration failed"); 1525*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Interface configuration failed"); 1526*7c478bd9Sstevel@tonic-gate return; 1527*7c478bd9Sstevel@tonic-gate } 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate /* assign a default route through the interface if required */ 1530*7c478bd9Sstevel@tonic-gate if (wo->default_route) 1531*7c478bd9Sstevel@tonic-gate if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) 1532*7c478bd9Sstevel@tonic-gate default_route_set[f->unit] = 1; 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate /* Make a proxy ARP entry if requested. */ 1535*7c478bd9Sstevel@tonic-gate if (wo->proxy_arp && 1536*7c478bd9Sstevel@tonic-gate sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit])) 1537*7c478bd9Sstevel@tonic-gate proxy_arp_set[f->unit] = 1; 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate } 1540*7c478bd9Sstevel@tonic-gate demand_rexmit(PPP_IP); 1541*7c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) { 1542*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Interface configuration failed."); 1543*7c478bd9Sstevel@tonic-gate return; 1544*7c478bd9Sstevel@tonic-gate } 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate } else { 1547*7c478bd9Sstevel@tonic-gate /* 1548*7c478bd9Sstevel@tonic-gate * Set IP addresses and (if specified) netmask. 1549*7c478bd9Sstevel@tonic-gate */ 1550*7c478bd9Sstevel@tonic-gate mask = GetMask(go->ouraddr); 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate #if SIFUPFIRST 1553*7c478bd9Sstevel@tonic-gate /* bring the interface up for IP */ 1554*7c478bd9Sstevel@tonic-gate if (!sifup(f->unit)) { 1555*7c478bd9Sstevel@tonic-gate warn("Interface failed to come up"); 1556*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Interface configuration failed"); 1557*7c478bd9Sstevel@tonic-gate return; 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate #endif 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { 1562*7c478bd9Sstevel@tonic-gate warn("Interface configuration failed"); 1563*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Interface configuration failed"); 1564*7c478bd9Sstevel@tonic-gate return; 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate #if !SIFUPFIRST 1568*7c478bd9Sstevel@tonic-gate /* bring the interface up for IP */ 1569*7c478bd9Sstevel@tonic-gate if (!sifup(f->unit)) { 1570*7c478bd9Sstevel@tonic-gate warn("Interface failed to come up"); 1571*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Interface configuration failed"); 1572*7c478bd9Sstevel@tonic-gate return; 1573*7c478bd9Sstevel@tonic-gate } 1574*7c478bd9Sstevel@tonic-gate #endif 1575*7c478bd9Sstevel@tonic-gate 1576*7c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) { 1577*7c478bd9Sstevel@tonic-gate ipcp_close(f->unit, "Interface configuration failed."); 1578*7c478bd9Sstevel@tonic-gate return; 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate /* assign a default route through the interface if required */ 1582*7c478bd9Sstevel@tonic-gate if (wo->default_route) 1583*7c478bd9Sstevel@tonic-gate if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) 1584*7c478bd9Sstevel@tonic-gate default_route_set[f->unit] = 1; 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate /* Make a proxy ARP entry if requested. */ 1587*7c478bd9Sstevel@tonic-gate if (wo->proxy_arp && 1588*7c478bd9Sstevel@tonic-gate sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit])) 1589*7c478bd9Sstevel@tonic-gate proxy_arp_set[f->unit] = 1; 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate wo->ouraddr = go->ouraddr; 1592*7c478bd9Sstevel@tonic-gate 1593*7c478bd9Sstevel@tonic-gate notice("local IP address %I", go->ouraddr); 1594*7c478bd9Sstevel@tonic-gate notice("remote IP address %I", ho->hisaddr); 1595*7c478bd9Sstevel@tonic-gate if (go->dnsaddr[0] != 0) 1596*7c478bd9Sstevel@tonic-gate notice("primary DNS address %I", go->dnsaddr[0]); 1597*7c478bd9Sstevel@tonic-gate if (go->dnsaddr[1] != 0) 1598*7c478bd9Sstevel@tonic-gate notice("secondary DNS address %I", go->dnsaddr[1]); 1599*7c478bd9Sstevel@tonic-gate } 1600*7c478bd9Sstevel@tonic-gate 1601*7c478bd9Sstevel@tonic-gate np_up(f->unit, PPP_IP); 1602*7c478bd9Sstevel@tonic-gate ipcp_is_up[f->unit] = 1; 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate if (ip_up_hook != NULL) 1605*7c478bd9Sstevel@tonic-gate (*ip_up_hook)(); 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate /* 1608*7c478bd9Sstevel@tonic-gate * Execute the ip-up script, like this: 1609*7c478bd9Sstevel@tonic-gate * /etc/ppp/ip-up interface tty speed local-IP remote-IP 1610*7c478bd9Sstevel@tonic-gate */ 1611*7c478bd9Sstevel@tonic-gate if (ipcp_script_state == s_down && ipcp_script_pid == 0) { 1612*7c478bd9Sstevel@tonic-gate ipcp_script_state = s_up; 1613*7c478bd9Sstevel@tonic-gate ipcp_script(_PATH_IPUP); 1614*7c478bd9Sstevel@tonic-gate } 1615*7c478bd9Sstevel@tonic-gate sys_unblock_proto(PPP_IP); 1616*7c478bd9Sstevel@tonic-gate } 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate 1619*7c478bd9Sstevel@tonic-gate /* 1620*7c478bd9Sstevel@tonic-gate * ipcp_down - IPCP has gone DOWN. 1621*7c478bd9Sstevel@tonic-gate * 1622*7c478bd9Sstevel@tonic-gate * Take the IP network interface down, clear its addresses 1623*7c478bd9Sstevel@tonic-gate * and delete routes through it. 1624*7c478bd9Sstevel@tonic-gate */ 1625*7c478bd9Sstevel@tonic-gate static void 1626*7c478bd9Sstevel@tonic-gate ipcp_down(f) 1627*7c478bd9Sstevel@tonic-gate fsm *f; 1628*7c478bd9Sstevel@tonic-gate { 1629*7c478bd9Sstevel@tonic-gate IPCPDEBUG(("ipcp: down")); 1630*7c478bd9Sstevel@tonic-gate /* XXX a bit IPv4-centric here, we only need to get the stats 1631*7c478bd9Sstevel@tonic-gate * before the interface is marked down. */ 1632*7c478bd9Sstevel@tonic-gate update_link_stats(f->unit); 1633*7c478bd9Sstevel@tonic-gate if (ip_down_hook != NULL) 1634*7c478bd9Sstevel@tonic-gate (*ip_down_hook)(); 1635*7c478bd9Sstevel@tonic-gate if (ipcp_is_up[f->unit]) { 1636*7c478bd9Sstevel@tonic-gate ipcp_is_up[f->unit] = 0; 1637*7c478bd9Sstevel@tonic-gate np_down(f->unit, PPP_IP); 1638*7c478bd9Sstevel@tonic-gate } 1639*7c478bd9Sstevel@tonic-gate if (sifvjcomp(f->unit, 0, 0, 0) != 1) { 1640*7c478bd9Sstevel@tonic-gate if (debug) 1641*7c478bd9Sstevel@tonic-gate warn("Failed to disable VJ TCP header compression."); 1642*7c478bd9Sstevel@tonic-gate } 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate /* 1645*7c478bd9Sstevel@tonic-gate * If we are doing dial-on-demand, set the interface 1646*7c478bd9Sstevel@tonic-gate * to queue up outgoing packets (for now). 1647*7c478bd9Sstevel@tonic-gate */ 1648*7c478bd9Sstevel@tonic-gate if (demand) { 1649*7c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE) != 1) { 1650*7c478bd9Sstevel@tonic-gate if (debug) 1651*7c478bd9Sstevel@tonic-gate warn("Failed to enable Queueing on outgoing packets."); 1652*7c478bd9Sstevel@tonic-gate } 1653*7c478bd9Sstevel@tonic-gate } else { 1654*7c478bd9Sstevel@tonic-gate if (sifnpmode(f->unit, PPP_IP, NPMODE_ERROR) != 1) { 1655*7c478bd9Sstevel@tonic-gate if (debug) 1656*7c478bd9Sstevel@tonic-gate warn("Could not set interface to drop packets."); 1657*7c478bd9Sstevel@tonic-gate } 1658*7c478bd9Sstevel@tonic-gate if (sifdown(f->unit) != 1) 1659*7c478bd9Sstevel@tonic-gate warn("Could not bring interface down."); 1660*7c478bd9Sstevel@tonic-gate ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr, 1661*7c478bd9Sstevel@tonic-gate ipcp_hisoptions[f->unit].hisaddr); 1662*7c478bd9Sstevel@tonic-gate } 1663*7c478bd9Sstevel@tonic-gate 1664*7c478bd9Sstevel@tonic-gate /* Execute the ip-down script */ 1665*7c478bd9Sstevel@tonic-gate if (ipcp_script_state == s_up && ipcp_script_pid == 0) { 1666*7c478bd9Sstevel@tonic-gate ipcp_script_state = s_down; 1667*7c478bd9Sstevel@tonic-gate ipcp_script(_PATH_IPDOWN); 1668*7c478bd9Sstevel@tonic-gate } 1669*7c478bd9Sstevel@tonic-gate } 1670*7c478bd9Sstevel@tonic-gate 1671*7c478bd9Sstevel@tonic-gate 1672*7c478bd9Sstevel@tonic-gate /* 1673*7c478bd9Sstevel@tonic-gate * ipcp_clear_addrs() - clear the interface addresses, routes, 1674*7c478bd9Sstevel@tonic-gate * proxy arp entries, etc. 1675*7c478bd9Sstevel@tonic-gate */ 1676*7c478bd9Sstevel@tonic-gate static void 1677*7c478bd9Sstevel@tonic-gate ipcp_clear_addrs(unit, ouraddr, hisaddr) 1678*7c478bd9Sstevel@tonic-gate int unit; 1679*7c478bd9Sstevel@tonic-gate u_int32_t ouraddr; /* local address */ 1680*7c478bd9Sstevel@tonic-gate u_int32_t hisaddr; /* remote address */ 1681*7c478bd9Sstevel@tonic-gate { 1682*7c478bd9Sstevel@tonic-gate if (proxy_arp_set[unit]) { 1683*7c478bd9Sstevel@tonic-gate (void) cifproxyarp(unit, hisaddr); 1684*7c478bd9Sstevel@tonic-gate proxy_arp_set[unit] = 0; 1685*7c478bd9Sstevel@tonic-gate } 1686*7c478bd9Sstevel@tonic-gate if (default_route_set[unit]) { 1687*7c478bd9Sstevel@tonic-gate (void) cifdefaultroute(unit, ouraddr, hisaddr); 1688*7c478bd9Sstevel@tonic-gate default_route_set[unit] = 0; 1689*7c478bd9Sstevel@tonic-gate } 1690*7c478bd9Sstevel@tonic-gate if (cifaddr(unit, ouraddr, hisaddr) != 1) 1691*7c478bd9Sstevel@tonic-gate warn("Could not clear addresses"); 1692*7c478bd9Sstevel@tonic-gate } 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate 1695*7c478bd9Sstevel@tonic-gate /* 1696*7c478bd9Sstevel@tonic-gate * ipcp_finished - possibly shut down the lower layers. 1697*7c478bd9Sstevel@tonic-gate */ 1698*7c478bd9Sstevel@tonic-gate static void 1699*7c478bd9Sstevel@tonic-gate ipcp_finished(f) 1700*7c478bd9Sstevel@tonic-gate fsm *f; 1701*7c478bd9Sstevel@tonic-gate { 1702*7c478bd9Sstevel@tonic-gate np_finished(f->unit, PPP_IP); 1703*7c478bd9Sstevel@tonic-gate } 1704*7c478bd9Sstevel@tonic-gate 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate /* 1707*7c478bd9Sstevel@tonic-gate * ipcp_script_done - called when the ip-up or ip-down script 1708*7c478bd9Sstevel@tonic-gate * has finished. 1709*7c478bd9Sstevel@tonic-gate */ 1710*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1711*7c478bd9Sstevel@tonic-gate static void 1712*7c478bd9Sstevel@tonic-gate ipcp_script_done(arg, status) 1713*7c478bd9Sstevel@tonic-gate void *arg; 1714*7c478bd9Sstevel@tonic-gate int status; 1715*7c478bd9Sstevel@tonic-gate { 1716*7c478bd9Sstevel@tonic-gate ipcp_script_pid = 0; 1717*7c478bd9Sstevel@tonic-gate switch (ipcp_script_state) { 1718*7c478bd9Sstevel@tonic-gate case s_up: 1719*7c478bd9Sstevel@tonic-gate if (ipcp_fsm[0].state != OPENED) { 1720*7c478bd9Sstevel@tonic-gate ipcp_script_state = s_down; 1721*7c478bd9Sstevel@tonic-gate ipcp_script(_PATH_IPDOWN); 1722*7c478bd9Sstevel@tonic-gate } 1723*7c478bd9Sstevel@tonic-gate break; 1724*7c478bd9Sstevel@tonic-gate case s_down: 1725*7c478bd9Sstevel@tonic-gate if (ipcp_fsm[0].state == OPENED) { 1726*7c478bd9Sstevel@tonic-gate ipcp_script_state = s_up; 1727*7c478bd9Sstevel@tonic-gate ipcp_script(_PATH_IPUP); 1728*7c478bd9Sstevel@tonic-gate } 1729*7c478bd9Sstevel@tonic-gate break; 1730*7c478bd9Sstevel@tonic-gate } 1731*7c478bd9Sstevel@tonic-gate } 1732*7c478bd9Sstevel@tonic-gate 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate /* 1735*7c478bd9Sstevel@tonic-gate * ipcp_script - Execute a script with arguments 1736*7c478bd9Sstevel@tonic-gate * interface-name tty-name speed local-IP remote-IP. 1737*7c478bd9Sstevel@tonic-gate */ 1738*7c478bd9Sstevel@tonic-gate static void 1739*7c478bd9Sstevel@tonic-gate ipcp_script(script) 1740*7c478bd9Sstevel@tonic-gate char *script; 1741*7c478bd9Sstevel@tonic-gate { 1742*7c478bd9Sstevel@tonic-gate char strspeed[32], strlocal[32], strremote[32]; 1743*7c478bd9Sstevel@tonic-gate char *argv[8]; 1744*7c478bd9Sstevel@tonic-gate 1745*7c478bd9Sstevel@tonic-gate (void) slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); 1746*7c478bd9Sstevel@tonic-gate (void) slprintf(strlocal, sizeof(strlocal), "%I", 1747*7c478bd9Sstevel@tonic-gate ipcp_gotoptions[0].ouraddr); 1748*7c478bd9Sstevel@tonic-gate (void) slprintf(strremote, sizeof(strremote), "%I", 1749*7c478bd9Sstevel@tonic-gate ipcp_hisoptions[0].hisaddr); 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate argv[0] = script; 1752*7c478bd9Sstevel@tonic-gate argv[1] = ifname; 1753*7c478bd9Sstevel@tonic-gate argv[2] = devnam; 1754*7c478bd9Sstevel@tonic-gate argv[3] = strspeed; 1755*7c478bd9Sstevel@tonic-gate argv[4] = strlocal; 1756*7c478bd9Sstevel@tonic-gate argv[5] = strremote; 1757*7c478bd9Sstevel@tonic-gate argv[6] = ipparam; 1758*7c478bd9Sstevel@tonic-gate argv[7] = NULL; 1759*7c478bd9Sstevel@tonic-gate ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL); 1760*7c478bd9Sstevel@tonic-gate } 1761*7c478bd9Sstevel@tonic-gate 1762*7c478bd9Sstevel@tonic-gate /* 1763*7c478bd9Sstevel@tonic-gate * create_resolv - create the replacement resolv.conf file 1764*7c478bd9Sstevel@tonic-gate */ 1765*7c478bd9Sstevel@tonic-gate static void 1766*7c478bd9Sstevel@tonic-gate create_resolv(peerdns1, peerdns2) 1767*7c478bd9Sstevel@tonic-gate u_int32_t peerdns1, peerdns2; 1768*7c478bd9Sstevel@tonic-gate { 1769*7c478bd9Sstevel@tonic-gate FILE *f; 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate f = fopen(_PATH_RESOLV, "w"); 1772*7c478bd9Sstevel@tonic-gate if (f == NULL) { 1773*7c478bd9Sstevel@tonic-gate error("Failed to create %s: %m", _PATH_RESOLV); 1774*7c478bd9Sstevel@tonic-gate return; 1775*7c478bd9Sstevel@tonic-gate } 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate if (peerdns1) 1778*7c478bd9Sstevel@tonic-gate if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1)) <= 0) 1779*7c478bd9Sstevel@tonic-gate error("Write failed to %s: %m", _PATH_RESOLV); 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate if (peerdns2) 1782*7c478bd9Sstevel@tonic-gate if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2)) <= 0) 1783*7c478bd9Sstevel@tonic-gate error("Write failed to %s: %m", _PATH_RESOLV); 1784*7c478bd9Sstevel@tonic-gate 1785*7c478bd9Sstevel@tonic-gate if (fclose(f) != 0) 1786*7c478bd9Sstevel@tonic-gate error("Failed to close %s: %m", _PATH_RESOLV); 1787*7c478bd9Sstevel@tonic-gate } 1788*7c478bd9Sstevel@tonic-gate 1789*7c478bd9Sstevel@tonic-gate /* 1790*7c478bd9Sstevel@tonic-gate * ipcp_printpkt - print the contents of an IPCP packet. 1791*7c478bd9Sstevel@tonic-gate */ 1792*7c478bd9Sstevel@tonic-gate static int 1793*7c478bd9Sstevel@tonic-gate ipcp_printpkt(p, plen, printer, arg) 1794*7c478bd9Sstevel@tonic-gate u_char *p; 1795*7c478bd9Sstevel@tonic-gate int plen; 1796*7c478bd9Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)); 1797*7c478bd9Sstevel@tonic-gate void *arg; 1798*7c478bd9Sstevel@tonic-gate { 1799*7c478bd9Sstevel@tonic-gate int code, id, len, olen; 1800*7c478bd9Sstevel@tonic-gate u_char *pstart, *optend; 1801*7c478bd9Sstevel@tonic-gate u_short cishort; 1802*7c478bd9Sstevel@tonic-gate u_int32_t cilong; 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate if (plen < HEADERLEN) 1805*7c478bd9Sstevel@tonic-gate return 0; 1806*7c478bd9Sstevel@tonic-gate pstart = p; 1807*7c478bd9Sstevel@tonic-gate GETCHAR(code, p); 1808*7c478bd9Sstevel@tonic-gate GETCHAR(id, p); 1809*7c478bd9Sstevel@tonic-gate GETSHORT(len, p); 1810*7c478bd9Sstevel@tonic-gate if (len < HEADERLEN || len > plen) 1811*7c478bd9Sstevel@tonic-gate return 0; 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate printer(arg, " %s id=0x%x", code_name(code, 1), id); 1814*7c478bd9Sstevel@tonic-gate len -= HEADERLEN; 1815*7c478bd9Sstevel@tonic-gate switch (code) { 1816*7c478bd9Sstevel@tonic-gate case CODE_CONFREQ: 1817*7c478bd9Sstevel@tonic-gate case CODE_CONFACK: 1818*7c478bd9Sstevel@tonic-gate case CODE_CONFNAK: 1819*7c478bd9Sstevel@tonic-gate case CODE_CONFREJ: 1820*7c478bd9Sstevel@tonic-gate /* print option list */ 1821*7c478bd9Sstevel@tonic-gate while (len >= 2) { 1822*7c478bd9Sstevel@tonic-gate GETCHAR(code, p); 1823*7c478bd9Sstevel@tonic-gate GETCHAR(olen, p); 1824*7c478bd9Sstevel@tonic-gate p -= 2; 1825*7c478bd9Sstevel@tonic-gate if (olen < 2 || olen > len) { 1826*7c478bd9Sstevel@tonic-gate break; 1827*7c478bd9Sstevel@tonic-gate } 1828*7c478bd9Sstevel@tonic-gate printer(arg, " <"); 1829*7c478bd9Sstevel@tonic-gate len -= olen; 1830*7c478bd9Sstevel@tonic-gate optend = p + olen; 1831*7c478bd9Sstevel@tonic-gate switch (code) { 1832*7c478bd9Sstevel@tonic-gate case CI_ADDRS: 1833*7c478bd9Sstevel@tonic-gate if (olen == CILEN_ADDRS) { 1834*7c478bd9Sstevel@tonic-gate p += 2; 1835*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); 1836*7c478bd9Sstevel@tonic-gate printer(arg, "addrs %I", cilong); 1837*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); 1838*7c478bd9Sstevel@tonic-gate printer(arg, " %I", cilong); 1839*7c478bd9Sstevel@tonic-gate } 1840*7c478bd9Sstevel@tonic-gate break; 1841*7c478bd9Sstevel@tonic-gate case CI_COMPRESSTYPE: 1842*7c478bd9Sstevel@tonic-gate if (olen >= CILEN_COMPRESS) { 1843*7c478bd9Sstevel@tonic-gate p += 2; 1844*7c478bd9Sstevel@tonic-gate GETSHORT(cishort, p); 1845*7c478bd9Sstevel@tonic-gate printer(arg, "compress "); 1846*7c478bd9Sstevel@tonic-gate switch (cishort) { 1847*7c478bd9Sstevel@tonic-gate case IPCP_VJ_COMP: 1848*7c478bd9Sstevel@tonic-gate printer(arg, "VJ"); 1849*7c478bd9Sstevel@tonic-gate break; 1850*7c478bd9Sstevel@tonic-gate case IPCP_VJ_COMP_OLD: 1851*7c478bd9Sstevel@tonic-gate printer(arg, "old-VJ"); 1852*7c478bd9Sstevel@tonic-gate break; 1853*7c478bd9Sstevel@tonic-gate default: 1854*7c478bd9Sstevel@tonic-gate printer(arg, "0x%x", cishort); 1855*7c478bd9Sstevel@tonic-gate } 1856*7c478bd9Sstevel@tonic-gate } 1857*7c478bd9Sstevel@tonic-gate break; 1858*7c478bd9Sstevel@tonic-gate case CI_ADDR: 1859*7c478bd9Sstevel@tonic-gate if (olen == CILEN_ADDR) { 1860*7c478bd9Sstevel@tonic-gate p += 2; 1861*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); 1862*7c478bd9Sstevel@tonic-gate printer(arg, "addr %I", cilong); 1863*7c478bd9Sstevel@tonic-gate } 1864*7c478bd9Sstevel@tonic-gate break; 1865*7c478bd9Sstevel@tonic-gate case CI_MS_DNS1: 1866*7c478bd9Sstevel@tonic-gate case CI_MS_DNS2: 1867*7c478bd9Sstevel@tonic-gate p += 2; 1868*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); 1869*7c478bd9Sstevel@tonic-gate printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1 ? 1 : 2), 1870*7c478bd9Sstevel@tonic-gate cilong); 1871*7c478bd9Sstevel@tonic-gate break; 1872*7c478bd9Sstevel@tonic-gate case CI_MS_WINS1: 1873*7c478bd9Sstevel@tonic-gate case CI_MS_WINS2: 1874*7c478bd9Sstevel@tonic-gate p += 2; 1875*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); 1876*7c478bd9Sstevel@tonic-gate printer(arg, "ms-wins%d %I", (code == CI_MS_WINS1 ? 1 : 2), 1877*7c478bd9Sstevel@tonic-gate cilong); 1878*7c478bd9Sstevel@tonic-gate break; 1879*7c478bd9Sstevel@tonic-gate case CI_SUBNET: 1880*7c478bd9Sstevel@tonic-gate p += 2; 1881*7c478bd9Sstevel@tonic-gate GETNLONG(cilong, p); 1882*7c478bd9Sstevel@tonic-gate printer(arg, "subnet %I", cilong); 1883*7c478bd9Sstevel@tonic-gate break; 1884*7c478bd9Sstevel@tonic-gate } 1885*7c478bd9Sstevel@tonic-gate while (p < optend) { 1886*7c478bd9Sstevel@tonic-gate GETCHAR(code, p); 1887*7c478bd9Sstevel@tonic-gate printer(arg, " %.2x", code); 1888*7c478bd9Sstevel@tonic-gate } 1889*7c478bd9Sstevel@tonic-gate printer(arg, ">"); 1890*7c478bd9Sstevel@tonic-gate } 1891*7c478bd9Sstevel@tonic-gate break; 1892*7c478bd9Sstevel@tonic-gate 1893*7c478bd9Sstevel@tonic-gate case CODE_TERMACK: 1894*7c478bd9Sstevel@tonic-gate case CODE_TERMREQ: 1895*7c478bd9Sstevel@tonic-gate if (len > 0 && *p >= ' ' && *p < 0x7f) { 1896*7c478bd9Sstevel@tonic-gate printer(arg, " "); 1897*7c478bd9Sstevel@tonic-gate print_string((char *)p, len, printer, arg); 1898*7c478bd9Sstevel@tonic-gate p += len; 1899*7c478bd9Sstevel@tonic-gate len = 0; 1900*7c478bd9Sstevel@tonic-gate } 1901*7c478bd9Sstevel@tonic-gate break; 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate 1904*7c478bd9Sstevel@tonic-gate /* print the rest of the bytes in the packet */ 1905*7c478bd9Sstevel@tonic-gate for (; len > 0; --len) { 1906*7c478bd9Sstevel@tonic-gate GETCHAR(code, p); 1907*7c478bd9Sstevel@tonic-gate printer(arg, " %.2x", code); 1908*7c478bd9Sstevel@tonic-gate } 1909*7c478bd9Sstevel@tonic-gate 1910*7c478bd9Sstevel@tonic-gate return p - pstart; 1911*7c478bd9Sstevel@tonic-gate } 1912*7c478bd9Sstevel@tonic-gate 1913*7c478bd9Sstevel@tonic-gate /* 1914*7c478bd9Sstevel@tonic-gate * ip_active_pkt - see if this IP packet is worth bringing the link up for. 1915*7c478bd9Sstevel@tonic-gate * We don't bring the link up for IP fragments or for TCP FIN packets 1916*7c478bd9Sstevel@tonic-gate * with no data. 1917*7c478bd9Sstevel@tonic-gate */ 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate static int 1920*7c478bd9Sstevel@tonic-gate ip_active_pkt(pkt, len) 1921*7c478bd9Sstevel@tonic-gate u_char *pkt; 1922*7c478bd9Sstevel@tonic-gate int len; 1923*7c478bd9Sstevel@tonic-gate { 1924*7c478bd9Sstevel@tonic-gate u_char *tcp; 1925*7c478bd9Sstevel@tonic-gate struct protoent *pep; 1926*7c478bd9Sstevel@tonic-gate int val; 1927*7c478bd9Sstevel@tonic-gate int hlen; 1928*7c478bd9Sstevel@tonic-gate char buf[32], *cp; 1929*7c478bd9Sstevel@tonic-gate u_int32_t src, dst; 1930*7c478bd9Sstevel@tonic-gate 1931*7c478bd9Sstevel@tonic-gate len -= PPP_HDRLEN; 1932*7c478bd9Sstevel@tonic-gate pkt += PPP_HDRLEN; 1933*7c478bd9Sstevel@tonic-gate if (len < IP_HDRLEN) { 1934*7c478bd9Sstevel@tonic-gate dbglog("IP packet of length %d is not activity", len); 1935*7c478bd9Sstevel@tonic-gate return 0; 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate src = get_ipsrc(pkt); 1938*7c478bd9Sstevel@tonic-gate dst = get_ipdst(pkt); 1939*7c478bd9Sstevel@tonic-gate if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { 1940*7c478bd9Sstevel@tonic-gate dbglog("IP fragment from %I->%I is not activity", src, dst); 1941*7c478bd9Sstevel@tonic-gate return 0; 1942*7c478bd9Sstevel@tonic-gate } 1943*7c478bd9Sstevel@tonic-gate val = get_ipproto(pkt); 1944*7c478bd9Sstevel@tonic-gate if (val != IPPROTO_TCP) { 1945*7c478bd9Sstevel@tonic-gate if (debug) { 1946*7c478bd9Sstevel@tonic-gate if ((pep = getprotobynumber(val)) != NULL) { 1947*7c478bd9Sstevel@tonic-gate cp = pep->p_name; 1948*7c478bd9Sstevel@tonic-gate } else { 1949*7c478bd9Sstevel@tonic-gate (void) slprintf(buf, sizeof (buf), "IP proto %d", val); 1950*7c478bd9Sstevel@tonic-gate cp = buf; 1951*7c478bd9Sstevel@tonic-gate } 1952*7c478bd9Sstevel@tonic-gate dbglog("%s from %I->%I is activity", cp, src, dst); 1953*7c478bd9Sstevel@tonic-gate } 1954*7c478bd9Sstevel@tonic-gate return 1; 1955*7c478bd9Sstevel@tonic-gate } 1956*7c478bd9Sstevel@tonic-gate hlen = get_iphl(pkt) * 4; 1957*7c478bd9Sstevel@tonic-gate if (len < hlen + TCP_HDRLEN) { 1958*7c478bd9Sstevel@tonic-gate dbglog("Bad TCP length %d<%d+%d %I->%I is not activity", len, hlen, 1959*7c478bd9Sstevel@tonic-gate TCP_HDRLEN, src, dst); 1960*7c478bd9Sstevel@tonic-gate return 0; 1961*7c478bd9Sstevel@tonic-gate } 1962*7c478bd9Sstevel@tonic-gate tcp = pkt + hlen; 1963*7c478bd9Sstevel@tonic-gate val = get_tcpflags(tcp); 1964*7c478bd9Sstevel@tonic-gate hlen += get_tcpoff(tcp) * 4; 1965*7c478bd9Sstevel@tonic-gate if ((val & TH_FIN) != 0 && len == hlen) { 1966*7c478bd9Sstevel@tonic-gate dbglog("Empty TCP FIN %I->%I is not activity", src, dst); 1967*7c478bd9Sstevel@tonic-gate return 0; 1968*7c478bd9Sstevel@tonic-gate } 1969*7c478bd9Sstevel@tonic-gate if (debug) { 1970*7c478bd9Sstevel@tonic-gate cp = buf; 1971*7c478bd9Sstevel@tonic-gate if (val & TH_URG) 1972*7c478bd9Sstevel@tonic-gate *cp++ = 'U'; 1973*7c478bd9Sstevel@tonic-gate if (val & TH_ACK) 1974*7c478bd9Sstevel@tonic-gate *cp++ = 'A'; 1975*7c478bd9Sstevel@tonic-gate if (val & TH_PUSH) 1976*7c478bd9Sstevel@tonic-gate *cp++ = 'P'; 1977*7c478bd9Sstevel@tonic-gate if (val & TH_RST) 1978*7c478bd9Sstevel@tonic-gate *cp++ = 'R'; 1979*7c478bd9Sstevel@tonic-gate if (val & TH_SYN) 1980*7c478bd9Sstevel@tonic-gate *cp++ = 'S'; 1981*7c478bd9Sstevel@tonic-gate if (val & TH_FIN) 1982*7c478bd9Sstevel@tonic-gate *cp++ = 'F'; 1983*7c478bd9Sstevel@tonic-gate if (cp != buf) 1984*7c478bd9Sstevel@tonic-gate *cp++ = ' '; 1985*7c478bd9Sstevel@tonic-gate *cp = '\0'; 1986*7c478bd9Sstevel@tonic-gate dbglog("TCP %d data %s%I->%I is activity", len - hlen, buf, src, dst); 1987*7c478bd9Sstevel@tonic-gate } 1988*7c478bd9Sstevel@tonic-gate return 1; 1989*7c478bd9Sstevel@tonic-gate } 1990*7c478bd9Sstevel@tonic-gate 1991*7c478bd9Sstevel@tonic-gate static void 1992*7c478bd9Sstevel@tonic-gate ipcp_print_stat(unit, strptr) 1993*7c478bd9Sstevel@tonic-gate int unit; 1994*7c478bd9Sstevel@tonic-gate FILE *strptr; 1995*7c478bd9Sstevel@tonic-gate { 1996*7c478bd9Sstevel@tonic-gate ipcp_options *go = &ipcp_gotoptions[unit]; 1997*7c478bd9Sstevel@tonic-gate ipcp_options *ho = &ipcp_hisoptions[unit]; 1998*7c478bd9Sstevel@tonic-gate char *proto_name = ipcp_protent.name; 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate if (!ipcp_protent.enabled_flag) { 2001*7c478bd9Sstevel@tonic-gate (void) flprintf(strptr, "%s disabled\n", proto_name); 2002*7c478bd9Sstevel@tonic-gate return; 2003*7c478bd9Sstevel@tonic-gate } 2004*7c478bd9Sstevel@tonic-gate 2005*7c478bd9Sstevel@tonic-gate (void) flprintf(strptr, "%s state: %s", proto_name, 2006*7c478bd9Sstevel@tonic-gate fsm_state(ipcp_fsm[unit].state)); 2007*7c478bd9Sstevel@tonic-gate (void) flprintf(strptr, "%s local %I remote %I", proto_name, go->ouraddr, 2008*7c478bd9Sstevel@tonic-gate ho->ouraddr); 2009*7c478bd9Sstevel@tonic-gate } 2010