X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=svr4%2Fppp_ahdlc.c;h=b483276bd9f39939b48ece071cdafc1cc5568518;hp=2e62d21b88f5a1d9b0ff320dc3f0a340ffa1d556;hb=528c6d493b74e1fb310f00f9ae9d5c840c61588d;hpb=eeeeae4502021b0dac85d3212f1b25a94496ee94 diff --git a/svr4/ppp_ahdlc.c b/svr4/ppp_ahdlc.c index 2e62d21..b483276 100644 --- a/svr4/ppp_ahdlc.c +++ b/svr4/ppp_ahdlc.c @@ -1,3 +1,36 @@ +/* + * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + * + * $Id: ppp_ahdlc.c,v 1.2 1995/05/19 02:18:34 paulus Exp $ + */ + +/* + * This file is used under Solaris 2. + */ + #include #include #include @@ -6,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -65,6 +100,7 @@ struct ahdlc_state { u_int32_t raccm; int mtu; int mru; + int unit; }; /* Values for flags */ @@ -185,6 +221,7 @@ ahdlc_wput(q, mp) { struct ahdlc_state *state; struct iocblk *iop; + int error; state = (struct ahdlc_state *) q->q_ptr; switch (mp->b_datap->db_type) { @@ -199,36 +236,63 @@ ahdlc_wput(q, mp) case M_IOCTL: iop = (struct iocblk *) mp->b_rptr; + error = EINVAL; switch (iop->ioc_cmd) { case PPPIO_XACCM: - if (iop->ioc_count != sizeof(ext_accm)) - goto iocnak; - bcopy(mp->b_cont->b_rptr, (caddr_t)state->xaccm, sizeof(ext_accm)); + if (iop->ioc_count < sizeof(u_int32_t) + || iop->ioc_count > sizeof(ext_accm)) + break; + bcopy(mp->b_cont->b_rptr, (caddr_t)state->xaccm, iop->ioc_count); state->xaccm[2] &= 0x40000000; /* don't escape 0x5e */ state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */ - goto iocack; + iop->ioc_count = 0; + error = 0; + break; case PPPIO_RACCM: if (iop->ioc_count != sizeof(u_int32_t)) - goto iocnak; - state->raccm = *(u_int32_t *)mp->b_cont->b_rptr; - goto iocack; + break; + bcopy(mp->b_cont->b_rptr, (caddr_t)&state->raccm, + sizeof(u_int32_t)); + iop->ioc_count = 0; + error = 0; + break; default: - putnext(q, mp); + error = -1; break; + } - iocack: - iop->ioc_count = 0; + if (error < 0) + putnext(q, mp); + else if (error == 0) { mp->b_datap->db_type = M_IOCACK; qreply(q, mp); - break; - - iocnak: + } else { mp->b_datap->db_type = M_IOCNAK; + iop->ioc_count = 0; + iop->ioc_error = error; qreply(q, mp); + } + break; + + case M_CTL: + switch (*mp->b_rptr) { + case PPPCTL_MTU: + state->mtu = ((unsigned short *)mp->b_rptr)[1]; + freemsg(mp); + break; + case PPPCTL_MRU: + state->mru = ((unsigned short *)mp->b_rptr)[1]; + freemsg(mp); + break; + case PPPCTL_UNIT: + state->unit = mp->b_rptr[1]; break; + default: + putnext(q, mp); } + break; default: putnext(q, mp); @@ -308,13 +372,22 @@ stuff_frame(q, mp) /* * For LCP packets, we must escape all control characters. + * LCP packets must not be A/C or protocol compressed. */ - if (proto == PPP_LCP) { - bcopy(state->xaccm, lcp_xaccm, sizeof(lcp_xaccm)); - lcp_xaccm[0] = ~0; - xaccm = lcp_xaccm; - } else - xaccm = state->xaccm; + xaccm = state->xaccm; + if (ilen >= PPP_HDRLEN) { + if (mp->b_wptr - mp->b_rptr >= PPP_HDRLEN + || pullupmsg(mp, PPP_HDRLEN)) { + if (PPP_ADDRESS(mp->b_rptr) == PPP_ALLSTATIONS + && PPP_CONTROL(mp->b_rptr) == PPP_UI + && PPP_PROTOCOL(mp->b_rptr) == PPP_LCP) { + bcopy((caddr_t) state->xaccm, (caddr_t) lcp_xaccm, + sizeof(lcp_xaccm)); + lcp_xaccm[0] = ~0; + xaccm = lcp_xaccm; + } + } + } sp = mp->b_rptr; fcs = PPP_INITFCS; @@ -457,7 +530,7 @@ unstuff_chars(q, mp) */ dp = om->b_wptr; len = om->b_datap->db_lim - dp; /* max # output bytes */ - extra = (cpend - cp) - len; /* #input chars - #output bytes */ + extra = (mp->b_wptr - cp) - len;/* #input chars - #output bytes */ if (extra < 0) { len += extra; /* we'll run out of input first */ extra = 0; @@ -471,11 +544,10 @@ unstuff_chars(q, mp) break; ++cp; if (c == PPP_ESCAPE) { - if (extra > 0) + if (extra > 0) { --extra; - else if (len > 1) - --len; - else { + ++cpend; + } else if (cp >= cpend) { state->flags |= ESCAPED; break; } @@ -491,7 +563,7 @@ unstuff_chars(q, mp) state->inlen += dp - dp0; state->infcs = fcs; om->b_wptr = dp; - if (len <= 0) + if (cp >= cpend) continue; /* go back and check cp again */ } @@ -508,20 +580,19 @@ unstuff_chars(q, mp) state->inlen = 0; if (om == 0) continue; - if (state->flags & (IFLUSH|ESCAPED) || len < PPP_FCSLEN) { - /* XXX should send up ctl message to notify VJ decomp */ - freemsg(om); - continue; - } - if (state->infcs != PPP_GOODFCS) { + if (!(state->flags & (IFLUSH|ESCAPED) || len < PPP_FCSLEN)) { + if (state->infcs == PPP_GOODFCS) { + adjmsg(om, -PPP_FCSLEN); /* chop off fcs */ + putnext(q, om); /* bombs away! */ + continue; + } /* incr bad fcs stats */ - /* would like to be able to pass this up for debugging */ - /* XXX should send up ctl message to notify VJ decomp */ - freemsg(om); - continue; +#if DEBUG + cmn_err(CE_CONT, "ppp_ahdl: bad fcs %x\n", state->infcs); +#endif } - adjmsg(om, -PPP_FCSLEN); /* chop off fcs */ - putnext(q, om); /* bombs away! */ + freemsg(om); + putctl1(q->q_next, M_CTL, PPPCTL_IERROR); continue; } @@ -529,6 +600,7 @@ unstuff_chars(q, mp) continue; if (state->flags & ESCAPED) { c ^= PPP_TRANS; + state->flags &= ~ESCAPED; } else if (c == PPP_ESCAPE) { state->flags |= ESCAPED; continue; @@ -549,11 +621,19 @@ unstuff_chars(q, mp) om = state->cur_blk; if (om->b_wptr >= om->b_datap->db_lim) { /* - * Current message block is full. Allocate another one. + * Current message block is full. Allocate another one, + * unless we have run out of MRU. */ + if (state->inlen >= state->mru + PPP_HDRLEN + PPP_FCSLEN) { +#if DEBUG + cmn_err(CE_CONT, "ppp_ahdl: frame too long (%d)\n", + state->inlen); +#endif + state->flags |= IFLUSH; + continue; + } om = allocb(IFRAME_BSIZE, BPRI_MED); if (om == 0) { - freemsg(state->cur_frame); state->flags |= IFLUSH; continue; } @@ -571,18 +651,20 @@ unstuff_chars(q, mp) * but we do leave space for the decompressed fields and * arrange for the info field to start on a word boundary. */ - cp = om->b_rptr; - if (*cp == PPP_ALLSTATIONS) - cp += 2; - if ((*cp & 1) == 0) - ++cp; - /* cp is now pointing at the last byte of the ppp protocol field */ - offset = 3 - ((unsigned)cp & 3); + dp = om->b_rptr; + if (PPP_ADDRESS(dp) == PPP_ALLSTATIONS + && PPP_CONTROL(dp) == PPP_UI) + dp += 2; + if ((*dp & 1) == 0) + ++dp; + /* dp is now pointing at the last byte of the ppp protocol field */ + offset = 3 - ((unsigned)dp & 3); if (offset > 0) { + dp = om->b_wptr; do { - cp[offset] = cp[0]; - --cp; - } while (cp >= om->b_rptr); + --dp; + dp[offset] = dp[0]; + } while (dp > om->b_rptr); om->b_rptr += offset; om->b_wptr += offset; }