xref: /titanic_41/usr/src/cmd/cmd-inet/usr.bin/pppd/cbcp.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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
setcbcp(argv,opt)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
cbcp_init(unit)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
cbcp_lowerup(unit)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
cbcp_input(unit,inpacket,pktlen)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
cbcp_protrej(int unit)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
cbcp_printpkt(p,plen,printer,arg)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
cbcp_recvreq(us,pckt,pcktlen)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
cbcp_send(us,code,buf,len)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
cbcp_recvack(us,pckt,len)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