17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * cbcp - Call Back Configuration Protocol.
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * Copyright (c) 2000 by Sun Microsystems, Inc.
57c478bd9Sstevel@tonic-gate * All rights reserved.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Pedro Roque Marques
87c478bd9Sstevel@tonic-gate * All rights reserved.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted
117c478bd9Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are
127c478bd9Sstevel@tonic-gate * duplicated in all such forms and that any documentation,
137c478bd9Sstevel@tonic-gate * advertising materials, and other materials related to such
147c478bd9Sstevel@tonic-gate * distribution and use acknowledge that the software was developed
157c478bd9Sstevel@tonic-gate * by Pedro Roque Marques. The name of the author may not be used to
167c478bd9Sstevel@tonic-gate * endorse or promote products derived from this software without
177c478bd9Sstevel@tonic-gate * specific prior written permission.
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
207c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
217c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
227c478bd9Sstevel@tonic-gate */
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate #include <stdio.h>
257c478bd9Sstevel@tonic-gate #include <string.h>
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/time.h>
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #include "pppd.h"
307c478bd9Sstevel@tonic-gate #include "cbcp.h"
317c478bd9Sstevel@tonic-gate #include "fsm.h"
327c478bd9Sstevel@tonic-gate #include "lcp.h"
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate * Options.
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate static int setcbcp __P((char **, option_t *));
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate static option_t cbcp_option_list[] = {
407c478bd9Sstevel@tonic-gate { "callback", o_special, (void *)setcbcp,
417c478bd9Sstevel@tonic-gate "Ask for callback" },
427c478bd9Sstevel@tonic-gate { NULL }
437c478bd9Sstevel@tonic-gate };
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate * Protocol entry points.
477c478bd9Sstevel@tonic-gate */
487c478bd9Sstevel@tonic-gate static void cbcp_init __P((int unit));
497c478bd9Sstevel@tonic-gate static void cbcp_lowerup __P((int unit));
507c478bd9Sstevel@tonic-gate static void cbcp_input __P((int unit, u_char *pkt, int len));
517c478bd9Sstevel@tonic-gate static void cbcp_protrej __P((int unit));
527c478bd9Sstevel@tonic-gate static int cbcp_printpkt __P((u_char *pkt, int len,
537c478bd9Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)),
547c478bd9Sstevel@tonic-gate void *arg));
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate struct protent cbcp_protent = {
577c478bd9Sstevel@tonic-gate PPP_CBCP, /* PPP protocol number */
587c478bd9Sstevel@tonic-gate cbcp_init, /* Initialization procedure */
597c478bd9Sstevel@tonic-gate cbcp_input, /* Process a received packet */
607c478bd9Sstevel@tonic-gate cbcp_protrej, /* Process a received protocol-reject */
617c478bd9Sstevel@tonic-gate cbcp_lowerup, /* Lower layer has come up */
627c478bd9Sstevel@tonic-gate NULL, /* Lower layer has gone down */
637c478bd9Sstevel@tonic-gate NULL, /* Open the protocol */
647c478bd9Sstevel@tonic-gate NULL, /* Close the protocol */
657c478bd9Sstevel@tonic-gate cbcp_printpkt, /* Print a packet in readable form */
667c478bd9Sstevel@tonic-gate NULL, /* Process a received data packet */
677c478bd9Sstevel@tonic-gate 0, /* 0 iff protocol is disabled */
687c478bd9Sstevel@tonic-gate "CBCP", /* Text name of protocol */
697c478bd9Sstevel@tonic-gate NULL, /* Text name of corresponding data protocol */
707c478bd9Sstevel@tonic-gate cbcp_option_list, /* List of command-line options */
717c478bd9Sstevel@tonic-gate NULL, /* Check requested options, assign defaults */
727c478bd9Sstevel@tonic-gate NULL, /* Configure interface for demand-dial */
737c478bd9Sstevel@tonic-gate NULL /* Say whether to bring up link for this pkt */
747c478bd9Sstevel@tonic-gate };
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /* Not static'd for plug-ins */
77*55fea89dSDan Cross cbcp_state cbcp[NUM_PPP];
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /* internal prototypes */
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len));
827c478bd9Sstevel@tonic-gate static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len));
837c478bd9Sstevel@tonic-gate static void cbcp_send __P((cbcp_state *us, int code, u_char *buf, int len));
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /* option processing */
867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
877c478bd9Sstevel@tonic-gate static int
setcbcp(argv,opt)887c478bd9Sstevel@tonic-gate setcbcp(argv, opt)
897c478bd9Sstevel@tonic-gate char **argv;
907c478bd9Sstevel@tonic-gate option_t *opt;
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate lcp_wantoptions[0].neg_cbcp = 1;
937c478bd9Sstevel@tonic-gate cbcp_protent.enabled_flag = 1;
947c478bd9Sstevel@tonic-gate cbcp[0].us_number = strdup(*argv);
957c478bd9Sstevel@tonic-gate if (cbcp[0].us_number == NULL)
967c478bd9Sstevel@tonic-gate novm("callback number");
977c478bd9Sstevel@tonic-gate cbcp[0].us_type |= (1 << CB_CONF_USER);
987c478bd9Sstevel@tonic-gate cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
997c478bd9Sstevel@tonic-gate return (1);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /* init state */
1037c478bd9Sstevel@tonic-gate static void
cbcp_init(unit)1047c478bd9Sstevel@tonic-gate cbcp_init(unit)
1057c478bd9Sstevel@tonic-gate int unit;
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate cbcp_state *us;
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate us = &cbcp[unit];
1107c478bd9Sstevel@tonic-gate BZERO(us, sizeof(cbcp_state));
1117c478bd9Sstevel@tonic-gate us->us_unit = unit;
1127c478bd9Sstevel@tonic-gate us->us_type |= (1 << CB_CONF_NO);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /* lower layer is up */
1167c478bd9Sstevel@tonic-gate static void
cbcp_lowerup(unit)1177c478bd9Sstevel@tonic-gate cbcp_lowerup(unit)
1187c478bd9Sstevel@tonic-gate int unit;
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate cbcp_state *us = &cbcp[unit];
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate if (debug) {
1237c478bd9Sstevel@tonic-gate dbglog("cbcp_lowerup: want: %d", us->us_type);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate if (us->us_type == CB_CONF_USER)
1267c478bd9Sstevel@tonic-gate dbglog("phone no: %s", us->us_number);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /* process an incoming packet */
1317c478bd9Sstevel@tonic-gate static void
cbcp_input(unit,inpacket,pktlen)1327c478bd9Sstevel@tonic-gate cbcp_input(unit, inpacket, pktlen)
1337c478bd9Sstevel@tonic-gate int unit;
1347c478bd9Sstevel@tonic-gate u_char *inpacket;
1357c478bd9Sstevel@tonic-gate int pktlen;
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate u_char *inp;
1387c478bd9Sstevel@tonic-gate u_char code, id;
1397c478bd9Sstevel@tonic-gate u_short len;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate cbcp_state *us = &cbcp[unit];
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate inp = inpacket;
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate if (pktlen < CBCP_MINLEN) {
1467c478bd9Sstevel@tonic-gate error("CBCP packet is too small (%d < %d)", pktlen, CBCP_MINLEN);
1477c478bd9Sstevel@tonic-gate return;
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate GETCHAR(code, inp);
1517c478bd9Sstevel@tonic-gate GETCHAR(id, inp);
1527c478bd9Sstevel@tonic-gate GETSHORT(len, inp);
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate if (len > pktlen) {
1557c478bd9Sstevel@tonic-gate error("CBCP packet: invalid length (%d > %d)", len, pktlen);
1567c478bd9Sstevel@tonic-gate return;
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate len -= CBCP_MINLEN;
160*55fea89dSDan Cross
1617c478bd9Sstevel@tonic-gate switch (code) {
1627c478bd9Sstevel@tonic-gate case CBCP_REQ:
1637c478bd9Sstevel@tonic-gate us->us_id = id;
1647c478bd9Sstevel@tonic-gate cbcp_recvreq(us, inp, len);
1657c478bd9Sstevel@tonic-gate break;
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate case CBCP_RESP:
1687c478bd9Sstevel@tonic-gate if (debug)
1697c478bd9Sstevel@tonic-gate dbglog("CBCP Response received; no request sent");
1707c478bd9Sstevel@tonic-gate break;
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate case CBCP_ACK:
1737c478bd9Sstevel@tonic-gate if (id != us->us_id) {
1747c478bd9Sstevel@tonic-gate if (debug)
1757c478bd9Sstevel@tonic-gate dbglog("CBCP Ack ID %d doesn't match expected %d", id,
1767c478bd9Sstevel@tonic-gate us->us_id);
1777c478bd9Sstevel@tonic-gate break;
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate cbcp_recvack(us, inp, len);
1817c478bd9Sstevel@tonic-gate break;
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate default:
1847c478bd9Sstevel@tonic-gate if (debug)
1857c478bd9Sstevel@tonic-gate dbglog("Unknown CBCP code number %d", code);
1867c478bd9Sstevel@tonic-gate break;
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate /* protocol was rejected by foe */
1917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1927c478bd9Sstevel@tonic-gate static void
cbcp_protrej(int unit)1937c478bd9Sstevel@tonic-gate cbcp_protrej(int unit)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate start_networks();
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate static char *cbcp_codenames[] = {
1997c478bd9Sstevel@tonic-gate "Request", "Response", "Ack"
2007c478bd9Sstevel@tonic-gate };
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate static char *cbcp_optionnames[] = {
2037c478bd9Sstevel@tonic-gate "NoCallback",
2047c478bd9Sstevel@tonic-gate "UserDefined",
2057c478bd9Sstevel@tonic-gate "AdminDefined",
2067c478bd9Sstevel@tonic-gate "List"
2077c478bd9Sstevel@tonic-gate };
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate * Pretty print a packet. Return value is number of bytes parsed out
2117c478bd9Sstevel@tonic-gate * of the packet and printed in some way. Caller (in util.c) will
2127c478bd9Sstevel@tonic-gate * print the remainder of the packet.
2137c478bd9Sstevel@tonic-gate */
2147c478bd9Sstevel@tonic-gate static int
cbcp_printpkt(p,plen,printer,arg)2157c478bd9Sstevel@tonic-gate cbcp_printpkt(p, plen, printer, arg)
2167c478bd9Sstevel@tonic-gate u_char *p;
2177c478bd9Sstevel@tonic-gate int plen;
2187c478bd9Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...));
2197c478bd9Sstevel@tonic-gate void *arg;
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate int code, id, len, olen, alen;
2227c478bd9Sstevel@tonic-gate u_char *pstart, cichar;
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate if (plen < HEADERLEN) {
2257c478bd9Sstevel@tonic-gate printer(arg, "too short (%d<%d)", plen, HEADERLEN);
2267c478bd9Sstevel@tonic-gate return (0);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate pstart = p;
2297c478bd9Sstevel@tonic-gate GETCHAR(code, p);
2307c478bd9Sstevel@tonic-gate GETCHAR(id, p);
2317c478bd9Sstevel@tonic-gate GETSHORT(len, p);
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if (code >= 1 && code <= Dim(cbcp_codenames))
2347c478bd9Sstevel@tonic-gate printer(arg, " %s", cbcp_codenames[code-1]);
2357c478bd9Sstevel@tonic-gate else
236*55fea89dSDan Cross printer(arg, " code=0x%x", code);
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate printer(arg, " id=0x%x", id);
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate if (len < HEADERLEN) {
2417c478bd9Sstevel@tonic-gate printer(arg, " header length %d<%d", len, HEADERLEN);
2427c478bd9Sstevel@tonic-gate return (HEADERLEN);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate if (len > plen) {
2457c478bd9Sstevel@tonic-gate printer(arg, " truncated (%d>%d)", len, plen);
2467c478bd9Sstevel@tonic-gate len = plen;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate len -= HEADERLEN;
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate switch (code) {
2517c478bd9Sstevel@tonic-gate case CBCP_REQ:
2527c478bd9Sstevel@tonic-gate case CBCP_RESP:
2537c478bd9Sstevel@tonic-gate case CBCP_ACK:
2547c478bd9Sstevel@tonic-gate while (len >= 2) {
2557c478bd9Sstevel@tonic-gate GETCHAR(cichar, p);
2567c478bd9Sstevel@tonic-gate GETCHAR(olen, p);
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate if (olen < 2)
2597c478bd9Sstevel@tonic-gate break;
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate printer(arg, " <");
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate if (olen > len) {
2647c478bd9Sstevel@tonic-gate printer(arg, "trunc[%d>%d] ", olen, len);
2657c478bd9Sstevel@tonic-gate olen = len;
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate len -= olen;
2687c478bd9Sstevel@tonic-gate olen -= 2;
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate if (cichar >= 1 && cichar <= Dim(cbcp_optionnames))
2717c478bd9Sstevel@tonic-gate printer(arg, " %s", cbcp_optionnames[cichar-1]);
2727c478bd9Sstevel@tonic-gate else
273*55fea89dSDan Cross printer(arg, " option=0x%x", cichar);
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate if (olen > 0) {
2767c478bd9Sstevel@tonic-gate GETCHAR(cichar, p);
2777c478bd9Sstevel@tonic-gate olen--;
2787c478bd9Sstevel@tonic-gate printer(arg, " delay=%d", cichar);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate while (olen > 0) {
2827c478bd9Sstevel@tonic-gate GETCHAR(cichar, p);
2837c478bd9Sstevel@tonic-gate olen--;
2847c478bd9Sstevel@tonic-gate if (cichar != 1)
2857c478bd9Sstevel@tonic-gate printer(arg, " (type %d?)", cichar);
2867c478bd9Sstevel@tonic-gate alen = strllen((const char *)p, olen);
2877c478bd9Sstevel@tonic-gate if (olen > 0 && alen > 0)
2887c478bd9Sstevel@tonic-gate printer(arg, " '%.*s'", alen, p);
2897c478bd9Sstevel@tonic-gate else
2907c478bd9Sstevel@tonic-gate printer(arg, " null");
2917c478bd9Sstevel@tonic-gate p += alen + 1;
2927c478bd9Sstevel@tonic-gate olen -= alen + 1;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate printer(arg, ">");
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate default:
2987c478bd9Sstevel@tonic-gate break;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate if (len > 0) {
3027c478bd9Sstevel@tonic-gate if (len > 8)
3037c478bd9Sstevel@tonic-gate printer(arg, "%8B ...", p);
3047c478bd9Sstevel@tonic-gate else
3057c478bd9Sstevel@tonic-gate printer(arg, "%.*B", len, p);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate p += len;
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate return p - pstart;
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate /*
3137c478bd9Sstevel@tonic-gate * received CBCP request.
3147c478bd9Sstevel@tonic-gate * No reason to print packet contents in detail here, since enabling
3157c478bd9Sstevel@tonic-gate * debug mode will cause the print routine above to be invoked.
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate static void
cbcp_recvreq(us,pckt,pcktlen)3187c478bd9Sstevel@tonic-gate cbcp_recvreq(us, pckt, pcktlen)
3197c478bd9Sstevel@tonic-gate cbcp_state *us;
3207c478bd9Sstevel@tonic-gate u_char *pckt;
3217c478bd9Sstevel@tonic-gate int pcktlen;
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate u_char type, opt_len;
3247c478bd9Sstevel@tonic-gate int len = pcktlen;
3257c478bd9Sstevel@tonic-gate u_char cb_type;
3267c478bd9Sstevel@tonic-gate u_char buf[256];
3277c478bd9Sstevel@tonic-gate u_char *bufp = buf;
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate us->us_allowed = 0;
3307c478bd9Sstevel@tonic-gate while (len > 0) {
3317c478bd9Sstevel@tonic-gate GETCHAR(type, pckt);
3327c478bd9Sstevel@tonic-gate GETCHAR(opt_len, pckt);
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate if (opt_len > 2) {
3357c478bd9Sstevel@tonic-gate pckt++; /* ignore the delay time */
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate len -= opt_len;
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate * Careful; don't use left-shift operator on numbers that are
3427c478bd9Sstevel@tonic-gate * too big.
3437c478bd9Sstevel@tonic-gate */
3447c478bd9Sstevel@tonic-gate if (type > CB_CONF_LIST) {
3457c478bd9Sstevel@tonic-gate if (debug)
3467c478bd9Sstevel@tonic-gate dbglog("CBCP: ignoring unknown type %d", type);
3477c478bd9Sstevel@tonic-gate continue;
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate us->us_allowed |= (1 << type);
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate switch (type) {
3537c478bd9Sstevel@tonic-gate case CB_CONF_NO:
3547c478bd9Sstevel@tonic-gate if (debug)
3557c478bd9Sstevel@tonic-gate dbglog("CBCP: operation without callback allowed");
3567c478bd9Sstevel@tonic-gate break;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate case CB_CONF_USER:
3597c478bd9Sstevel@tonic-gate if (debug)
3607c478bd9Sstevel@tonic-gate dbglog("callback to user-specified number allowed");
3617c478bd9Sstevel@tonic-gate break;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate case CB_CONF_ADMIN:
3647c478bd9Sstevel@tonic-gate if (debug)
3657c478bd9Sstevel@tonic-gate dbglog("CBCP: callback to admin-defined address allowed");
3667c478bd9Sstevel@tonic-gate break;
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate case CB_CONF_LIST:
3697c478bd9Sstevel@tonic-gate if (debug)
3707c478bd9Sstevel@tonic-gate dbglog("CBCP: callback to one out of list allowed");
3717c478bd9Sstevel@tonic-gate break;
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate /* Now generate the response */
3767c478bd9Sstevel@tonic-gate len = 0;
3777c478bd9Sstevel@tonic-gate cb_type = us->us_allowed & us->us_type;
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate if (cb_type & ( 1 << CB_CONF_USER ) ) {
3807c478bd9Sstevel@tonic-gate if (debug)
3817c478bd9Sstevel@tonic-gate dbglog("CBCP Response: selecting user-specified number");
3827c478bd9Sstevel@tonic-gate PUTCHAR(CB_CONF_USER, bufp);
3837c478bd9Sstevel@tonic-gate len = 3 + 1 + strlen(us->us_number) + 1;
3847c478bd9Sstevel@tonic-gate PUTCHAR(len , bufp);
3857c478bd9Sstevel@tonic-gate PUTCHAR(5, bufp); /* delay */
3867c478bd9Sstevel@tonic-gate PUTCHAR(1, bufp);
3877c478bd9Sstevel@tonic-gate BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
3887c478bd9Sstevel@tonic-gate cbcp_send(us, CBCP_RESP, buf, len);
3897c478bd9Sstevel@tonic-gate return;
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
3937c478bd9Sstevel@tonic-gate if (debug)
3947c478bd9Sstevel@tonic-gate dbglog("CBCP Response: selecting admin-specified number");
3957c478bd9Sstevel@tonic-gate PUTCHAR(CB_CONF_ADMIN, bufp);
3967c478bd9Sstevel@tonic-gate len = 3;
3977c478bd9Sstevel@tonic-gate PUTCHAR(len, bufp);
3987c478bd9Sstevel@tonic-gate PUTCHAR(5, bufp); /* delay */
3997c478bd9Sstevel@tonic-gate cbcp_send(us, CBCP_RESP, buf, len);
4007c478bd9Sstevel@tonic-gate return;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate if (cb_type & ( 1 << CB_CONF_NO ) ) {
4047c478bd9Sstevel@tonic-gate if (debug)
4057c478bd9Sstevel@tonic-gate dbglog("CBCP Response: selecting no-callback mode");
4067c478bd9Sstevel@tonic-gate PUTCHAR(CB_CONF_NO, bufp);
4077c478bd9Sstevel@tonic-gate len = 3;
4087c478bd9Sstevel@tonic-gate PUTCHAR(len , bufp);
4097c478bd9Sstevel@tonic-gate PUTCHAR(0, bufp);
4107c478bd9Sstevel@tonic-gate cbcp_send(us, CBCP_RESP, buf, len);
4117c478bd9Sstevel@tonic-gate start_networks();
4127c478bd9Sstevel@tonic-gate return;
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate if (debug)
4167c478bd9Sstevel@tonic-gate dbglog("CBCP: no callback types in common");
4177c478bd9Sstevel@tonic-gate lcp_close(us->us_unit, "No CBCP callback options available");
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate static void
cbcp_send(us,code,buf,len)4217c478bd9Sstevel@tonic-gate cbcp_send(us, code, buf, len)
4227c478bd9Sstevel@tonic-gate cbcp_state *us;
4237c478bd9Sstevel@tonic-gate int code;
4247c478bd9Sstevel@tonic-gate u_char *buf;
4257c478bd9Sstevel@tonic-gate int len;
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate u_char *outp;
4287c478bd9Sstevel@tonic-gate int outlen;
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate outp = outpacket_buf;
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate outlen = 4 + len;
433*55fea89dSDan Cross
4347c478bd9Sstevel@tonic-gate MAKEHEADER(outp, PPP_CBCP);
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate PUTCHAR(code, outp);
4377c478bd9Sstevel@tonic-gate PUTCHAR(us->us_id, outp);
4387c478bd9Sstevel@tonic-gate PUTSHORT(outlen, outp);
439*55fea89dSDan Cross
4407c478bd9Sstevel@tonic-gate if (len > 0)
4417c478bd9Sstevel@tonic-gate BCOPY(buf, outp, len);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate * Received CBCP Acknowledgment message.
4487c478bd9Sstevel@tonic-gate */
4497c478bd9Sstevel@tonic-gate static void
cbcp_recvack(us,pckt,len)4507c478bd9Sstevel@tonic-gate cbcp_recvack(us, pckt, len)
4517c478bd9Sstevel@tonic-gate cbcp_state *us;
4527c478bd9Sstevel@tonic-gate u_char *pckt;
4537c478bd9Sstevel@tonic-gate int len;
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate u_char type, addr_type;
4567c478bd9Sstevel@tonic-gate int opt_len;
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate if (len > 0) {
4597c478bd9Sstevel@tonic-gate GETCHAR(type, pckt);
4607c478bd9Sstevel@tonic-gate GETCHAR(opt_len, pckt);
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate if (type == CB_CONF_NO) {
4637c478bd9Sstevel@tonic-gate if (debug)
4647c478bd9Sstevel@tonic-gate dbglog("CBCP: proceeding without callback");
4657c478bd9Sstevel@tonic-gate return;
4667c478bd9Sstevel@tonic-gate }
467*55fea89dSDan Cross
4687c478bd9Sstevel@tonic-gate /* just ignore the delay time */
4697c478bd9Sstevel@tonic-gate pckt++;
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate if (opt_len > 4) {
4727c478bd9Sstevel@tonic-gate GETCHAR(addr_type, pckt);
4737c478bd9Sstevel@tonic-gate if (addr_type != 1)
4747c478bd9Sstevel@tonic-gate warn("CBCP: unknown callback address type %d", addr_type);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate if (debug && opt_len > 5)
4777c478bd9Sstevel@tonic-gate dbglog("CBCP: peer will call %.*s", pckt, opt_len - 4);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate persist = 0;
4817c478bd9Sstevel@tonic-gate lcp_close(us->us_unit, "Call me back, please");
4827c478bd9Sstevel@tonic-gate status = EXIT_CALLBACK;
4837c478bd9Sstevel@tonic-gate }
484