2 * cbcp - Call Back Configuration Protocol.
4 * Copyright (c) 1995 Pedro Roque Marques. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * 3. The names of the authors of this software must not be used to
19 * endorse or promote products derived from this software without
20 * prior written permission.
22 * 4. Redistributions of any form whatsoever must retain the following
24 * "This product includes software developed by Pedro Roque Marques
25 * <pedro_m@yahoo.com>"
27 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
28 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
30 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
31 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
32 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
33 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36 #define RCSID "$Id: cbcp.c,v 1.17 2006/05/22 00:04:07 paulus Exp $"
40 #include <sys/types.h>
48 static const char rcsid
[] = RCSID
;
53 static int setcbcp
__P((char **));
55 static option_t cbcp_option_list
[] = {
56 { "callback", o_special
, (void *)setcbcp
,
57 "Ask for callback", OPT_PRIO
| OPT_A2STRVAL
, &cbcp
[0].us_number
},
62 * Protocol entry points.
64 static void cbcp_init
__P((int unit
));
65 static void cbcp_open
__P((int unit
));
66 static void cbcp_lowerup
__P((int unit
));
67 static void cbcp_input
__P((int unit
, u_char
*pkt
, int len
));
68 static void cbcp_protrej
__P((int unit
));
69 static int cbcp_printpkt
__P((u_char
*pkt
, int len
,
70 void (*printer
) __P((void *, char *, ...)),
73 struct protent cbcp_protent
= {
93 cbcp_state cbcp
[NUM_PPP
];
95 /* internal prototypes */
97 static void cbcp_recvreq
__P((cbcp_state
*us
, u_char
*pckt
, int len
));
98 static void cbcp_resp
__P((cbcp_state
*us
));
99 static void cbcp_up
__P((cbcp_state
*us
));
100 static void cbcp_recvack
__P((cbcp_state
*us
, u_char
*pckt
, int len
));
101 static void cbcp_send
__P((cbcp_state
*us
, int code
, u_char
*buf
, int len
));
103 /* option processing */
108 lcp_wantoptions
[0].neg_cbcp
= 1;
109 cbcp_protent
.enabled_flag
= 1;
110 cbcp
[0].us_number
= strdup(*argv
);
111 if (cbcp
[0].us_number
== 0)
112 novm("callback number");
113 cbcp
[0].us_type
|= (1 << CB_CONF_USER
);
114 cbcp
[0].us_type
|= (1 << CB_CONF_ADMIN
);
126 memset(us
, 0, sizeof(cbcp_state
));
128 us
->us_type
|= (1 << CB_CONF_NO
);
131 /* lower layer is up */
136 cbcp_state
*us
= &cbcp
[iface
];
138 dbglog("cbcp_lowerup");
139 dbglog("want: %d", us
->us_type
);
141 if (us
->us_type
== CB_CONF_USER
)
142 dbglog("phone no: %s", us
->us_number
);
152 /* process an incomming packet */
154 cbcp_input(unit
, inpacket
, pktlen
)
163 cbcp_state
*us
= &cbcp
[unit
];
167 if (pktlen
< CBCP_MINLEN
) {
169 dbglog("CBCP packet is too small");
177 if (len
> pktlen
|| len
< CBCP_MINLEN
) {
179 dbglog("CBCP packet: invalid length %d", len
);
188 cbcp_recvreq(us
, inp
, len
);
193 dbglog("CBCP_RESP received");
197 if (debug
&& id
!= us
->us_id
)
198 dbglog("id doesn't match: expected %d recv %d",
201 cbcp_recvack(us
, inp
, len
);
209 /* protocol was rejected by foe */
210 void cbcp_protrej(int iface
)
214 char *cbcp_codenames
[] = {
215 "Request", "Response", "Ack"
218 char *cbcp_optionnames
[] = {
225 /* pretty print a packet */
227 cbcp_printpkt(p
, plen
, printer
, arg
)
230 void (*printer
) __P((void *, char *, ...));
233 int code
, opt
, id
, len
, olen
, delay
;
236 if (plen
< HEADERLEN
)
242 if (len
< HEADERLEN
|| len
> plen
)
245 if (code
>= 1 && code
<= sizeof(cbcp_codenames
) / sizeof(char *))
246 printer(arg
, " %s", cbcp_codenames
[code
-1]);
248 printer(arg
, " code=0x%x", code
);
250 printer(arg
, " id=0x%x", id
);
261 if (olen
< 2 || olen
> len
) {
268 if (opt
>= 1 && opt
<= sizeof(cbcp_optionnames
) / sizeof(char *))
269 printer(arg
, " %s", cbcp_optionnames
[opt
-1]);
271 printer(arg
, " option=0x%x", opt
);
275 printer(arg
, " delay = %d", delay
);
283 memcpy(str
, p
, olen
- 4);
285 printer(arg
, " number = %s", str
);
295 for (; len
> 0; --len
) {
297 printer(arg
, " %.2x", code
);
303 /* received CBCP request */
305 cbcp_recvreq(us
, pckt
, pcktlen
)
310 u_char type
, opt_len
, delay
, addr_type
;
317 dbglog("length: %d", len
);
320 GETCHAR(opt_len
, pckt
);
321 if (opt_len
< 2 || opt_len
> len
)
325 GETCHAR(delay
, pckt
);
327 us
->us_allowed
|= (1 << type
);
331 dbglog("no callback allowed");
335 dbglog("user callback allowed");
337 GETCHAR(addr_type
, pckt
);
338 memcpy(address
, pckt
, opt_len
- 4);
339 address
[opt_len
- 4] = 0;
341 dbglog("address: %s", address
);
346 dbglog("user admin defined allowed");
356 dbglog("cbcp_recvreq: malformed packet (%d bytes left)", len
);
373 cb_type
= us
->us_allowed
& us
->us_type
;
374 dbglog("cbcp_resp cb_type=%d", cb_type
);
378 lcp_down(us
->us_unit
);
381 if (cb_type
& ( 1 << CB_CONF_USER
) ) {
382 dbglog("cbcp_resp CONF_USER");
383 slen
= strlen(us
->us_number
);
385 warn("callback number truncated to 250 characters");
388 PUTCHAR(CB_CONF_USER
, bufp
);
389 len
= 3 + 1 + slen
+ 1;
391 PUTCHAR(5, bufp
); /* delay */
393 BCOPY(us
->us_number
, bufp
, slen
+ 1);
394 cbcp_send(us
, CBCP_RESP
, buf
, len
);
398 if (cb_type
& ( 1 << CB_CONF_ADMIN
) ) {
399 dbglog("cbcp_resp CONF_ADMIN");
400 PUTCHAR(CB_CONF_ADMIN
, bufp
);
403 PUTCHAR(5, bufp
); /* delay */
404 cbcp_send(us
, CBCP_RESP
, buf
, len
);
408 if (cb_type
& ( 1 << CB_CONF_NO
) ) {
409 dbglog("cbcp_resp CONF_NO");
410 PUTCHAR(CB_CONF_NO
, bufp
);
413 cbcp_send(us
, CBCP_RESP
, buf
, len
);
414 start_networks(us
->us_unit
);
420 cbcp_send(us
, code
, buf
, len
)
429 outp
= outpacket_buf
;
433 MAKEHEADER(outp
, PPP_CBCP
);
436 PUTCHAR(us
->us_id
, outp
);
437 PUTSHORT(outlen
, outp
);
440 BCOPY(buf
, outp
, len
);
442 output(us
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
446 cbcp_recvack(us
, pckt
, len
)
451 u_char type
, delay
, addr_type
;
457 GETCHAR(opt_len
, pckt
);
458 if (opt_len
>= 2 && opt_len
<= len
) {
461 GETCHAR(delay
, pckt
);
464 GETCHAR(addr_type
, pckt
);
465 memcpy(address
, pckt
, opt_len
- 4);
466 address
[opt_len
- 4] = 0;
468 dbglog("peer will call: %s", address
);
470 if (type
== CB_CONF_NO
)
476 dbglog("cbcp_recvack: malformed packet");
480 /* ok peer will do callback */
486 status
= EXIT_CALLBACK
;
487 lcp_close(0, "Call me back, please");