📄 ppp_ahdlc.c
字号:
error = 0; break; case PPPIO_LASTMOD: /* we knew this anyway */ error = 0; break; default: error = -1; break; } if (error < 0) putnext(q, mp); else if (error == 0) { mp->b_datap->db_type = M_IOCACK; qreply(q, mp); } 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:#if defined(USE_MUTEX) mutex_enter(&state->lock);#endif /* USE_MUTEX */ state->mtu = ((unsigned short *)mp->b_rptr)[1];#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */ freemsg(mp); break; case PPPCTL_MRU:#if defined(USE_MUTEX) mutex_enter(&state->lock);#endif /* USE_MUTEX */ state->mru = ((unsigned short *)mp->b_rptr)[1];#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */ freemsg(mp); break; case PPPCTL_UNIT:#if defined(USE_MUTEX) mutex_enter(&state->lock);#endif /* USE_MUTEX */ state->unit = mp->b_rptr[1];#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */ break; default: putnext(q, mp); } break; default: putnext(q, mp); } return 0;}/* * Read side put routine */static intahdlc_rput(q, mp) queue_t *q; mblk_t *mp;{ ahdlc_state_t *state; state = (ahdlc_state_t *) q->q_ptr; if (state == 0) { DPRINT("state == 0 in ahdlc_rput\n"); freemsg(mp); return 0; } switch (mp->b_datap->db_type) { case M_DATA: ahdlc_decode(q, mp); freemsg(mp); break; case M_HANGUP:#if defined(USE_MUTEX) mutex_enter(&state->lock);#endif /* USE_MUTEX */ if (state->rx_buf != 0) { /* XXX would like to send this up for debugging */ freemsg(state->rx_buf); state->rx_buf = 0; } state->flags = IFLUSH;#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */ putnext(q, mp); break; default: putnext(q, mp); } return 0;}/* * Extract bit c from map m, to determine if c needs to be escaped */#define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))static voidahdlc_encode(q, mp) queue_t *q; mblk_t *mp;{ ahdlc_state_t *state; u_int32_t *xaccm, loc_xaccm[8]; ushort_t fcs; size_t outmp_len; mblk_t *outmp, *tmp; uchar_t *dp, fcs_val; int is_lcp, code;#if defined(SOL2) clock_t lbolt;#endif /* SOL2 */ if (msgdsize(mp) < 4) { return; } state = (ahdlc_state_t *)q->q_ptr;#if defined(USE_MUTEX) mutex_enter(&state->lock);#endif /* USE_MUTEX */ /* * Allocate an output buffer large enough to handle a case where all * characters need to be escaped */ outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */ (sizeof(fcs) << 2) + /* HDLC FCS x 4 */ (sizeof(uchar_t) << 1); /* HDLC flags x 2 */ outmp = allocb(outmp_len, BPRI_MED); if (outmp == NULL) { state->stats.ppp_oerrors++;#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */ putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR); return; }#if defined(SOL2) /* * Check if our last transmit happenned within flag_time, using * the system's LBOLT value in clock ticks */ if (drv_getparm(LBOLT, &lbolt) != -1) { if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) { *outmp->b_wptr++ = PPP_FLAG; } state->lbolt = lbolt; } else { *outmp->b_wptr++ = PPP_FLAG; }#else /* * If the driver below still has a message to process, skip the * HDLC flag, otherwise, put one in the beginning */ if (qsize(q->q_next) == 0) { *outmp->b_wptr++ = PPP_FLAG; }#endif /* * All control characters must be escaped for LCP packets with code * values between 1 (Conf-Req) and 7 (Code-Rej). */ is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) && (MSG_BYTE(mp, 1) == PPP_UI) && (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) && (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) && LCP_USE_DFLT(mp)); xaccm = state->xaccm; if (is_lcp) { bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm)); loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */ xaccm = loc_xaccm; } fcs = PPP_INITFCS; /* Initial FCS is 0xffff */ /* * Process this block and the rest (if any) attached to the this one */ for (tmp = mp; tmp; tmp = tmp->b_cont) { if (tmp->b_datap->db_type == M_DATA) { for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) { fcs = PPP_FCS(fcs, *dp); if (IN_TX_MAP(*dp, xaccm)) { *outmp->b_wptr++ = PPP_ESCAPE; *outmp->b_wptr++ = *dp ^ PPP_TRANS; } else { *outmp->b_wptr++ = *dp; } } } else { continue; /* skip if db_type is something other than M_DATA */ } } /* * Append the HDLC FCS, making sure that escaping is done on any * necessary bytes */ fcs_val = (fcs ^ 0xffff) & 0xff; if (IN_TX_MAP(fcs_val, xaccm)) { *outmp->b_wptr++ = PPP_ESCAPE; *outmp->b_wptr++ = fcs_val ^ PPP_TRANS; } else { *outmp->b_wptr++ = fcs_val; } fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff; if (IN_TX_MAP(fcs_val, xaccm)) { *outmp->b_wptr++ = PPP_ESCAPE; *outmp->b_wptr++ = fcs_val ^ PPP_TRANS; } else { *outmp->b_wptr++ = fcs_val; } /* * And finally, append the HDLC flag, and send it away */ *outmp->b_wptr++ = PPP_FLAG; state->stats.ppp_obytes += msgdsize(outmp); state->stats.ppp_opackets++;#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */ putnext(q, outmp); return;}/* * Checks the 32-bit receive ACCM to see if the byte needs un-escaping */#define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \ (m) & (1 << (c)))/* * Process received characters. */static voidahdlc_decode(q, mp) queue_t *q; mblk_t *mp;{ ahdlc_state_t *state; mblk_t *om; uchar_t *dp; ushort_t fcs;#if defined(SOL2) mblk_t *zmp;#endif /* SOL2 */#if defined(SOL2) /* * In case the driver (or something below) doesn't send * data upstream in one message block, concatenate everything */ if (!((mp->b_wptr - mp->b_rptr == msgdsize(mp)) && ((intpointer_t)mp->b_rptr % sizeof(intpointer_t) == 0))) { zmp = msgpullup(mp, -1); freemsg(mp); mp = zmp; if (mp == 0) return; }#endif /* SOL2 */ state = (ahdlc_state_t *) q->q_ptr;#if defined(USE_MUTEX) mutex_enter(&state->lock);#endif /* USE_MUTEX */ state->stats.ppp_ibytes += msgdsize(mp); for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) { /* * This should detect the lack of 8-bit communication channel * which is necessary for PPP to work. In addition, it also * checks on the parity. */ if (*dp & 0x80) state->flags |= RCV_B7_1; else state->flags |= RCV_B7_0; if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f))) state->flags |= RCV_ODDP; else state->flags |= RCV_EVNP; /* * So we have a HDLC flag ... */ if (*dp == PPP_FLAG) { /* * If we think that it marks the beginning of the frame, * then continue to process the next octects */ if ((state->flags & IFLUSH) || (state->rx_buf == 0) || (msgdsize(state->rx_buf) == 0)) { state->flags &= ~IFLUSH; continue; } /* * We get here because the above condition isn't true, * in which case the HDLC flag was there to mark the end * of the frame (or so we think) */ om = state->rx_buf; if (state->infcs == PPP_GOODFCS) { state->stats.ppp_ipackets++; adjmsg(om, -PPP_FCSLEN); putnext(q, om); } else { DPRINT2("ppp%d: bad fcs (len=%d)\n", state->unit, msgdsize(state->rx_buf)); freemsg(state->rx_buf); state->flags &= ~(IFLUSH | ESCAPED); state->stats.ppp_ierrors++; putctl1(q->q_next, M_CTL, PPPCTL_IERROR); } state->rx_buf = 0; continue; } if (state->flags & IFLUSH) { continue; } /* * Allocate a receive buffer, large enough to store a frame (after * un-escaping) of at least 1500 octets. If MRU is negotiated to * be more than the default, then allocate that much. In addition, * we add an extra 32-bytes for a fudge factor */ if (state->rx_buf == 0) { state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru); state->rx_buf_size += (sizeof(u_int32_t) << 3); state->rx_buf = allocb(state->rx_buf_size, BPRI_MED); /* * If allocation fails, try again on the next frame */ if (state->rx_buf == 0) { state->flags |= IFLUSH; continue; } state->flags &= ~(IFLUSH | ESCAPED); state->infcs = PPP_INITFCS; } if (*dp == PPP_ESCAPE) { state->flags |= ESCAPED; continue; } /* * Make sure we un-escape the necessary characters, as well as the * ones in our receive async control character map */ if (state->flags & ESCAPED) { *dp ^= PPP_TRANS; state->flags &= ~ESCAPED; } else if (IN_RX_MAP(*dp, state->raccm)) continue; /* * Unless the peer lied to us about the negotiated MRU, we should * never get a frame which is too long. If it happens, toss it away * and grab the next incoming one */ if (msgdsize(state->rx_buf) < state->rx_buf_size) { state->infcs = PPP_FCS(state->infcs, *dp); *state->rx_buf->b_wptr++ = *dp; } else { DPRINT2("ppp%d: frame too long (%d)\n", state->unit, msgdsize(state->rx_buf)); freemsg(state->rx_buf); state->rx_buf = 0; state->flags |= IFLUSH; } }#if defined(USE_MUTEX) mutex_exit(&state->lock);#endif /* USE_MUTEX */}static intmsg_byte(mp, i) mblk_t *mp; unsigned int i;{ while (mp != 0 && i >= mp->b_wptr - mp->b_rptr) mp = mp->b_cont; if (mp == 0) return -1; return mp->b_rptr[i];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -