diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 1996-12-23 13:22:50 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 1996-12-23 13:22:50 +0000 |
commit | 244ae4f36d8485d801b276c564b0912f8970db1a (patch) | |
tree | c2338ca08d1a28b6a12f5a03b849eebdb17a864c /usr.sbin/pppd/cbcp.c | |
parent | b091d7e1ea9e2cf69fd0694da9b01b1c022b4611 (diff) |
pppd 2.3b3 import. some minor buf oflow fixes and so.
try it out ppl, but i've got it running talking to cisco w/ all the AFs
enabled in kernel.
Diffstat (limited to 'usr.sbin/pppd/cbcp.c')
-rw-r--r-- | usr.sbin/pppd/cbcp.c | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/usr.sbin/pppd/cbcp.c b/usr.sbin/pppd/cbcp.c new file mode 100644 index 00000000000..2ee07283e50 --- /dev/null +++ b/usr.sbin/pppd/cbcp.c @@ -0,0 +1,434 @@ +/* $OpenBSD: cbcp.c,v 1.1 1996/12/23 13:22:37 mickey Exp $ */ + +/* + * cbcp - Call Back Configuration Protocol. + * + * Copyright (c) 1995 Pedro Roque Marques + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Pedro Roque Marques. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: cbcp.c,v 1.1 1996/12/23 13:22:37 mickey Exp $"; +#endif + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <syslog.h> + +#include "pppd.h" +#include "cbcp.h" +#include "fsm.h" +#include "lcp.h" +#include "ipcp.h" + +/* + * Protocol entry points. + */ +static void cbcp_init __P((int unit)); +static void cbcp_open __P((int unit)); +static void cbcp_lowerup __P((int unit)); +static void cbcp_input __P((int unit, u_char *pkt, int len)); +static void cbcp_protrej __P((int unit)); +static int cbcp_printpkt __P((u_char *pkt, int len, + void (*printer) __P((void *, char *, ...)), + void *arg)); + +struct protent cbcp_protent = { + PPP_CBCP, + cbcp_init, + cbcp_input, + cbcp_protrej, + cbcp_lowerup, + NULL, + cbcp_open, + NULL, + cbcp_printpkt, + NULL, + 0, + "CBCP", + NULL, + NULL, + NULL +}; + +cbcp_state cbcp[NUM_PPP]; + +/* internal prototypes */ + +static void cbcp_recvreq(cbcp_state *us, char *pckt, int len); +static void cbcp_resp(cbcp_state *us); +static void cbcp_up(cbcp_state *us); +static void cbcp_recvack(cbcp_state *us, char *pckt, int len); +static void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len); + +/* init state */ +static void +cbcp_init(iface) + int iface; +{ + cbcp_state *us; + + us = &cbcp[iface]; + memset(us, 0, sizeof(cbcp_state)); + us->us_unit = iface; + us->us_type |= (1 << CB_CONF_NO); +} + +/* lower layer is up */ +static void +cbcp_lowerup(iface) + int iface; +{ + cbcp_state *us = &cbcp[iface]; + + syslog(LOG_DEBUG, "cbcp_lowerup"); + syslog(LOG_DEBUG, "want: %d", us->us_type); + + if (us->us_type == CB_CONF_USER) + syslog(LOG_DEBUG, "phone no: %s", us->us_number); +} + +static void +cbcp_open(unit) + int unit; +{ + syslog(LOG_DEBUG, "cbcp_open"); +} + +/* process an incomming packet */ +static void +cbcp_input(unit, inpacket, pktlen) + int unit; + u_char *inpacket; + int pktlen; +{ + u_char *inp; + u_char code, id; + u_short len; + + cbcp_state *us = &cbcp[unit]; + + inp = inpacket; + + if (pktlen < CBCP_MINLEN) { + syslog(LOG_ERR, "CBCP packet is too small"); + return; + } + + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + +#if 0 + if (len > pktlen) { + syslog(LOG_ERR, "CBCP packet: invalid length"); + return; + } +#endif + + len -= CBCP_MINLEN; + + switch(code) { + case CBCP_REQ: + us->us_id = id; + cbcp_recvreq(us, inp, len); + break; + + case CBCP_RESP: + syslog(LOG_DEBUG, "CBCP_RESP received"); + break; + + case CBCP_ACK: + if (id != us->us_id) + syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d", + us->us_id, id); + + cbcp_recvack(us, inp, len); + break; + + default: + break; + } +} + +/* protocol was rejected by foe */ +void cbcp_protrej(int iface) +{ +} + +char *cbcp_codenames[] = { + "Request", "Response", "Ack" +}; + +char *cbcp_optionnames[] = { + "NoCallback", + "UserDefined", + "AdminDefined", + "List" +}; + +/* pretty print a packet */ +static int +cbcp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int code, opt, id, len, olen, delay; + u_char *pstart, *optend; + u_short cishort; + u_long cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *)) + printer(arg, " %s", cbcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + + switch (code) { + case CBCP_REQ: + case CBCP_RESP: + case CBCP_ACK: + while(len >= 2) { + GETCHAR(opt, p); + GETCHAR(olen, p); + + if (olen < 2 || olen > len) { + break; + } + + printer(arg, " <"); + len -= olen; + + if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *)) + printer(arg, " %s", cbcp_optionnames[opt-1]); + else + printer(arg, " option=0x%x", opt); + + if (olen > 2) { + GETCHAR(delay, p); + printer(arg, " delay = %d", delay); + } + + if (olen > 3) { + int addrt; + char str[256]; + + GETCHAR(addrt, p); + memcpy(str, p, olen - 4); + str[olen - 4] = 0; + printer(arg, " number = %s", str); + } + printer(arg, ">"); + break; + } + + default: + break; + } + + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} + +/* received CBCP request */ +static void +cbcp_recvreq(us, pckt, pcktlen) + cbcp_state *us; + char *pckt; + int pcktlen; +{ + u_char type, opt_len, delay, addr_type; + char address[256]; + int len = pcktlen; + + address[0] = 0; + + while (len) { + syslog(LOG_DEBUG, "length: %d", len); + + GETCHAR(type, pckt); + GETCHAR(opt_len, pckt); + + if (opt_len > 2) + GETCHAR(delay, pckt); + + us->us_allowed |= (1 << type); + + switch(type) { + case CB_CONF_NO: + syslog(LOG_DEBUG, "no callback allowed"); + break; + + case CB_CONF_USER: + syslog(LOG_DEBUG, "user callback allowed"); + if (opt_len > 4) { + GETCHAR(addr_type, pckt); + memcpy(address, pckt, opt_len - 4); + address[opt_len - 4] = 0; + if (address[0]) + syslog(LOG_DEBUG, "address: %s", address); + } + break; + + case CB_CONF_ADMIN: + syslog(LOG_DEBUG, "user admin defined allowed"); + break; + + case CB_CONF_LIST: + break; + } + len -= opt_len; + } + + cbcp_resp(us); +} + +static void +cbcp_resp(us) + cbcp_state *us; +{ + u_char cb_type; + u_char buf[256]; + u_char *bufp = buf; + int len = 0; + + cb_type = us->us_allowed & us->us_type; + syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type); + +#if 0 + if (!cb_type) + lcp_down(us->us_unit); +#endif + + if (cb_type & ( 1 << CB_CONF_USER ) ) { + syslog(LOG_DEBUG, "cbcp_resp CONF_USER"); + PUTCHAR(CB_CONF_USER, bufp); + len = 3 + 1 + strlen(us->us_number) + 1; + PUTCHAR(len , bufp); + PUTCHAR(5, bufp); /* delay */ + PUTCHAR(1, bufp); + BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); + cbcp_send(us, CBCP_RESP, buf, len); + return; + } + + if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { + syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN"); + PUTCHAR(CB_CONF_ADMIN, bufp); + len = 3 + 1; + PUTCHAR(len , bufp); + PUTCHAR(5, bufp); /* delay */ + PUTCHAR(0, bufp); + cbcp_send(us, CBCP_RESP, buf, len); + return; + } + + if (cb_type & ( 1 << CB_CONF_NO ) ) { + syslog(LOG_DEBUG, "cbcp_resp CONF_NO"); + PUTCHAR(CB_CONF_NO, bufp); + len = 3; + PUTCHAR(len , bufp); + PUTCHAR(0, bufp); + cbcp_send(us, CBCP_RESP, buf, len); + ipcp_open(us->us_unit); + return; + } +} + +static void +cbcp_send(us, code, buf, len) + cbcp_state *us; + u_char code; + u_char *buf; + int len; +{ + u_char *outp; + int outlen; + + outp = outpacket_buf; + + outlen = 4 + len; + + MAKEHEADER(outp, PPP_CBCP); + + PUTCHAR(code, outp); + PUTCHAR(us->us_id, outp); + PUTSHORT(outlen, outp); + + if (len) + BCOPY(buf, outp, len); + + output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN); +} + +static void +cbcp_recvack(us, pckt, len) + cbcp_state *us; + char *pckt; + int len; +{ + u_char type, delay, addr_type; + int opt_len; + char address[256]; + + if (len) { + GETCHAR(type, pckt); + GETCHAR(opt_len, pckt); + + if (opt_len > 2) + GETCHAR(delay, pckt); + + if (opt_len > 4) { + GETCHAR(addr_type, pckt); + memcpy(address, pckt, opt_len - 4); + address[opt_len - 4] = 0; + if (address[0]) + syslog(LOG_DEBUG, "peer will call: %s", address); + } + } + + cbcp_up(us); +} + +extern int persist; + +/* ok peer will do callback */ +static void +cbcp_up(us) + cbcp_state *us; +{ + persist = 0; + lcp_close(0,0); +} |