📄 ppp.c
字号:
DPRINT1("ppp%d: lower stream still connected on close?\n", up->mn); LOCK_LOWER_W; up->lowerq->q_ptr = 0; RD(up->lowerq)->q_ptr = 0; up->lowerq = 0; UNLOCK_LOWER; } /* * This stream represents a PPA: * For all streams attached to the PPA, clear their * references to this PPA. * Then remove this PPA from the list of PPAs. */ for (as = up->next; as != 0; as = asnext) { asnext = as->next; as->next = 0; as->ppa = 0; if (as->flags & US_BLOCKED) { as->flags &= ~US_BLOCKED; flushq(WR(as->q), FLUSHDATA); } } for (upp = &ppas; *upp != 0; upp = &(*upp)->nextppa) if (*upp == up) { *upp = up->nextppa; break; }#ifdef LACHTCP /* Remove the statistics from the active list. */ for (ifp = ifstats, pifp = 0; ifp; ifp = ifp->ifs_next) { if (ifp == &up->ifstats) { if (pifp) pifp->ifs_next = ifp->ifs_next; else ifstats = ifp->ifs_next; break; } pifp = ifp; }#endif } else { /* * If this stream is attached to a PPA, * remove it from the PPA's list. */ if ((as = up->ppa) != 0) { for (; as->next != 0; as = as->next) if (as->next == up) { as->next = up->next; break; } } }#ifdef SOL2 if (up->kstats) kstat_delete(up->kstats); mutex_destroy(&up->stats_lock);#endif q->q_ptr = NULL; WR(q)->q_ptr = NULL; for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) { if (*prevp == up) { *prevp = up->nextmn; break; } } FREE(up, sizeof(upperstr_t)); --ppp_count; return 0;}/* * A message from on high. We do one of three things: * - qreply() * - put the message on the lower write stream * - queue it for our service routine */static intpppuwput(q, mp) queue_t *q; mblk_t *mp;{ upperstr_t *us, *ppa, *nps; struct iocblk *iop; struct linkblk *lb;#ifdef LACHTCP struct ifreq *ifr; int i;#endif queue_t *lq; int error, n, sap; mblk_t *mq; struct ppp_idle *pip;#ifdef PRIOQ queue_t *tlq;#endif /* PRIOQ */#ifdef NO_DLPI upperstr_t *os;#endif us = (upperstr_t *) q->q_ptr; if (us == 0) { DPRINT("pppuwput: q_ptr = 0!\n"); return 0; } if (mp == 0) { DPRINT1("pppuwput/%d: mp = 0!\n", us->mn); return 0; } if (mp->b_datap == 0) { DPRINT1("pppuwput/%d: mp->b_datap = 0!\n", us->mn); return 0; } switch (mp->b_datap->db_type) {#ifndef NO_DLPI case M_PCPROTO: case M_PROTO: dlpi_request(q, mp, us); break;#endif /* NO_DLPI */ case M_DATA: if (us->flags & US_DBGLOG) DPRINT3("ppp/%d: uwput M_DATA len=%d flags=%x\n", us->mn, msgdsize(mp), us->flags); if (us->ppa == 0 || msgdsize(mp) > us->ppa->mtu + PPP_HDRLEN#ifndef NO_DLPI || (us->flags & US_CONTROL) == 0#endif /* NO_DLPI */ ) { DPRINT1("pppuwput: junk data len=%d\n", msgdsize(mp)); freemsg(mp); break; }#ifdef NO_DLPI if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1)) break;#endif if (!send_data(mp, us)) putq(q, mp); break; case M_IOCTL: iop = (struct iocblk *) mp->b_rptr; error = EINVAL; if (us->flags & US_DBGLOG) DPRINT3("ppp/%d: ioctl %x count=%d\n", us->mn, iop->ioc_cmd, iop->ioc_count); switch (iop->ioc_cmd) {#if defined(SOL2) case DLIOCRAW: /* raw M_DATA mode */ us->flags |= US_RAWDATA; error = 0; break;#endif /* defined(SOL2) */ case I_LINK: if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl I_LINK b_cont = 0!\n", us->mn); break; } lb = (struct linkblk *) mp->b_cont->b_rptr; lq = lb->l_qbot; if (lq == 0) { DPRINT1("pppuwput/%d: ioctl I_LINK l_qbot = 0!\n", us->mn); break; } LOCK_LOWER_W; us->lowerq = lq; lq->q_ptr = (caddr_t) q; RD(lq)->q_ptr = (caddr_t) us->q; UNLOCK_LOWER; iop->ioc_count = 0; error = 0; us->flags &= ~US_LASTMOD; /* Unblock upper streams which now feed this lower stream. */ qenable(q); /* Send useful information down to the modules which are now linked below us. */ putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id); putctl4(lq, M_CTL, PPPCTL_MRU, us->mru); putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);#ifdef PRIOQ /* Lower tty driver's queue hiwat/lowat from default 4096/128 to 256/128 since we don't want queueing of data on output to physical device */ freezestr(lq); for (tlq = lq; tlq->q_next != NULL; tlq = tlq->q_next) ; strqset(tlq, QHIWAT, 0, 256); strqset(tlq, QLOWAT, 0, 128); unfreezestr(lq);#endif /* PRIOQ */ break; case I_UNLINK: if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl I_UNLINK b_cont = 0!\n", us->mn); break; } lb = (struct linkblk *) mp->b_cont->b_rptr;#if DEBUG if (us->lowerq != lb->l_qbot) { DPRINT2("ppp unlink: lowerq=%x qbot=%x\n", us->lowerq, lb->l_qbot); break; }#endif iop->ioc_count = 0; qwriter(q, mp, detach_lower, PERIM_OUTER); error = -1; break; case PPPIO_NEWPPA: if (us->flags & US_CONTROL) break; if ((us->flags & US_PRIV) == 0) { error = EPERM; break; } /* Arrange to return an int */ if ((mq = mp->b_cont) == 0 || mq->b_datap->db_lim - mq->b_rptr < sizeof(int)) { mq = allocb(sizeof(int), 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; } iop->ioc_count = sizeof(int); mq->b_wptr = mq->b_rptr + sizeof(int); qwriter(q, mp, new_ppa, PERIM_OUTER); error = -1; break; case PPPIO_ATTACH: /* like dlpi_attach, for programs which can't write to the stream (like pppstats) */ if (iop->ioc_count != sizeof(int) || us->ppa != 0) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl PPPIO_ATTACH b_cont = 0!\n", us->mn); break; } n = *(int *)mp->b_cont->b_rptr; for (ppa = ppas; ppa != 0; ppa = ppa->nextppa) if (ppa->ppa_id == n) break; if (ppa == 0) break; us->ppa = ppa; iop->ioc_count = 0; qwriter(q, mp, attach_ppa, PERIM_OUTER); error = -1; break;#ifdef NO_DLPI case PPPIO_BIND: /* Attach to a given SAP. */ if (iop->ioc_count != sizeof(int) || us->ppa == 0) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl PPPIO_BIND b_cont = 0!\n", us->mn); break; } n = *(int *)mp->b_cont->b_rptr; /* n must be a valid PPP network protocol number. */ if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1) break; /* check that no other stream is bound to this sap already. */ for (os = us->ppa; os != 0; os = os->next) if (os->sap == n) break; if (os != 0) break; us->sap = n; iop->ioc_count = 0; error = 0; break;#endif /* NO_DLPI */ case PPPIO_MRU: if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl PPPIO_MRU b_cont = 0!\n", us->mn); break; } n = *(int *)mp->b_cont->b_rptr; if (n <= 0 || n > PPP_MAXMRU) break; if (n < PPP_MRU) n = PPP_MRU; us->mru = n; if (us->lowerq) putctl4(us->lowerq, M_CTL, PPPCTL_MRU, n); error = 0; iop->ioc_count = 0; break; case PPPIO_MTU: if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl PPPIO_MTU b_cont = 0!\n", us->mn); break; } n = *(int *)mp->b_cont->b_rptr; if (n <= 0 || n > PPP_MAXMTU) break; us->mtu = n;#ifdef LACHTCP /* The MTU reported in netstat, not used as IP max packet size! */ us->ifstats.ifs_mtu = n;#endif if (us->lowerq) putctl4(us->lowerq, M_CTL, PPPCTL_MTU, n); error = 0; iop->ioc_count = 0; break; case PPPIO_LASTMOD: us->flags |= US_LASTMOD; error = 0; break; case PPPIO_DEBUG: if (iop->ioc_count != sizeof(int)) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl PPPIO_DEBUG b_cont = 0!\n", us->mn); break; } n = *(int *)mp->b_cont->b_rptr; if (n == PPPDBG_DUMP + PPPDBG_DRIVER) { qwriter(q, NULL, debug_dump, PERIM_OUTER); iop->ioc_count = 0; error = -1; } else if (n == PPPDBG_LOG + PPPDBG_DRIVER) { DPRINT1("ppp/%d: debug log enabled\n", us->mn); us->flags |= US_DBGLOG; iop->ioc_count = 0; error = 0; } else { if (us->ppa == 0 || us->ppa->lowerq == 0) break; putnext(us->ppa->lowerq, mp); error = -1; } break; case PPPIO_NPMODE: if (iop->ioc_count != 2 * sizeof(int)) break; if ((us->flags & US_CONTROL) == 0) break; if (mp->b_cont == 0) { DPRINT1("pppuwput/%d: ioctl PPPIO_NPMODE b_cont = 0!\n", us->mn); break; } sap = ((int *)mp->b_cont->b_rptr)[0]; for (nps = us->next; nps != 0; nps = nps->next) { if (us->flags & US_DBGLOG) DPRINT2("us = 0x%x, us->next->sap = 0x%x\n", nps, nps->sap); 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; } /* XXX possibly should use qwriter here */ nps->npmode = (enum NPmode) ((int *)mp->b_cont->b_rptr)[1]; if (nps->npmode != NPMODE_QUEUE && (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: /* Sent from IP down to us. Attach the ifstats structure. */ if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0) break; ifr = (struct ifreq *)mp->b_cont->b_rptr; /* Find the unit number in the interface name. */ for (i = 0; i < IFNAMSIZ; i++) { if (ifr->ifr_name[i] == 0 || (ifr->ifr_name[i] >= '0' && ifr->ifr_name[i] <= '9')) break; else us->ifname[i] = ifr->ifr_name[i]; } us->ifname[i] = 0; /* Convert the unit number to binary. */ for (n = 0; i < IFNAMSIZ; i++) { if (ifr->ifr_name[i] == 0) { break; } else { n = n * 10 + ifr->ifr_name[i] - '0'; } } /* Verify the ppa. */ if (us->ppa->ppa_id != n) break; ppa = us->ppa; /* Set up the netstat block. */ strncpy (ppa->ifname, us->ifname, IFNAMSIZ); ppa->ifstats.ifs_name = ppa->ifname; ppa->ifstats.ifs_unit = n; ppa->ifstats.ifs_active = us->state != DL_UNBOUND; ppa->ifstats.ifs_mtu = ppa->mtu; /* Link in statistics used by netstat. */ ppa->ifstats.ifs_next = ifstats; ifstats = &ppa->ifstats; iop->ioc_count = 0; error = 0; break; case SIOCGIFFLAGS: if (!(us->flags & US_CONTROL)) { if (us->ppa) us = us->ppa; else break; } ((struct iocblk_in *)iop)->ioc_ifflags = us->ifflags; error = 0; break; case SIOCSIFFLAGS: if (!(us->flags & US_CONTROL)) { if (us->ppa) us = us->ppa; else break; } us->ifflags = ((struct iocblk_in *)iop)->ioc_ifflags; error = 0; break; case SIOCSIFADDR: if (!(us->flags & US_CONTROL)) { if (us->ppa) us = us->ppa; else break; } us->ifflags |= IFF_RUNNING; ((struct iocblk_in *)iop)->ioc_ifflags |= IFF_RUNNING; error = 0; break; case SIOCSIFMTU: /* * Vanilla SVR4 systems don't handle SIOCSIFMTU, rather * they take the MTU from the DL_INFO_ACK we sent in response
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -