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

📄 ppp.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * has dropped below the low-water mark.	 */	if (us->lowerq != 0)	    qenable(RD(us->lowerq));		    } else {	/*	 * A network protocol stream.  Put a DLPI header on each	 * packet and send it on.	 * (Actually, it seems that the IP module will happily	 * accept M_DATA messages without the DL_UNITDATA_IND header.)	 */	while ((mp = getq(q)) != 0) {	    if (!canputnext(q)) {		putbq(q, mp);		break;	    }#ifndef NO_DLPI	    proto = PPP_PROTOCOL(mp->b_rptr);	    mp->b_rptr += PPP_HDRLEN;	    hdr = allocb(sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint),			 BPRI_MED);	    if (hdr == 0) {		/* XXX should put it back and use bufcall */		freemsg(mp);		continue;	    }	    hdr->b_datap->db_type = M_PROTO;	    ud = (dl_unitdata_ind_t *) hdr->b_wptr;	    hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(uint);	    hdr->b_cont = mp;	    ud->dl_primitive = DL_UNITDATA_IND;	    ud->dl_dest_addr_length = sizeof(uint);	    ud->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);	    ud->dl_src_addr_length = sizeof(uint);	    ud->dl_src_addr_offset = ud->dl_dest_addr_offset + sizeof(uint);#if DL_CURRENT_VERSION >= 2	    ud->dl_group_address = 0;#endif	    /* Send the DLPI client the data with the SAP they requested,	       (e.g. ETHERTYPE_IP) rather than the PPP protocol number	       (e.g. PPP_IP) */	    ((uint *)(ud + 1))[0] = us->req_sap;	/* dest SAP */	    ((uint *)(ud + 1))[1] = us->req_sap;	/* src SAP */	    putnext(q, hdr);#else /* NO_DLPI */	    putnext(q, mp);#endif /* NO_DLPI */	}	/*	 * Now that we have consumed some packets from this queue,	 * enable the control stream's read service routine so that we	 * can process any packets for us that might have got queued	 * there for flow control reasons.	 */	if (us->ppa)	    qenable(us->ppa->q);    }    return 0;}static upperstr_t *find_dest(ppa, proto)    upperstr_t *ppa;    int proto;{    upperstr_t *us;    for (us = ppa->next; us != 0; us = us->next)	if (proto == us->sap)	    break;    return us;}#if defined (SOL2)/* * Test upstream promiscuous conditions. As of now, only pass IPv4 and * Ipv6 packets upstream (let PPP packets be decoded elsewhere). */static upperstr_t *find_promisc(us, proto)    upperstr_t *us;    int proto;{    if ((proto != PPP_IP) && (proto != PPP_IPV6))	return (upperstr_t *)0;    for ( ; us; us = us->next) {	if ((us->flags & US_PROMISC) && (us->state == DL_IDLE))	    return us;    }    return (upperstr_t *)0;}/* * Prepend an empty Ethernet header to msg for snoop, et al. */static mblk_t *prepend_ether(us, mp, proto)    upperstr_t *us;    mblk_t *mp;    int proto;{    mblk_t *eh;    int type;    if ((eh = allocb(sizeof(struct ether_header), BPRI_HI)) == 0) {	freemsg(mp);	return (mblk_t *)0;    }    if (proto == PPP_IP)	type = ETHERTYPE_IP;    else if (proto == PPP_IPV6)	type = ETHERTYPE_IPV6;    else 	type = proto;	    /* What else? Let decoder decide */    eh->b_wptr += sizeof(struct ether_header);    bzero((caddr_t)eh->b_rptr, sizeof(struct ether_header));    ((struct ether_header *)eh->b_rptr)->ether_type = htons((short)type);    eh->b_cont = mp;    return (eh);}/* * Prepend DL_UNITDATA_IND mblk to msg */static mblk_t *prepend_udind(us, mp, proto)    upperstr_t *us;    mblk_t *mp;    int proto;{    dl_unitdata_ind_t *dlu;    mblk_t *dh;    size_t size;    size = sizeof(dl_unitdata_ind_t);    if ((dh = allocb(size, BPRI_MED)) == 0) {	freemsg(mp);	return (mblk_t *)0;    }    dh->b_datap->db_type = M_PROTO;    dh->b_wptr = dh->b_datap->db_lim;    dh->b_rptr = dh->b_wptr - size;    dlu = (dl_unitdata_ind_t *)dh->b_rptr;    dlu->dl_primitive = DL_UNITDATA_IND;    dlu->dl_dest_addr_length = 0;    dlu->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);    dlu->dl_src_addr_length = 0;    dlu->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);    dlu->dl_group_address = 0;    dh->b_cont = mp;    return (dh);}/* * For any recognized promiscuous streams, send data upstream */static voidpromisc_sendup(ppa, mp, proto, skip)    upperstr_t *ppa;    mblk_t *mp;    int proto, skip;{    mblk_t *dup_mp, *dup_dup_mp;    upperstr_t *prus, *nprus;    if ((prus = find_promisc(ppa, proto)) != 0) {	if (dup_mp = dupmsg(mp)) {	    if (skip)		dup_mp->b_rptr += PPP_HDRLEN;	    for ( ; nprus = find_promisc(prus->next, proto); 		    prus = nprus) {		if (dup_dup_mp = dupmsg(dup_mp)) {		    if (canputnext(prus->q)) {			if (prus->flags & US_RAWDATA) {			    dup_dup_mp = prepend_ether(prus, dup_dup_mp, proto);			    putnext(prus->q, dup_dup_mp);			} else {			    dup_dup_mp = prepend_udind(prus, dup_dup_mp, proto);			    putnext(prus->q, dup_dup_mp);			}		    } else {			DPRINT("ppp_urput: data to promisc q dropped\n");			freemsg(dup_dup_mp);		    }		}	    }	    if (canputnext(prus->q)) {		if (prus->flags & US_RAWDATA) {		    dup_mp = prepend_ether(prus, dup_mp, proto);		    putnext(prus->q, dup_mp);		} else {		    dup_mp = prepend_udind(prus, dup_mp, proto);		    putnext(prus->q, dup_mp);		}	    } else {		DPRINT("ppp_urput: data to promisc q dropped\n");		freemsg(dup_mp);	    }	}    }}#endif /* defined(SOL2) *//* * We simply put the message on to the associated upper control stream * (either here or in ppplrsrv).  That way we enter the perimeters * before looking through the list of attached streams to decide which * stream it should go up. */static intppplrput(q, mp)    queue_t *q;    mblk_t *mp;{    queue_t *uq;    struct iocblk *iop;    switch (mp->b_datap->db_type) {    case M_IOCTL:	iop = (struct iocblk *) mp->b_rptr;	iop->ioc_error = EINVAL;	mp->b_datap->db_type = M_IOCNAK;	qreply(q, mp);	return 0;    case M_FLUSH:	if (*mp->b_rptr & FLUSHR)	    flushq(q, FLUSHDATA);	if (*mp->b_rptr & FLUSHW) {	    *mp->b_rptr &= ~FLUSHR;	    qreply(q, mp);	} else	    freemsg(mp);	return 0;    }    /*     * If we can't get the lower lock straight away, queue this one     * rather than blocking, to avoid the possibility of deadlock.     */    if (!TRYLOCK_LOWER_R) {	putq(q, mp);	return 0;    }    /*     * Check that we're still connected to the driver.     */    uq = (queue_t *) q->q_ptr;    if (uq == 0) {	UNLOCK_LOWER;	DPRINT1("ppplrput: q = %x, uq = 0??\n", q);	freemsg(mp);	return 0;    }    /*     * Try to forward the message to the put routine for the upper     * control stream for this lower stream.     * If there are already messages queued here, queue this one so     * they don't get out of order.     */    if (queclass(mp) == QPCTL || (qsize(q) == 0 && canput(uq)))	put(uq, mp);    else	putq(q, mp);    UNLOCK_LOWER;    return 0;}static intppplrsrv(q)    queue_t *q;{    mblk_t *mp;    queue_t *uq;    /*     * Packets get queued here for flow control reasons     * or if the lrput routine couldn't get the lower lock     * without blocking.     */    LOCK_LOWER_R;    uq = (queue_t *) q->q_ptr;    if (uq == 0) {	UNLOCK_LOWER;	flushq(q, FLUSHALL);	DPRINT1("ppplrsrv: q = %x, uq = 0??\n", q);	return 0;    }    while ((mp = getq(q)) != 0) {	if (queclass(mp) == QPCTL || canput(uq))	    put(uq, mp);	else {	    putbq(q, mp);	    break;	}    }    UNLOCK_LOWER;    return 0;}static intputctl2(q, type, code, val)    queue_t *q;    int type, code, val;{    mblk_t *mp;    mp = allocb(2, BPRI_HI);    if (mp == 0)	return 0;    mp->b_datap->db_type = type;    mp->b_wptr[0] = code;    mp->b_wptr[1] = val;    mp->b_wptr += 2;    putnext(q, mp);    return 1;}static intputctl4(q, type, code, val)    queue_t *q;    int type, code, val;{    mblk_t *mp;    mp = allocb(4, BPRI_HI);    if (mp == 0)	return 0;    mp->b_datap->db_type = type;    mp->b_wptr[0] = code;    ((short *)mp->b_wptr)[1] = val;    mp->b_wptr += 4;    putnext(q, mp);    return 1;}static voiddebug_dump(q, mp)    queue_t *q;    mblk_t *mp;{    upperstr_t *us;    queue_t *uq, *lq;    DPRINT("ppp upper streams:\n");    for (us = minor_devs; us != 0; us = us->nextmn) {	uq = us->q;	DPRINT3(" %d: q=%x rlev=%d",		us->mn, uq, (uq? qsize(uq): 0));	DPRINT3(" wlev=%d flags=0x%b", (uq? qsize(WR(uq)): 0),		us->flags, "\020\1priv\2control\3blocked\4last");	DPRINT3(" state=%x sap=%x req_sap=%x", us->state, us->sap,		us->req_sap);	if (us->ppa == 0)	    DPRINT(" ppa=?\n");	else	    DPRINT1(" ppa=%d\n", us->ppa->ppa_id);	if (us->flags & US_CONTROL) {	    lq = us->lowerq;	    DPRINT3("    control for %d lq=%x rlev=%d",		    us->ppa_id, lq, (lq? qsize(RD(lq)): 0));	    DPRINT3(" wlev=%d mru=%d mtu=%d\n",		    (lq? qsize(lq): 0), us->mru, us->mtu);	}    }    mp->b_datap->db_type = M_IOCACK;    qreply(q, mp);}#ifdef FILTER_PACKETS#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <netinet/tcp.h>#define MAX_IPHDR    128     /* max TCP/IP header size *//* The following table contains a hard-coded list of protocol/port pairs. * Any matching packets are either discarded unconditionally, or,  * if ok_if_link_up is non-zero when a connection does not currently exist * (i.e., they go through if the connection is present, but never initiate * a dial-out). * This idea came from a post by dm@garage.uun.org (David Mazieres) */static struct pktfilt_tab { 	int proto; 	u_short port; 	u_short ok_if_link_up; } pktfilt_tab[] = {	{ IPPROTO_UDP,	520,	1 },	/* RIP, ok to pass if link is up */	{ IPPROTO_UDP,	123,	1 },	/* NTP, don't keep up the link for it */	{ -1, 		0,	0 }	/* terminator entry has port == -1 */};static intip_hard_filter(us, mp, outbound)    upperstr_t *us;    mblk_t *mp;    int outbound;{    struct ip *ip;    struct pktfilt_tab *pft;    mblk_t *temp_mp;    int proto;    int len, hlen;    /* Note, the PPP header has already been pulled up in all cases */    proto = PPP_PROTOCOL(mp->b_rptr);    if (us->flags & US_DBGLOG)        DPRINT3("ppp/%d: filter, proto=0x%x, out=%d\n", us->mn, proto, outbound);    switch (proto)    {    case PPP_IP:	if ((mp->b_wptr - mp->b_rptr) == PPP_HDRLEN && mp->b_cont != 0) {	    temp_mp = mp->b_cont;    	    len = msgdsize(temp_mp);	    hlen = (len < MAX_IPHDR) ? len : MAX_IPHDR;	    PULLUP(temp_mp, hlen);	    if (temp_mp == 0) {		DPRINT2("ppp/%d: filter, pullup next failed, len=%d\n", 			us->mn, hlen);		mp->b_cont = 0;		/* PULLUP() freed the rest */	        freemsg(mp);	        return 0;	    }	    ip = (struct ip *)mp->b_cont->b_rptr;	}	else {	    len = msgdsize(mp);	    hlen = (len < (PPP_HDRLEN+MAX_IPHDR)) ? len : (PPP_HDRLEN+MAX_IPHDR);	    PULLUP(mp, hlen);	    if (mp == 0) {		DPRINT2("ppp/%d: filter, pullup failed, len=%d\n", 			us->mn, hlen);	        return 0;	    }	    ip = (struct ip *)(mp->b_rptr + PPP_HDRLEN);	}	/* For IP traffic, certain packets (e.g., RIP) may be either	 *   1.  ignored - dropped completely	 *   2.  will not initiate a connection, but	 *       will be passed if a connection is currently up.	 */	for (pft=pktfilt_tab; pft->proto != -1; pft++) {	    if (ip->ip_p == pft->proto) {		switch(pft->proto) {		case IPPROTO_UDP:		    if (((struct udphdr *) &((int *)ip)[ip->ip_hl])->uh_dport				== htons(pft->port)) goto endfor;		    break;		case IPPROTO_TCP:		    if (((struct tcphdr *) &((int *)ip)[ip->ip_hl])->th_dport				== htons(pft->port)) goto endfor;		    break;		}		    }	}	endfor:	if (pft->proto != -1) {	    if (us->flags & US_DBGLOG)		DPRINT3("ppp/%d: found IP pkt, proto=0x%x (%d)\n", 				us->mn, pft->proto, pft->port);	    /* Discard if not connected, or if not pass_with_link_up */	    /* else, if link is up let go by, but don't update time */	    return pft->ok_if_link_up? -1: 0;	}        break;    } /* end switch (proto) */    return 1;}#endif /* FILTER_PACKETS */

⌨️ 快捷键说明

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