1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * cbcp - Call Back Configuration Protocol. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000 by Sun Microsystems, Inc. 5*7c478bd9Sstevel@tonic-gate * All rights reserved. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Pedro Roque Marques 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 Pedro Roque Marques. The name of the author may not be used to 16*7c478bd9Sstevel@tonic-gate * endorse or promote products derived from this software without 17*7c478bd9Sstevel@tonic-gate * specific prior written permission. 18*7c478bd9Sstevel@tonic-gate * 19*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 20*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 21*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22*7c478bd9Sstevel@tonic-gate */ 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 25*7c478bd9Sstevel@tonic-gate #define RCSID "$Id: cbcp.c,v 1.10 1999/08/13 06:46:10 paulus Exp $" 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #include <stdio.h> 28*7c478bd9Sstevel@tonic-gate #include <string.h> 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include "pppd.h" 33*7c478bd9Sstevel@tonic-gate #include "cbcp.h" 34*7c478bd9Sstevel@tonic-gate #include "fsm.h" 35*7c478bd9Sstevel@tonic-gate #include "lcp.h" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 38*7c478bd9Sstevel@tonic-gate static const char rcsid[] = RCSID; 39*7c478bd9Sstevel@tonic-gate #endif 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * Options. 43*7c478bd9Sstevel@tonic-gate */ 44*7c478bd9Sstevel@tonic-gate static int setcbcp __P((char **, option_t *)); 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate static option_t cbcp_option_list[] = { 47*7c478bd9Sstevel@tonic-gate { "callback", o_special, (void *)setcbcp, 48*7c478bd9Sstevel@tonic-gate "Ask for callback" }, 49*7c478bd9Sstevel@tonic-gate { NULL } 50*7c478bd9Sstevel@tonic-gate }; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* 53*7c478bd9Sstevel@tonic-gate * Protocol entry points. 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate static void cbcp_init __P((int unit)); 56*7c478bd9Sstevel@tonic-gate static void cbcp_lowerup __P((int unit)); 57*7c478bd9Sstevel@tonic-gate static void cbcp_input __P((int unit, u_char *pkt, int len)); 58*7c478bd9Sstevel@tonic-gate static void cbcp_protrej __P((int unit)); 59*7c478bd9Sstevel@tonic-gate static int cbcp_printpkt __P((u_char *pkt, int len, 60*7c478bd9Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)), 61*7c478bd9Sstevel@tonic-gate void *arg)); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate struct protent cbcp_protent = { 64*7c478bd9Sstevel@tonic-gate PPP_CBCP, /* PPP protocol number */ 65*7c478bd9Sstevel@tonic-gate cbcp_init, /* Initialization procedure */ 66*7c478bd9Sstevel@tonic-gate cbcp_input, /* Process a received packet */ 67*7c478bd9Sstevel@tonic-gate cbcp_protrej, /* Process a received protocol-reject */ 68*7c478bd9Sstevel@tonic-gate cbcp_lowerup, /* Lower layer has come up */ 69*7c478bd9Sstevel@tonic-gate NULL, /* Lower layer has gone down */ 70*7c478bd9Sstevel@tonic-gate NULL, /* Open the protocol */ 71*7c478bd9Sstevel@tonic-gate NULL, /* Close the protocol */ 72*7c478bd9Sstevel@tonic-gate cbcp_printpkt, /* Print a packet in readable form */ 73*7c478bd9Sstevel@tonic-gate NULL, /* Process a received data packet */ 74*7c478bd9Sstevel@tonic-gate 0, /* 0 iff protocol is disabled */ 75*7c478bd9Sstevel@tonic-gate "CBCP", /* Text name of protocol */ 76*7c478bd9Sstevel@tonic-gate NULL, /* Text name of corresponding data protocol */ 77*7c478bd9Sstevel@tonic-gate cbcp_option_list, /* List of command-line options */ 78*7c478bd9Sstevel@tonic-gate NULL, /* Check requested options, assign defaults */ 79*7c478bd9Sstevel@tonic-gate NULL, /* Configure interface for demand-dial */ 80*7c478bd9Sstevel@tonic-gate NULL /* Say whether to bring up link for this pkt */ 81*7c478bd9Sstevel@tonic-gate }; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* Not static'd for plug-ins */ 84*7c478bd9Sstevel@tonic-gate cbcp_state cbcp[NUM_PPP]; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate /* internal prototypes */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len)); 89*7c478bd9Sstevel@tonic-gate static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len)); 90*7c478bd9Sstevel@tonic-gate static void cbcp_send __P((cbcp_state *us, int code, u_char *buf, int len)); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* option processing */ 93*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 94*7c478bd9Sstevel@tonic-gate static int 95*7c478bd9Sstevel@tonic-gate setcbcp(argv, opt) 96*7c478bd9Sstevel@tonic-gate char **argv; 97*7c478bd9Sstevel@tonic-gate option_t *opt; 98*7c478bd9Sstevel@tonic-gate { 99*7c478bd9Sstevel@tonic-gate lcp_wantoptions[0].neg_cbcp = 1; 100*7c478bd9Sstevel@tonic-gate cbcp_protent.enabled_flag = 1; 101*7c478bd9Sstevel@tonic-gate cbcp[0].us_number = strdup(*argv); 102*7c478bd9Sstevel@tonic-gate if (cbcp[0].us_number == NULL) 103*7c478bd9Sstevel@tonic-gate novm("callback number"); 104*7c478bd9Sstevel@tonic-gate cbcp[0].us_type |= (1 << CB_CONF_USER); 105*7c478bd9Sstevel@tonic-gate cbcp[0].us_type |= (1 << CB_CONF_ADMIN); 106*7c478bd9Sstevel@tonic-gate return (1); 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* init state */ 110*7c478bd9Sstevel@tonic-gate static void 111*7c478bd9Sstevel@tonic-gate cbcp_init(unit) 112*7c478bd9Sstevel@tonic-gate int unit; 113*7c478bd9Sstevel@tonic-gate { 114*7c478bd9Sstevel@tonic-gate cbcp_state *us; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate us = &cbcp[unit]; 117*7c478bd9Sstevel@tonic-gate BZERO(us, sizeof(cbcp_state)); 118*7c478bd9Sstevel@tonic-gate us->us_unit = unit; 119*7c478bd9Sstevel@tonic-gate us->us_type |= (1 << CB_CONF_NO); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* lower layer is up */ 123*7c478bd9Sstevel@tonic-gate static void 124*7c478bd9Sstevel@tonic-gate cbcp_lowerup(unit) 125*7c478bd9Sstevel@tonic-gate int unit; 126*7c478bd9Sstevel@tonic-gate { 127*7c478bd9Sstevel@tonic-gate cbcp_state *us = &cbcp[unit]; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if (debug) { 130*7c478bd9Sstevel@tonic-gate dbglog("cbcp_lowerup: want: %d", us->us_type); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate if (us->us_type == CB_CONF_USER) 133*7c478bd9Sstevel@tonic-gate dbglog("phone no: %s", us->us_number); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* process an incoming packet */ 138*7c478bd9Sstevel@tonic-gate static void 139*7c478bd9Sstevel@tonic-gate cbcp_input(unit, inpacket, pktlen) 140*7c478bd9Sstevel@tonic-gate int unit; 141*7c478bd9Sstevel@tonic-gate u_char *inpacket; 142*7c478bd9Sstevel@tonic-gate int pktlen; 143*7c478bd9Sstevel@tonic-gate { 144*7c478bd9Sstevel@tonic-gate u_char *inp; 145*7c478bd9Sstevel@tonic-gate u_char code, id; 146*7c478bd9Sstevel@tonic-gate u_short len; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate cbcp_state *us = &cbcp[unit]; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate inp = inpacket; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate if (pktlen < CBCP_MINLEN) { 153*7c478bd9Sstevel@tonic-gate error("CBCP packet is too small (%d < %d)", pktlen, CBCP_MINLEN); 154*7c478bd9Sstevel@tonic-gate return; 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate GETCHAR(code, inp); 158*7c478bd9Sstevel@tonic-gate GETCHAR(id, inp); 159*7c478bd9Sstevel@tonic-gate GETSHORT(len, inp); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if (len > pktlen) { 162*7c478bd9Sstevel@tonic-gate error("CBCP packet: invalid length (%d > %d)", len, pktlen); 163*7c478bd9Sstevel@tonic-gate return; 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate len -= CBCP_MINLEN; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate switch (code) { 169*7c478bd9Sstevel@tonic-gate case CBCP_REQ: 170*7c478bd9Sstevel@tonic-gate us->us_id = id; 171*7c478bd9Sstevel@tonic-gate cbcp_recvreq(us, inp, len); 172*7c478bd9Sstevel@tonic-gate break; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate case CBCP_RESP: 175*7c478bd9Sstevel@tonic-gate if (debug) 176*7c478bd9Sstevel@tonic-gate dbglog("CBCP Response received; no request sent"); 177*7c478bd9Sstevel@tonic-gate break; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate case CBCP_ACK: 180*7c478bd9Sstevel@tonic-gate if (id != us->us_id) { 181*7c478bd9Sstevel@tonic-gate if (debug) 182*7c478bd9Sstevel@tonic-gate dbglog("CBCP Ack ID %d doesn't match expected %d", id, 183*7c478bd9Sstevel@tonic-gate us->us_id); 184*7c478bd9Sstevel@tonic-gate break; 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate cbcp_recvack(us, inp, len); 188*7c478bd9Sstevel@tonic-gate break; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate default: 191*7c478bd9Sstevel@tonic-gate if (debug) 192*7c478bd9Sstevel@tonic-gate dbglog("Unknown CBCP code number %d", code); 193*7c478bd9Sstevel@tonic-gate break; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* protocol was rejected by foe */ 198*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 199*7c478bd9Sstevel@tonic-gate static void 200*7c478bd9Sstevel@tonic-gate cbcp_protrej(int unit) 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate start_networks(); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate static char *cbcp_codenames[] = { 206*7c478bd9Sstevel@tonic-gate "Request", "Response", "Ack" 207*7c478bd9Sstevel@tonic-gate }; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate static char *cbcp_optionnames[] = { 210*7c478bd9Sstevel@tonic-gate "NoCallback", 211*7c478bd9Sstevel@tonic-gate "UserDefined", 212*7c478bd9Sstevel@tonic-gate "AdminDefined", 213*7c478bd9Sstevel@tonic-gate "List" 214*7c478bd9Sstevel@tonic-gate }; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate /* 217*7c478bd9Sstevel@tonic-gate * Pretty print a packet. Return value is number of bytes parsed out 218*7c478bd9Sstevel@tonic-gate * of the packet and printed in some way. Caller (in util.c) will 219*7c478bd9Sstevel@tonic-gate * print the remainder of the packet. 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate static int 222*7c478bd9Sstevel@tonic-gate cbcp_printpkt(p, plen, printer, arg) 223*7c478bd9Sstevel@tonic-gate u_char *p; 224*7c478bd9Sstevel@tonic-gate int plen; 225*7c478bd9Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)); 226*7c478bd9Sstevel@tonic-gate void *arg; 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate int code, id, len, olen, alen; 229*7c478bd9Sstevel@tonic-gate u_char *pstart, cichar; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if (plen < HEADERLEN) { 232*7c478bd9Sstevel@tonic-gate printer(arg, "too short (%d<%d)", plen, HEADERLEN); 233*7c478bd9Sstevel@tonic-gate return (0); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate pstart = p; 236*7c478bd9Sstevel@tonic-gate GETCHAR(code, p); 237*7c478bd9Sstevel@tonic-gate GETCHAR(id, p); 238*7c478bd9Sstevel@tonic-gate GETSHORT(len, p); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate if (code >= 1 && code <= Dim(cbcp_codenames)) 241*7c478bd9Sstevel@tonic-gate printer(arg, " %s", cbcp_codenames[code-1]); 242*7c478bd9Sstevel@tonic-gate else 243*7c478bd9Sstevel@tonic-gate printer(arg, " code=0x%x", code); 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate printer(arg, " id=0x%x", id); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate if (len < HEADERLEN) { 248*7c478bd9Sstevel@tonic-gate printer(arg, " header length %d<%d", len, HEADERLEN); 249*7c478bd9Sstevel@tonic-gate return (HEADERLEN); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate if (len > plen) { 252*7c478bd9Sstevel@tonic-gate printer(arg, " truncated (%d>%d)", len, plen); 253*7c478bd9Sstevel@tonic-gate len = plen; 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate len -= HEADERLEN; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate switch (code) { 258*7c478bd9Sstevel@tonic-gate case CBCP_REQ: 259*7c478bd9Sstevel@tonic-gate case CBCP_RESP: 260*7c478bd9Sstevel@tonic-gate case CBCP_ACK: 261*7c478bd9Sstevel@tonic-gate while (len >= 2) { 262*7c478bd9Sstevel@tonic-gate GETCHAR(cichar, p); 263*7c478bd9Sstevel@tonic-gate GETCHAR(olen, p); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if (olen < 2) 266*7c478bd9Sstevel@tonic-gate break; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate printer(arg, " <"); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate if (olen > len) { 271*7c478bd9Sstevel@tonic-gate printer(arg, "trunc[%d>%d] ", olen, len); 272*7c478bd9Sstevel@tonic-gate olen = len; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate len -= olen; 275*7c478bd9Sstevel@tonic-gate olen -= 2; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate if (cichar >= 1 && cichar <= Dim(cbcp_optionnames)) 278*7c478bd9Sstevel@tonic-gate printer(arg, " %s", cbcp_optionnames[cichar-1]); 279*7c478bd9Sstevel@tonic-gate else 280*7c478bd9Sstevel@tonic-gate printer(arg, " option=0x%x", cichar); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (olen > 0) { 283*7c478bd9Sstevel@tonic-gate GETCHAR(cichar, p); 284*7c478bd9Sstevel@tonic-gate olen--; 285*7c478bd9Sstevel@tonic-gate printer(arg, " delay=%d", cichar); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate while (olen > 0) { 289*7c478bd9Sstevel@tonic-gate GETCHAR(cichar, p); 290*7c478bd9Sstevel@tonic-gate olen--; 291*7c478bd9Sstevel@tonic-gate if (cichar != 1) 292*7c478bd9Sstevel@tonic-gate printer(arg, " (type %d?)", cichar); 293*7c478bd9Sstevel@tonic-gate alen = strllen((const char *)p, olen); 294*7c478bd9Sstevel@tonic-gate if (olen > 0 && alen > 0) 295*7c478bd9Sstevel@tonic-gate printer(arg, " '%.*s'", alen, p); 296*7c478bd9Sstevel@tonic-gate else 297*7c478bd9Sstevel@tonic-gate printer(arg, " null"); 298*7c478bd9Sstevel@tonic-gate p += alen + 1; 299*7c478bd9Sstevel@tonic-gate olen -= alen + 1; 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate printer(arg, ">"); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate default: 305*7c478bd9Sstevel@tonic-gate break; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if (len > 0) { 309*7c478bd9Sstevel@tonic-gate if (len > 8) 310*7c478bd9Sstevel@tonic-gate printer(arg, "%8B ...", p); 311*7c478bd9Sstevel@tonic-gate else 312*7c478bd9Sstevel@tonic-gate printer(arg, "%.*B", len, p); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate p += len; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate return p - pstart; 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* 320*7c478bd9Sstevel@tonic-gate * received CBCP request. 321*7c478bd9Sstevel@tonic-gate * No reason to print packet contents in detail here, since enabling 322*7c478bd9Sstevel@tonic-gate * debug mode will cause the print routine above to be invoked. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate static void 325*7c478bd9Sstevel@tonic-gate cbcp_recvreq(us, pckt, pcktlen) 326*7c478bd9Sstevel@tonic-gate cbcp_state *us; 327*7c478bd9Sstevel@tonic-gate u_char *pckt; 328*7c478bd9Sstevel@tonic-gate int pcktlen; 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate u_char type, opt_len; 331*7c478bd9Sstevel@tonic-gate int len = pcktlen; 332*7c478bd9Sstevel@tonic-gate u_char cb_type; 333*7c478bd9Sstevel@tonic-gate u_char buf[256]; 334*7c478bd9Sstevel@tonic-gate u_char *bufp = buf; 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate us->us_allowed = 0; 337*7c478bd9Sstevel@tonic-gate while (len > 0) { 338*7c478bd9Sstevel@tonic-gate GETCHAR(type, pckt); 339*7c478bd9Sstevel@tonic-gate GETCHAR(opt_len, pckt); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate if (opt_len > 2) { 342*7c478bd9Sstevel@tonic-gate pckt++; /* ignore the delay time */ 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate len -= opt_len; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Careful; don't use left-shift operator on numbers that are 349*7c478bd9Sstevel@tonic-gate * too big. 350*7c478bd9Sstevel@tonic-gate */ 351*7c478bd9Sstevel@tonic-gate if (type > CB_CONF_LIST) { 352*7c478bd9Sstevel@tonic-gate if (debug) 353*7c478bd9Sstevel@tonic-gate dbglog("CBCP: ignoring unknown type %d", type); 354*7c478bd9Sstevel@tonic-gate continue; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate us->us_allowed |= (1 << type); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate switch (type) { 360*7c478bd9Sstevel@tonic-gate case CB_CONF_NO: 361*7c478bd9Sstevel@tonic-gate if (debug) 362*7c478bd9Sstevel@tonic-gate dbglog("CBCP: operation without callback allowed"); 363*7c478bd9Sstevel@tonic-gate break; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate case CB_CONF_USER: 366*7c478bd9Sstevel@tonic-gate if (debug) 367*7c478bd9Sstevel@tonic-gate dbglog("callback to user-specified number allowed"); 368*7c478bd9Sstevel@tonic-gate break; 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate case CB_CONF_ADMIN: 371*7c478bd9Sstevel@tonic-gate if (debug) 372*7c478bd9Sstevel@tonic-gate dbglog("CBCP: callback to admin-defined address allowed"); 373*7c478bd9Sstevel@tonic-gate break; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate case CB_CONF_LIST: 376*7c478bd9Sstevel@tonic-gate if (debug) 377*7c478bd9Sstevel@tonic-gate dbglog("CBCP: callback to one out of list allowed"); 378*7c478bd9Sstevel@tonic-gate break; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* Now generate the response */ 383*7c478bd9Sstevel@tonic-gate len = 0; 384*7c478bd9Sstevel@tonic-gate cb_type = us->us_allowed & us->us_type; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate if (cb_type & ( 1 << CB_CONF_USER ) ) { 387*7c478bd9Sstevel@tonic-gate if (debug) 388*7c478bd9Sstevel@tonic-gate dbglog("CBCP Response: selecting user-specified number"); 389*7c478bd9Sstevel@tonic-gate PUTCHAR(CB_CONF_USER, bufp); 390*7c478bd9Sstevel@tonic-gate len = 3 + 1 + strlen(us->us_number) + 1; 391*7c478bd9Sstevel@tonic-gate PUTCHAR(len , bufp); 392*7c478bd9Sstevel@tonic-gate PUTCHAR(5, bufp); /* delay */ 393*7c478bd9Sstevel@tonic-gate PUTCHAR(1, bufp); 394*7c478bd9Sstevel@tonic-gate BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); 395*7c478bd9Sstevel@tonic-gate cbcp_send(us, CBCP_RESP, buf, len); 396*7c478bd9Sstevel@tonic-gate return; 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { 400*7c478bd9Sstevel@tonic-gate if (debug) 401*7c478bd9Sstevel@tonic-gate dbglog("CBCP Response: selecting admin-specified number"); 402*7c478bd9Sstevel@tonic-gate PUTCHAR(CB_CONF_ADMIN, bufp); 403*7c478bd9Sstevel@tonic-gate len = 3; 404*7c478bd9Sstevel@tonic-gate PUTCHAR(len, bufp); 405*7c478bd9Sstevel@tonic-gate PUTCHAR(5, bufp); /* delay */ 406*7c478bd9Sstevel@tonic-gate cbcp_send(us, CBCP_RESP, buf, len); 407*7c478bd9Sstevel@tonic-gate return; 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate if (cb_type & ( 1 << CB_CONF_NO ) ) { 411*7c478bd9Sstevel@tonic-gate if (debug) 412*7c478bd9Sstevel@tonic-gate dbglog("CBCP Response: selecting no-callback mode"); 413*7c478bd9Sstevel@tonic-gate PUTCHAR(CB_CONF_NO, bufp); 414*7c478bd9Sstevel@tonic-gate len = 3; 415*7c478bd9Sstevel@tonic-gate PUTCHAR(len , bufp); 416*7c478bd9Sstevel@tonic-gate PUTCHAR(0, bufp); 417*7c478bd9Sstevel@tonic-gate cbcp_send(us, CBCP_RESP, buf, len); 418*7c478bd9Sstevel@tonic-gate start_networks(); 419*7c478bd9Sstevel@tonic-gate return; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (debug) 423*7c478bd9Sstevel@tonic-gate dbglog("CBCP: no callback types in common"); 424*7c478bd9Sstevel@tonic-gate lcp_close(us->us_unit, "No CBCP callback options available"); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate static void 428*7c478bd9Sstevel@tonic-gate cbcp_send(us, code, buf, len) 429*7c478bd9Sstevel@tonic-gate cbcp_state *us; 430*7c478bd9Sstevel@tonic-gate int code; 431*7c478bd9Sstevel@tonic-gate u_char *buf; 432*7c478bd9Sstevel@tonic-gate int len; 433*7c478bd9Sstevel@tonic-gate { 434*7c478bd9Sstevel@tonic-gate u_char *outp; 435*7c478bd9Sstevel@tonic-gate int outlen; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate outp = outpacket_buf; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate outlen = 4 + len; 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate MAKEHEADER(outp, PPP_CBCP); 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate PUTCHAR(code, outp); 444*7c478bd9Sstevel@tonic-gate PUTCHAR(us->us_id, outp); 445*7c478bd9Sstevel@tonic-gate PUTSHORT(outlen, outp); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if (len > 0) 448*7c478bd9Sstevel@tonic-gate BCOPY(buf, outp, len); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * Received CBCP Acknowledgment message. 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate static void 457*7c478bd9Sstevel@tonic-gate cbcp_recvack(us, pckt, len) 458*7c478bd9Sstevel@tonic-gate cbcp_state *us; 459*7c478bd9Sstevel@tonic-gate u_char *pckt; 460*7c478bd9Sstevel@tonic-gate int len; 461*7c478bd9Sstevel@tonic-gate { 462*7c478bd9Sstevel@tonic-gate u_char type, addr_type; 463*7c478bd9Sstevel@tonic-gate int opt_len; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate if (len > 0) { 466*7c478bd9Sstevel@tonic-gate GETCHAR(type, pckt); 467*7c478bd9Sstevel@tonic-gate GETCHAR(opt_len, pckt); 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (type == CB_CONF_NO) { 470*7c478bd9Sstevel@tonic-gate if (debug) 471*7c478bd9Sstevel@tonic-gate dbglog("CBCP: proceeding without callback"); 472*7c478bd9Sstevel@tonic-gate return; 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate /* just ignore the delay time */ 476*7c478bd9Sstevel@tonic-gate pckt++; 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate if (opt_len > 4) { 479*7c478bd9Sstevel@tonic-gate GETCHAR(addr_type, pckt); 480*7c478bd9Sstevel@tonic-gate if (addr_type != 1) 481*7c478bd9Sstevel@tonic-gate warn("CBCP: unknown callback address type %d", addr_type); 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate if (debug && opt_len > 5) 484*7c478bd9Sstevel@tonic-gate dbglog("CBCP: peer will call %.*s", pckt, opt_len - 4); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate persist = 0; 488*7c478bd9Sstevel@tonic-gate lcp_close(us->us_unit, "Call me back, please"); 489*7c478bd9Sstevel@tonic-gate status = EXIT_CALLBACK; 490*7c478bd9Sstevel@tonic-gate } 491