⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppp.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*     * Here is where we might, in future, decide whether to pass     * or drop the packet, and whether it counts as link activity.     */    pass = 1;#endif /* FILTER_PACKETS */    if (pass < 0) {	/* pass only if link already up, and don't update time */	if (ppa->lowerq == 0) {	    freemsg(mp);	    return 0;	}	pass = 1;    } else if (pass) {	if (outbound)	    ppa->last_sent = time;	else	    ppa->last_recv = time;    }    return pass;}/* * We have some data to send down to the lower stream (or up the * control stream, if we don't have a lower stream attached). * Returns 1 if the message was dealt with, 0 if it wasn't able * to be sent on and should therefore be queued up. */static intsend_data(mp, us)    mblk_t *mp;    upperstr_t *us;{    upperstr_t *ppa;    if ((us->flags & US_BLOCKED) || us->npmode == NPMODE_QUEUE)	return 0;    ppa = us->ppa;    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 (ppa->lowerq == 0) {	/* try to send it up the control stream */        if (bcanputnext(ppa->q, mp->b_band)) {	    /*	     * 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 {        if (bcanputnext(ppa->lowerq, mp->b_band)) {	    MT_ENTER(&ppa->stats_lock);	    ppa->stats.ppp_opackets++;	    ppa->stats.ppp_obytes += msgdsize(mp);#ifdef INCR_OPACKETS	    INCR_OPACKETS(ppa);#endif	    MT_EXIT(&ppa->stats_lock);	    /*	     * The lower queue is only ever detached while holding an	     * exclusive lock on the whole driver.  So we can be confident	     * that the lower queue is still there.	     */	    putnext(ppa->lowerq, mp);	    return 1;	}    }    us->flags |= US_BLOCKED;    return 0;}/* * Allocate a new PPA id and link this stream into the list of PPAs. * This procedure is called with an exclusive lock on all queues in * this driver. */static voidnew_ppa(q, mp)    queue_t *q;    mblk_t *mp;{    upperstr_t *us, *up, **usp;    int ppa_id;    us = (upperstr_t *) q->q_ptr;    if (us == 0) {	DPRINT("new_ppa: q_ptr = 0!\n");	return;    }    usp = &ppas;    ppa_id = 0;    while ((up = *usp) != 0 && ppa_id == up->ppa_id) {	++ppa_id;	usp = &up->nextppa;    }    us->ppa_id = ppa_id;    us->ppa = us;    us->next = 0;    us->nextppa = *usp;    *usp = us;    us->flags |= US_CONTROL;    us->npmode = NPMODE_PASS;    us->mtu = PPP_MTU;    us->mru = PPP_MRU;#ifdef SOL2    /*     * Create a kstats record for our statistics, so netstat -i works.     */    if (us->kstats == 0) {	char unit[32];	sprintf(unit, "ppp%d", us->ppa->ppa_id);	us->kstats = kstat_create("ppp", us->ppa->ppa_id, unit,				  "net", KSTAT_TYPE_NAMED, 4, 0);	if (us->kstats != 0) {	    kstat_named_t *kn = KSTAT_NAMED_PTR(us->kstats);	    strcpy(kn[0].name, "ipackets");	    kn[0].data_type = KSTAT_DATA_ULONG;	    strcpy(kn[1].name, "ierrors");	    kn[1].data_type = KSTAT_DATA_ULONG;	    strcpy(kn[2].name, "opackets");	    kn[2].data_type = KSTAT_DATA_ULONG;	    strcpy(kn[3].name, "oerrors");	    kn[3].data_type = KSTAT_DATA_ULONG;	    kstat_install(us->kstats);	}    }#endif /* SOL2 */    *(int *)mp->b_cont->b_rptr = ppa_id;    mp->b_datap->db_type = M_IOCACK;    qreply(q, mp);}static voidattach_ppa(q, mp)    queue_t *q;    mblk_t *mp;{    upperstr_t *us, *t;    us = (upperstr_t *) q->q_ptr;    if (us == 0) {	DPRINT("attach_ppa: q_ptr = 0!\n");	return;    }#ifndef NO_DLPI    us->state = DL_UNBOUND;#endif    for (t = us->ppa; t->next != 0; t = t->next)	;    t->next = us;    us->next = 0;    if (mp->b_datap->db_type == M_IOCTL) {	mp->b_datap->db_type = M_IOCACK;	qreply(q, mp);    } else {#ifndef NO_DLPI	dlpi_ok(q, DL_ATTACH_REQ);#endif    }}static voiddetach_ppa(q, mp)    queue_t *q;    mblk_t *mp;{    upperstr_t *us, *t;    us = (upperstr_t *) q->q_ptr;    if (us == 0) {	DPRINT("detach_ppa: q_ptr = 0!\n");	return;    }    for (t = us->ppa; t->next != 0; t = t->next)	if (t->next == us) {	    t->next = us->next;	    break;	}    us->next = 0;    us->ppa = 0;#ifndef NO_DLPI    us->state = DL_UNATTACHED;    dlpi_ok(q, DL_DETACH_REQ);#endif}/* * We call this with qwriter in order to give the upper queue procedures * the guarantee that the lower queue is not going to go away while * they are executing. */static voiddetach_lower(q, mp)    queue_t *q;    mblk_t *mp;{    upperstr_t *us;    us = (upperstr_t *) q->q_ptr;    if (us == 0) {	DPRINT("detach_lower: q_ptr = 0!\n");	return;    }    LOCK_LOWER_W;    us->lowerq->q_ptr = 0;    RD(us->lowerq)->q_ptr = 0;    us->lowerq = 0;    UNLOCK_LOWER;    /* Unblock streams which now feed back up the control stream. */    qenable(us->q);    mp->b_datap->db_type = M_IOCACK;    qreply(q, mp);}static intpppuwsrv(q)    queue_t *q;{    upperstr_t *us, *as;    mblk_t *mp;    us = (upperstr_t *) q->q_ptr;    if (us == 0) {	DPRINT("pppuwsrv: q_ptr = 0!\n");	return 0;    }    /*     * If this is a control stream, then this service procedure     * probably got enabled because of flow control in the lower     * stream being enabled (or because of the lower stream going     * away).  Therefore we enable the service procedure of all     * attached upper streams.     */    if (us->flags & US_CONTROL) {	for (as = us->next; as != 0; as = as->next)	    qenable(WR(as->q));    }    /* Try to send on any data queued here. */    us->flags &= ~US_BLOCKED;    while ((mp = getq(q)) != 0) {	if (!send_data(mp, us)) {	    putbq(q, mp);	    break;	}    }    return 0;}/* should never get called... */static intppplwput(q, mp)    queue_t *q;    mblk_t *mp;{    putnext(q, mp);    return 0;}static intppplwsrv(q)    queue_t *q;{    queue_t *uq;    /*     * Flow control has back-enabled this stream:     * enable the upper write service procedure for     * the upper control stream for this lower stream.     */    LOCK_LOWER_R;    uq = (queue_t *) q->q_ptr;    if (uq != 0)	qenable(uq);    UNLOCK_LOWER;    return 0;}/* * This should only get called for control streams. */static intpppurput(q, mp)    queue_t *q;    mblk_t *mp;{    upperstr_t *ppa, *us;    int proto, len;    struct iocblk *iop;    ppa = (upperstr_t *) q->q_ptr;    if (ppa == 0) {	DPRINT("pppurput: q_ptr = 0!\n");	return 0;    }    switch (mp->b_datap->db_type) {    case M_CTL:	MT_ENTER(&ppa->stats_lock);	switch (*mp->b_rptr) {	case PPPCTL_IERROR:#ifdef INCR_IERRORS	    INCR_IERRORS(ppa);#endif	    ppa->stats.ppp_ierrors++;	    break;	case PPPCTL_OERROR:#ifdef INCR_OERRORS	    INCR_OERRORS(ppa);#endif	    ppa->stats.ppp_oerrors++;	    break;	}	MT_EXIT(&ppa->stats_lock);	freemsg(mp);	break;    case M_IOCACK:    case M_IOCNAK:	/*	 * Attempt to match up the response with the stream	 * that the request came from.	 */	iop = (struct iocblk *) mp->b_rptr;	for (us = ppa; us != 0; us = us->next)	    if (us->ioc_id == iop->ioc_id)		break;	if (us == 0)	    freemsg(mp);	else	    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);	    if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN) {		PULLUP(mp, PPP_HDRLEN);		if (mp == 0) {		    DPRINT1("ppp_urput: msgpullup failed (len=%d)\n", len);		    break;		}	    }	    MT_ENTER(&ppa->stats_lock);	    ppa->stats.ppp_ipackets++;	    ppa->stats.ppp_ibytes += len;#ifdef INCR_IPACKETS	    INCR_IPACKETS(ppa);#endif	    MT_EXIT(&ppa->stats_lock);	    proto = PPP_PROTOCOL(mp->b_rptr);#if defined(SOL2)	    /*	     * Should there be any promiscuous stream(s), send the data	     * up for each promiscuous stream that we recognize.	     */	    promisc_sendup(ppa, mp, proto, 1);#endif /* defined(SOL2) */	    if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {		/*		 * A data packet for some network protocol.		 * Queue it on the upper stream for that protocol.		 * XXX could we just putnext it?  (would require thought)		 * The rblocked flag is there to ensure that we keep		 * messages in order for each network protocol.		 */		if (!pass_packet(us, mp, 0))		    break;		if (!us->rblocked && !canput(us->q))		    us->rblocked = 1;		if (!us->rblocked)		    putq(us->q, mp);		else		    putq(q, mp);		break;	    }	}	/*	 * A control frame, a frame for an unknown protocol,	 * or some other message type.	 * Send it up to pppd via the control stream.	 */	if (queclass(mp) == QPCTL || canputnext(ppa->q))	    putnext(ppa->q, mp);	else	    putq(q, mp);	break;    }    return 0;}static intpppursrv(q)    queue_t *q;{    upperstr_t *us, *as;    mblk_t *mp, *hdr;#ifndef NO_DLPI    dl_unitdata_ind_t *ud;#endif    int proto;    us = (upperstr_t *) q->q_ptr;    if (us == 0) {	DPRINT("pppursrv: q_ptr = 0!\n");	return 0;    }    if (us->flags & US_CONTROL) {	/*	 * A control stream.	 * If there is no lower queue attached, run the write service	 * routines of other upper streams attached to this PPA.	 */	if (us->lowerq == 0) {	    as = us;	    do {		if (as->flags & US_BLOCKED)		    qenable(WR(as->q));		as = as->next;	    } while (as != 0);	}	/*	 * Messages get queued on this stream's read queue if they	 * can't be queued on the read queue of the attached stream	 * that they are destined for.  This is for flow control -	 * when this queue fills up, the lower read put procedure will	 * queue messages there and the flow control will propagate	 * down from there.	 */	while ((mp = getq(q)) != 0) {	    proto = PPP_PROTOCOL(mp->b_rptr);	    if (proto < 0x8000 && (as = find_dest(us, proto)) != 0) {		if (!canput(as->q))		    break;		putq(as->q, mp);	    } else {		if (!canputnext(q))		    break;		putnext(q, mp);	    }	}	if (mp) {	    putbq(q, mp);	} else {	    /* can now put stuff directly on network protocol streams again */	    for (as = us->next; as != 0; as = as->next)		as->rblocked = 0;	}	/*	 * If this stream has a lower stream attached,	 * enable the read queue's service routine.	 * XXX we should really only do this if the queue length

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -