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