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.
26 #include <sys/types.h>
37 static int setcbcp
__P((char **, option_t
*));
39 static option_t cbcp_option_list
[] = {
40 { "callback", o_special
, (void *)setcbcp
,
46 * Protocol entry points.
48 static void cbcp_init
__P((int unit
));
49 static void cbcp_lowerup
__P((int unit
));
50 static void cbcp_input
__P((int unit
, u_char
*pkt
, int len
));
51 static void cbcp_protrej
__P((int unit
));
52 static int cbcp_printpkt
__P((u_char
*pkt
, int len
,
53 void (*printer
) __P((void *, const char *, ...)),
56 struct protent cbcp_protent
= {
57 PPP_CBCP
, /* PPP protocol number */
58 cbcp_init
, /* Initialization procedure */
59 cbcp_input
, /* Process a received packet */
60 cbcp_protrej
, /* Process a received protocol-reject */
61 cbcp_lowerup
, /* Lower layer has come up */
62 NULL
, /* Lower layer has gone down */
63 NULL
, /* Open the protocol */
64 NULL
, /* Close the protocol */
65 cbcp_printpkt
, /* Print a packet in readable form */
66 NULL
, /* Process a received data packet */
67 0, /* 0 iff protocol is disabled */
68 "CBCP", /* Text name of protocol */
69 NULL
, /* Text name of corresponding data protocol */
70 cbcp_option_list
, /* List of command-line options */
71 NULL
, /* Check requested options, assign defaults */
72 NULL
, /* Configure interface for demand-dial */
73 NULL
/* Say whether to bring up link for this pkt */
76 /* Not static'd for plug-ins */
77 cbcp_state cbcp
[NUM_PPP
];
79 /* internal prototypes */
81 static void cbcp_recvreq
__P((cbcp_state
*us
, u_char
*pckt
, int len
));
82 static void cbcp_recvack
__P((cbcp_state
*us
, u_char
*pckt
, int len
));
83 static void cbcp_send
__P((cbcp_state
*us
, int code
, u_char
*buf
, int len
));
85 /* option processing */
92 lcp_wantoptions
[0].neg_cbcp
= 1;
93 cbcp_protent
.enabled_flag
= 1;
94 cbcp
[0].us_number
= strdup(*argv
);
95 if (cbcp
[0].us_number
== NULL
)
96 novm("callback number");
97 cbcp
[0].us_type
|= (1 << CB_CONF_USER
);
98 cbcp
[0].us_type
|= (1 << CB_CONF_ADMIN
);
110 BZERO(us
, sizeof(cbcp_state
));
112 us
->us_type
|= (1 << CB_CONF_NO
);
115 /* lower layer is up */
120 cbcp_state
*us
= &cbcp
[unit
];
123 dbglog("cbcp_lowerup: want: %d", us
->us_type
);
125 if (us
->us_type
== CB_CONF_USER
)
126 dbglog("phone no: %s", us
->us_number
);
130 /* process an incoming packet */
132 cbcp_input(unit
, inpacket
, pktlen
)
141 cbcp_state
*us
= &cbcp
[unit
];
145 if (pktlen
< CBCP_MINLEN
) {
146 error("CBCP packet is too small (%d < %d)", pktlen
, CBCP_MINLEN
);
155 error("CBCP packet: invalid length (%d > %d)", len
, pktlen
);
164 cbcp_recvreq(us
, inp
, len
);
169 dbglog("CBCP Response received; no request sent");
173 if (id
!= us
->us_id
) {
175 dbglog("CBCP Ack ID %d doesn't match expected %d", id
,
180 cbcp_recvack(us
, inp
, len
);
185 dbglog("Unknown CBCP code number %d", code
);
190 /* protocol was rejected by foe */
193 cbcp_protrej(int unit
)
198 static char *cbcp_codenames
[] = {
199 "Request", "Response", "Ack"
202 static char *cbcp_optionnames
[] = {
210 * Pretty print a packet. Return value is number of bytes parsed out
211 * of the packet and printed in some way. Caller (in util.c) will
212 * print the remainder of the packet.
215 cbcp_printpkt(p
, plen
, printer
, arg
)
218 void (*printer
) __P((void *, const char *, ...));
221 int code
, id
, len
, olen
, alen
;
222 u_char
*pstart
, cichar
;
224 if (plen
< HEADERLEN
) {
225 printer(arg
, "too short (%d<%d)", plen
, HEADERLEN
);
233 if (code
>= 1 && code
<= Dim(cbcp_codenames
))
234 printer(arg
, " %s", cbcp_codenames
[code
-1]);
236 printer(arg
, " code=0x%x", code
);
238 printer(arg
, " id=0x%x", id
);
240 if (len
< HEADERLEN
) {
241 printer(arg
, " header length %d<%d", len
, HEADERLEN
);
245 printer(arg
, " truncated (%d>%d)", len
, plen
);
264 printer(arg
, "trunc[%d>%d] ", olen
, len
);
270 if (cichar
>= 1 && cichar
<= Dim(cbcp_optionnames
))
271 printer(arg
, " %s", cbcp_optionnames
[cichar
-1]);
273 printer(arg
, " option=0x%x", cichar
);
278 printer(arg
, " delay=%d", cichar
);
285 printer(arg
, " (type %d?)", cichar
);
286 alen
= strllen((const char *)p
, olen
);
287 if (olen
> 0 && alen
> 0)
288 printer(arg
, " '%.*s'", alen
, p
);
290 printer(arg
, " null");
303 printer(arg
, "%8B ...", p
);
305 printer(arg
, "%.*B", len
, p
);
313 * received CBCP request.
314 * No reason to print packet contents in detail here, since enabling
315 * debug mode will cause the print routine above to be invoked.
318 cbcp_recvreq(us
, pckt
, pcktlen
)
323 u_char type
, opt_len
;
332 GETCHAR(opt_len
, pckt
);
335 pckt
++; /* ignore the delay time */
341 * Careful; don't use left-shift operator on numbers that are
344 if (type
> CB_CONF_LIST
) {
346 dbglog("CBCP: ignoring unknown type %d", type
);
350 us
->us_allowed
|= (1 << type
);
355 dbglog("CBCP: operation without callback allowed");
360 dbglog("callback to user-specified number allowed");
365 dbglog("CBCP: callback to admin-defined address allowed");
370 dbglog("CBCP: callback to one out of list allowed");
375 /* Now generate the response */
377 cb_type
= us
->us_allowed
& us
->us_type
;
379 if (cb_type
& ( 1 << CB_CONF_USER
) ) {
381 dbglog("CBCP Response: selecting user-specified number");
382 PUTCHAR(CB_CONF_USER
, bufp
);
383 len
= 3 + 1 + strlen(us
->us_number
) + 1;
385 PUTCHAR(5, bufp
); /* delay */
387 BCOPY(us
->us_number
, bufp
, strlen(us
->us_number
) + 1);
388 cbcp_send(us
, CBCP_RESP
, buf
, len
);
392 if (cb_type
& ( 1 << CB_CONF_ADMIN
) ) {
394 dbglog("CBCP Response: selecting admin-specified number");
395 PUTCHAR(CB_CONF_ADMIN
, bufp
);
398 PUTCHAR(5, bufp
); /* delay */
399 cbcp_send(us
, CBCP_RESP
, buf
, len
);
403 if (cb_type
& ( 1 << CB_CONF_NO
) ) {
405 dbglog("CBCP Response: selecting no-callback mode");
406 PUTCHAR(CB_CONF_NO
, bufp
);
410 cbcp_send(us
, CBCP_RESP
, buf
, len
);
416 dbglog("CBCP: no callback types in common");
417 lcp_close(us
->us_unit
, "No CBCP callback options available");
421 cbcp_send(us
, code
, buf
, len
)
430 outp
= outpacket_buf
;
434 MAKEHEADER(outp
, PPP_CBCP
);
437 PUTCHAR(us
->us_id
, outp
);
438 PUTSHORT(outlen
, outp
);
441 BCOPY(buf
, outp
, len
);
443 output(us
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
447 * Received CBCP Acknowledgment message.
450 cbcp_recvack(us
, pckt
, len
)
455 u_char type
, addr_type
;
460 GETCHAR(opt_len
, pckt
);
462 if (type
== CB_CONF_NO
) {
464 dbglog("CBCP: proceeding without callback");
468 /* just ignore the delay time */
472 GETCHAR(addr_type
, pckt
);
474 warn("CBCP: unknown callback address type %d", addr_type
);
476 if (debug
&& opt_len
> 5)
477 dbglog("CBCP: peer will call %.*s", pckt
, opt_len
- 4);
481 lcp_close(us
->us_unit
, "Call me back, please");
482 status
= EXIT_CALLBACK
;