X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=modules%2Fppp.c;h=7a181aaeaf469c18307c975f9a2667fe3cf8019c;hp=b3d78a336c1694cafecedd0007dbe9283e9b61c0;hb=f201866a877a11896aa9deffe7343670d756ea6d;hpb=a44a616baa968a263dc273bc06ed79c475b7deec;ds=sidebyside diff --git a/modules/ppp.c b/modules/ppp.c index b3d78a3..7a181aa 100644 --- a/modules/ppp.c +++ b/modules/ppp.c @@ -14,7 +14,7 @@ * 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 + * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, @@ -24,11 +24,11 @@ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * - * $Id: ppp.c,v 1.1 1995/12/11 05:06:40 paulus Exp $ + * $Id: ppp.c,v 1.8 1996/09/14 05:18:45 paulus Exp $ */ /* - * This file is used under Solaris 2 and SunOS 4. + * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX. */ #include @@ -37,7 +37,14 @@ #include #include #include +#ifdef __osf__ +#include +#include +#define queclass(mp) ((mp)->b_band & QPCTL) +#else #include +#endif +#include #ifdef SVR4 #include #include @@ -66,7 +73,7 @@ #endif /* - * The IP module uses this SAP value for IP packets. + * The IP module may use this SAP value for IP packets. */ #ifndef ETHERTYPE_IP #define ETHERTYPE_IP 0x800 @@ -76,6 +83,8 @@ #define PPP_MAXMTU 65535 #endif +extern time_t time; + /* * Private information; one per upper stream. */ @@ -90,6 +99,7 @@ typedef struct upperstr { struct upperstr *ppa; /* control stream for our ppa */ struct upperstr *next; /* next stream for this ppa */ uint ioc_id; /* last ioctl ID for this stream */ + enum NPmode npmode; /* what to do with packets on this SAP */ /* * There is exactly one control stream for each PPA. * The following fields are only used for control streams. @@ -100,6 +110,8 @@ typedef struct upperstr { int mru; int mtu; struct pppstat stats; /* statistics */ + time_t last_sent; /* time last NP packet sent */ + time_t last_recv; /* time last NP packet rcvd */ #ifdef SOL2 kstat_t *kstats; /* stats for netstat */ #endif /* SOL2 */ @@ -147,9 +159,11 @@ static void debug_dump __P((queue_t *, mblk_t *)); static upperstr_t *find_dest __P((upperstr_t *, int)); static int putctl2 __P((queue_t *, int, int, int)); static int putctl4 __P((queue_t *, int, int, int)); +static int pass_packet __P((upperstr_t *ppa, mblk_t *mp, int outbound)); +#define PPP_ID 0xb1a6 static struct module_info ppp_info = { - 0xb1a6, "ppp", 0, 512, 512, 128 + PPP_ID, "ppp", 0, 512, 512, 128 }; static struct qinit pppurint = { @@ -282,6 +296,8 @@ pppopen(q, dev, oflag, sflag) up->ifflags = IFF_UP | IFF_POINTOPOINT; #endif up->sap = -1; + up->last_sent = up->last_recv = time; + up->npmode = NPMODE_DROP; q->q_ptr = (caddr_t) up; WR(q)->q_ptr = (caddr_t) up; noenable(WR(q)); @@ -379,7 +395,7 @@ pppclose(q, flag) break; } } - kmem_free(up, sizeof(upperstr_t)); + FREE(up, sizeof(upperstr_t)); --ppp_count; return 0; @@ -396,7 +412,7 @@ pppuwput(q, mp) queue_t *q; mblk_t *mp; { - upperstr_t *us, *usnext, *ppa, *os; + upperstr_t *us, *usnext, *ppa, *os, *nps; struct iocblk *iop; struct linkblk *lb; #ifdef LACHTCP @@ -404,8 +420,10 @@ pppuwput(q, mp) int i; #endif queue_t *lq; - int error, n; + int error, n, sap; mblk_t *mq; + struct ppp_idle *pip; + int len; us = (upperstr_t *) q->q_ptr; switch (mp->b_datap->db_type) { @@ -429,6 +447,12 @@ pppuwput(q, mp) freemsg(mp); break; } +#ifdef NO_DLPI + if (!pass_packet(us->ppa, mp, 1)) { + freemsg(mp); + break; + } +#endif if (!send_data(mp, us)) putq(q, mp); break; @@ -598,9 +622,52 @@ pppuwput(q, mp) } break; + case PPPIO_NPMODE: + if (iop->ioc_count != 2 * sizeof(int)) + break; + if ((us->flags & US_CONTROL) == 0) + break; + sap = ((int *)mp->b_cont->b_rptr)[0]; + for (nps = us->next; nps != 0; nps = nps->next) + if (nps->sap == sap) + break; + if (nps == 0) { + if (us->flags & US_DBGLOG) + DPRINT2("ppp/%d: no stream for sap %x\n", us->mn, sap); + break; + } + nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1]; + if (nps->npmode == NPMODE_DROP || nps->npmode == NPMODE_ERROR) + flushq(WR(nps->q), FLUSHDATA); + else if (nps->npmode == NPMODE_PASS && qsize(WR(nps->q)) > 0 + && (nps->flags & US_BLOCKED) == 0) + qenable(WR(nps->q)); + iop->ioc_count = 0; + error = 0; + break; + + case PPPIO_GIDLE: + if ((ppa = us->ppa) == 0) + break; + mq = allocb(sizeof(struct ppp_idle), BPRI_HI); + if (mq == 0) { + error = ENOSR; + break; + } + if (mp->b_cont != 0) + freemsg(mp->b_cont); + mp->b_cont = mq; + mq->b_cont = 0; + pip = (struct ppp_idle *) mq->b_wptr; + pip->xmit_idle = time - ppa->last_sent; + pip->recv_idle = time - ppa->last_recv; + mq->b_wptr += sizeof(struct ppp_idle); + iop->ioc_count = sizeof(struct ppp_idle); + error = 0; + break; + #ifdef LACHTCP case SIOCSIFNAME: - printf("SIOCSIFNAME\n"); /* Sent from IP down to us. Attach the ifstats structure. */ if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0) break; @@ -648,7 +715,6 @@ pppuwput(q, mp) break; case SIOCGIFFLAGS: - printf("SIOCGIFFLAGS\n"); if (!(us->flags & US_CONTROL)) { if (us->ppa) us = us->ppa; @@ -660,7 +726,6 @@ pppuwput(q, mp) break; case SIOCSIFFLAGS: - printf("SIOCSIFFLAGS\n"); if (!(us->flags & US_CONTROL)) { if (us->ppa) us = us->ppa; @@ -672,7 +737,6 @@ pppuwput(q, mp) break; case SIOCSIFADDR: - printf("SIOCSIFADDR\n"); if (!(us->flags & US_CONTROL)) { if (us->ppa) us = us->ppa; @@ -765,7 +829,7 @@ dlpi_request(q, mp, us) dl_bind_ack_t *ackp; if (us->flags & US_DBGLOG) - cmn_err(CE_CONT, "ppp/%d: dlpi prim %x len=%d\n", us->mn, + DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn, d->dl_primitive, size); switch (d->dl_primitive) { case DL_INFO_REQ: @@ -840,9 +904,6 @@ dlpi_request(q, mp, us) except that we accept ETHERTYPE_IP in place of PPP_IP. */ sap = d->bind_req.dl_sap; us->req_sap = sap; -#if DEBUG - cmn_err(CE_CONT, "ppp bind %x\n", sap); -#endif if (sap == ETHERTYPE_IP) sap = PPP_IP; if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) { @@ -886,7 +947,7 @@ dlpi_request(q, mp, us) } us->sap = -1; us->state = DL_UNBOUND; -#ifndef sun +#ifdef LACHTCP us->ppa->ifstats.ifs_active = 0; #endif dlpi_ok(q, DL_UNBIND_REQ); @@ -899,15 +960,13 @@ dlpi_request(q, mp, us) dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0); break; } - if (us->ppa == 0) { + if ((ppa = us->ppa) == 0) { cmn_err(CE_CONT, "ppp: in state dl_idle but ppa == 0?\n"); break; } len = mp->b_cont == 0? 0: msgdsize(mp->b_cont); - if (len > us->ppa->mtu) { -#if DEBUG - cmn_err(CE_CONT, "dlpi data too large (%d > %d)\n", len, us->mtu); -#endif + if (len > ppa->mtu) { + DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu); break; } /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */ @@ -928,8 +987,12 @@ dlpi_request(q, mp, us) mp->b_rptr[1] = PPP_UI; mp->b_rptr[2] = us->sap >> 8; mp->b_rptr[3] = us->sap; - if (!send_data(mp, us)) - putq(q, mp); + if (!pass_packet(ppa, mp, 1)) { + freemsg(mp); + } else { + if (!send_data(mp, us)) + putq(q, mp); + } return; #if DL_CURRENT_VERSION >= 2 @@ -1020,6 +1083,23 @@ dlpi_ok(q, prim) } #endif /* NO_DLPI */ +static int +pass_packet(ppa, mp, outbound) + upperstr_t *ppa; + mblk_t *mp; + int outbound; +{ + /* + * Here is where we might, in future, decide whether to pass + * or drop the packet, and whether it counts as link activity. + */ + if (outbound) + ppa->last_sent = time; + else + ppa->last_recv = time; + return 1; +} + static int send_data(mp, us) mblk_t *mp; @@ -1028,17 +1108,26 @@ send_data(mp, us) queue_t *q; upperstr_t *ppa; - if (us->flags & US_BLOCKED) + if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE) return 0; ppa = us->ppa; - if (ppa == 0) { + if (ppa == 0 || us->npmode == NPMODE_DROP || us->npmode == NPMODE_ERROR) { + if (us->flags & US_DBGLOG) + DPRINT2("ppp/%d: dropping pkt (npmode=%d)\n", us->mn, us->npmode); freemsg(mp); return 1; } if ((q = ppa->lowerq) == 0) { /* try to send it up the control stream */ if (canputnext(ppa->q)) { - putnext(ppa->q, mp); + /* + * The message seems to get corrupted for some reason if + * we just send the message up as it is, so we send a copy. + */ + mblk_t *np = copymsg(mp); + freemsg(mp); + if (np != 0) + putnext(ppa->q, np); return 1; } } else { @@ -1083,6 +1172,7 @@ new_ppa(q, mp) us->nextppa = *usp; *usp = us; us->flags |= US_CONTROL; + us->npmode = NPMODE_PASS; us->mtu = PPP_MRU; us->mru = PPP_MRU; @@ -1377,6 +1467,22 @@ ppplrput(q, mp) putnext(us->q, mp); break; + case M_HANGUP: + /* + * The serial device has hung up. We don't want to send + * the M_HANGUP message up to pppd because that will stop + * us from using the control stream any more. Instead we + * send a zero-length message as an end-of-file indication. + */ + freemsg(mp); + mp = allocb(1, BPRI_HI); + if (mp == 0) { + DPRINT1("ppp/%d: couldn't allocate eof message!\n", ppa->mn); + break; + } + putnext(ppa->q, mp); + break; + default: if (mp->b_datap->db_type == M_DATA) { len = msgdsize(mp); @@ -1392,6 +1498,10 @@ ppplrput(q, mp) #ifdef INCR_IPACKETS INCR_IPACKETS(ppa); #endif + if (!pass_packet(ppa, mp, 0)) { + freemsg(mp); + break; + } proto = PPP_PROTOCOL(mp->b_rptr); if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) { /*