2 * cbcp - Call Back Configuration Protocol.
4 * Copyright (c) 2000 by Sun Microsystems, Inc.
7 * Copyright (c) 1995 Pedro Roque Marques
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by Pedro Roque Marques. The name of the author may not be used to
16 * endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #pragma ident "%Z%%M% %I% %E% SMI"
25 #define RCSID "$Id: cbcp.c,v 1.10 1999/08/13 06:46:10 paulus Exp $"
29 #include <sys/types.h>
37 #if !defined(lint) && !defined(_lint)
38 static const char rcsid
[] = RCSID
;
44 static int setcbcp
__P((char **, option_t
*));
46 static option_t cbcp_option_list
[] = {
47 { "callback", o_special
, (void *)setcbcp
,
53 * Protocol entry points.
55 static void cbcp_init
__P((int unit
));
56 static void cbcp_lowerup
__P((int unit
));
57 static void cbcp_input
__P((int unit
, u_char
*pkt
, int len
));
58 static void cbcp_protrej
__P((int unit
));
59 static int cbcp_printpkt
__P((u_char
*pkt
, int len
,
60 void (*printer
) __P((void *, const char *, ...)),
63 struct protent cbcp_protent
= {
64 PPP_CBCP
, /* PPP protocol number */
65 cbcp_init
, /* Initialization procedure */
66 cbcp_input
, /* Process a received packet */
67 cbcp_protrej
, /* Process a received protocol-reject */
68 cbcp_lowerup
, /* Lower layer has come up */
69 NULL
, /* Lower layer has gone down */
70 NULL
, /* Open the protocol */
71 NULL
, /* Close the protocol */
72 cbcp_printpkt
, /* Print a packet in readable form */
73 NULL
, /* Process a received data packet */
74 0, /* 0 iff protocol is disabled */
75 "CBCP", /* Text name of protocol */
76 NULL
, /* Text name of corresponding data protocol */
77 cbcp_option_list
, /* List of command-line options */
78 NULL
, /* Check requested options, assign defaults */
79 NULL
, /* Configure interface for demand-dial */
80 NULL
/* Say whether to bring up link for this pkt */
83 /* Not static'd for plug-ins */
84 cbcp_state cbcp
[NUM_PPP
];
86 /* internal prototypes */
88 static void cbcp_recvreq
__P((cbcp_state
*us
, u_char
*pckt
, int len
));
89 static void cbcp_recvack
__P((cbcp_state
*us
, u_char
*pckt
, int len
));
90 static void cbcp_send
__P((cbcp_state
*us
, int code
, u_char
*buf
, int len
));
92 /* option processing */
99 lcp_wantoptions
[0].neg_cbcp
= 1;
100 cbcp_protent
.enabled_flag
= 1;
101 cbcp
[0].us_number
= strdup(*argv
);
102 if (cbcp
[0].us_number
== NULL
)
103 novm("callback number");
104 cbcp
[0].us_type
|= (1 << CB_CONF_USER
);
105 cbcp
[0].us_type
|= (1 << CB_CONF_ADMIN
);
117 BZERO(us
, sizeof(cbcp_state
));
119 us
->us_type
|= (1 << CB_CONF_NO
);
122 /* lower layer is up */
127 cbcp_state
*us
= &cbcp
[unit
];
130 dbglog("cbcp_lowerup: want: %d", us
->us_type
);
132 if (us
->us_type
== CB_CONF_USER
)
133 dbglog("phone no: %s", us
->us_number
);
137 /* process an incoming packet */
139 cbcp_input(unit
, inpacket
, pktlen
)
148 cbcp_state
*us
= &cbcp
[unit
];
152 if (pktlen
< CBCP_MINLEN
) {
153 error("CBCP packet is too small (%d < %d)", pktlen
, CBCP_MINLEN
);
162 error("CBCP packet: invalid length (%d > %d)", len
, pktlen
);
171 cbcp_recvreq(us
, inp
, len
);
176 dbglog("CBCP Response received; no request sent");
180 if (id
!= us
->us_id
) {
182 dbglog("CBCP Ack ID %d doesn't match expected %d", id
,
187 cbcp_recvack(us
, inp
, len
);
192 dbglog("Unknown CBCP code number %d", code
);
197 /* protocol was rejected by foe */
200 cbcp_protrej(int unit
)
205 static char *cbcp_codenames
[] = {
206 "Request", "Response", "Ack"
209 static char *cbcp_optionnames
[] = {
217 * Pretty print a packet. Return value is number of bytes parsed out
218 * of the packet and printed in some way. Caller (in util.c) will
219 * print the remainder of the packet.
222 cbcp_printpkt(p
, plen
, printer
, arg
)
225 void (*printer
) __P((void *, const char *, ...));
228 int code
, id
, len
, olen
, alen
;
229 u_char
*pstart
, cichar
;
231 if (plen
< HEADERLEN
) {
232 printer(arg
, "too short (%d<%d)", plen
, HEADERLEN
);
240 if (code
>= 1 && code
<= Dim(cbcp_codenames
))
241 printer(arg
, " %s", cbcp_codenames
[code
-1]);
243 printer(arg
, " code=0x%x", code
);
245 printer(arg
, " id=0x%x", id
);
247 if (len
< HEADERLEN
) {
248 printer(arg
, " header length %d<%d", len
, HEADERLEN
);
252 printer(arg
, " truncated (%d>%d)", len
, plen
);
271 printer(arg
, "trunc[%d>%d] ", olen
, len
);
277 if (cichar
>= 1 && cichar
<= Dim(cbcp_optionnames
))
278 printer(arg
, " %s", cbcp_optionnames
[cichar
-1]);
280 printer(arg
, " option=0x%x", cichar
);
285 printer(arg
, " delay=%d", cichar
);
292 printer(arg
, " (type %d?)", cichar
);
293 alen
= strllen((const char *)p
, olen
);
294 if (olen
> 0 && alen
> 0)
295 printer(arg
, " '%.*s'", alen
, p
);
297 printer(arg
, " null");
310 printer(arg
, "%8B ...", p
);
312 printer(arg
, "%.*B", len
, p
);
320 * received CBCP request.
321 * No reason to print packet contents in detail here, since enabling
322 * debug mode will cause the print routine above to be invoked.
325 cbcp_recvreq(us
, pckt
, pcktlen
)
330 u_char type
, opt_len
;
339 GETCHAR(opt_len
, pckt
);
342 pckt
++; /* ignore the delay time */
348 * Careful; don't use left-shift operator on numbers that are
351 if (type
> CB_CONF_LIST
) {
353 dbglog("CBCP: ignoring unknown type %d", type
);
357 us
->us_allowed
|= (1 << type
);
362 dbglog("CBCP: operation without callback allowed");
367 dbglog("callback to user-specified number allowed");
372 dbglog("CBCP: callback to admin-defined address allowed");
377 dbglog("CBCP: callback to one out of list allowed");
382 /* Now generate the response */
384 cb_type
= us
->us_allowed
& us
->us_type
;
386 if (cb_type
& ( 1 << CB_CONF_USER
) ) {
388 dbglog("CBCP Response: selecting user-specified number");
389 PUTCHAR(CB_CONF_USER
, bufp
);
390 len
= 3 + 1 + strlen(us
->us_number
) + 1;
392 PUTCHAR(5, bufp
); /* delay */
394 BCOPY(us
->us_number
, bufp
, strlen(us
->us_number
) + 1);
395 cbcp_send(us
, CBCP_RESP
, buf
, len
);
399 if (cb_type
& ( 1 << CB_CONF_ADMIN
) ) {
401 dbglog("CBCP Response: selecting admin-specified number");
402 PUTCHAR(CB_CONF_ADMIN
, bufp
);
405 PUTCHAR(5, bufp
); /* delay */
406 cbcp_send(us
, CBCP_RESP
, buf
, len
);
410 if (cb_type
& ( 1 << CB_CONF_NO
) ) {
412 dbglog("CBCP Response: selecting no-callback mode");
413 PUTCHAR(CB_CONF_NO
, bufp
);
417 cbcp_send(us
, CBCP_RESP
, buf
, len
);
423 dbglog("CBCP: no callback types in common");
424 lcp_close(us
->us_unit
, "No CBCP callback options available");
428 cbcp_send(us
, code
, buf
, len
)
437 outp
= outpacket_buf
;
441 MAKEHEADER(outp
, PPP_CBCP
);
444 PUTCHAR(us
->us_id
, outp
);
445 PUTSHORT(outlen
, outp
);
448 BCOPY(buf
, outp
, len
);
450 output(us
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
454 * Received CBCP Acknowledgment message.
457 cbcp_recvack(us
, pckt
, len
)
462 u_char type
, addr_type
;
467 GETCHAR(opt_len
, pckt
);
469 if (type
== CB_CONF_NO
) {
471 dbglog("CBCP: proceeding without callback");
475 /* just ignore the delay time */
479 GETCHAR(addr_type
, pckt
);
481 warn("CBCP: unknown callback address type %d", addr_type
);
483 if (debug
&& opt_len
> 5)
484 dbglog("CBCP: peer will call %.*s", pckt
, opt_len
- 4);
488 lcp_close(us
->us_unit
, "Call me back, please");
489 status
= EXIT_CALLBACK
;