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

📄 if_ppp.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	    snit_intr(ifp, mb, &nif);	}#endif/* * For Digital UNIX, there's space set aside in the header mbuf * for the interface info. * * For Sun it's smuggled around via a pointer at the front of the mbuf. */#ifdef __osf__        mb->m_pkthdr.rcvif = ifp;        mb->m_pkthdr.len = len;#else	mb->m_off -= sizeof(struct ifnet *);	mb->m_len += sizeof(struct ifnet *);	*mtod(mb, struct ifnet **) = ifp;#endif	inq = 0;	switch (proto) {	case PPP_IP:	    inq = &ipintrq;	    schednetisr(NETISR_IP);	}	if (inq != 0) {	    s = splhigh();	    if (IF_QFULL(inq)) {		IF_DROP(inq);		++ifp->if_ierrors;		if (sp->flags & DBGLOG)		    printf("if_ppp: inq full, proto=%x\n", proto);		m_freem(mb);	    } else {		IF_ENQUEUE(inq, mb);	    }	    splx(s);	} else {	    if (sp->flags & DBGLOG)		printf("if_ppp%d: proto=%x?\n", ifp->if_unit, proto);	    ++ifp->if_ierrors;	    m_freem(mb);	}	break;    default:	putnext(q, mp);    }    return 0;}/* * Network code wants to output a packet. * Turn it into a STREAMS message and send it down. */static intif_ppp_output(ifp, m0, dst)    struct ifnet *ifp;    struct mbuf *m0;    struct sockaddr *dst;{    mblk_t *mp;    int proto, s;    if_ppp_t *sp;    u_char *p;    if ((ifp->if_flags & IFF_UP) == 0) {	m_freem(m0);	return ENETDOWN;    }    if ((unsigned)ifp->if_unit >= ppp_nalloc) {#ifdef DEBUG	printf("if_ppp_output: unit %d?\n", ifp->if_unit);#endif	m_freem(m0);	return EINVAL;    }    sp = states[ifp->if_unit];    if (sp == 0) {#ifdef DEBUG	printf("if_ppp_output: no queue?\n");#endif	m_freem(m0);	return ENETDOWN;    }    if (sp->flags & DBGLOG) {	p = mtod(m0, u_char *);	printf("if_ppp_output%d: af=%d data=%x %x %x %x %x %x %x %x q=%x\n",	       ifp->if_unit, dst->sa_family, p[0], p[1], p[2], p[3], p[4],	       p[5], p[6], p[7], sp->q);    }    switch (dst->sa_family) {    case AF_INET:	proto = PPP_IP;#ifdef SNIT_SUPPORT	if (ifp->if_flags & IFF_PROMISC) {	    struct nit_if nif;	    struct mbuf *m;	    int len;	    for (len = 0, m = m0; m != NULL; m = m->m_next)		len += m->m_len;	    nif.nif_header = (caddr_t) &snit_ehdr;	    nif.nif_hdrlen = sizeof(snit_ehdr);	    nif.nif_bodylen = len;	    nif.nif_promisc = 0;	    snit_intr(ifp, m0, &nif);	}#endif	break;    default:	m_freem(m0);	return EAFNOSUPPORT;    }    ++ifp->if_opackets;    mp = make_message(m0, PPP_HDRLEN);    m_freem(m0);    if (mp == 0) {	++ifp->if_oerrors;	return ENOBUFS;    }    mp->b_rptr -= PPP_HDRLEN;    mp->b_rptr[0] = PPP_ALLSTATIONS;    mp->b_rptr[1] = PPP_UI;    mp->b_rptr[2] = proto >> 8;    mp->b_rptr[3] = proto;    s = splstr();    if (sp->flags & DBGLOG)	printf("if_ppp: putnext(%x, %x), r=%x w=%x p=%x\n",	       sp->q, mp, mp->b_rptr, mp->b_wptr, proto);    putnext(sp->q, mp);    splx(s);    return 0;}/* * Socket ioctl routine for ppp interfaces. */static intif_ppp_ioctl(ifp, cmd, data)    struct ifnet *ifp;    u_int cmd;    caddr_t data;{    int s, error;    struct ifreq *ifr = (struct ifreq *) data;    struct ifaddr *ifa = (struct ifaddr *) data;    u_short mtu;    error = 0;    s = splimp();    switch (cmd) {    case SIOCSIFFLAGS:	if ((ifp->if_flags & IFF_RUNNING) == 0)	    ifp->if_flags &= ~IFF_UP;	break;    case SIOCSIFADDR:	if (IFA_ADDR(ifa).sa_family != AF_INET)	    error = EAFNOSUPPORT;	break;    case SIOCSIFDSTADDR:	if (IFA_ADDR(ifa).sa_family != AF_INET)	    error = EAFNOSUPPORT;	break;    case SIOCSIFMTU:	if ((error = NOTSUSER()) != 0)	    break;#ifdef __osf__	/* this hack is necessary because ifioctl checks ifr_data	 * in 4.0 and 5.0, but ifr_data and ifr_metric overlay each 	 * other in the definition of struct ifreq so pppd can't set both.	 */        bcopy(ifr->ifr_data, &mtu, sizeof (u_short));        ifr->ifr_mtu = mtu;#endif	if (ifr->ifr_mtu < PPP_MINMTU || ifr->ifr_mtu > PPP_MAXMTU) {	    error = EINVAL;	    break;	}	ifp->if_mtu = ifr->ifr_mtu;	break;    case SIOCGIFMTU:	ifr->ifr_mtu = ifp->if_mtu;	break;    case SIOCADDMULTI:    case SIOCDELMULTI:	switch(ifr->ifr_addr.sa_family) {	case AF_INET:	    break;	default:	    error = EAFNOSUPPORT;	    break;	}	break;    default:	error = EINVAL;    }    splx(s);    return (error);}/* * Turn a STREAMS message into an mbuf chain. */static struct mbuf *make_mbufs(mp, off)    mblk_t *mp;    int off;{    struct mbuf *head, **prevp, *m;    int len, space, n;    unsigned char *cp, *dp;    len = msgdsize(mp);    if (len == 0)	return 0;    prevp = &head;    space = 0;    cp = mp->b_rptr;#ifdef __osf__    MGETHDR(m, M_DONTWAIT, MT_DATA);    m->m_len = 0;    space = MHLEN;    *prevp = m;    prevp = &m->m_next;    dp = mtod(m, unsigned char *);    len -= space;    off = 0;#endif    for (;;) {	while (cp >= mp->b_wptr) {	    mp = mp->b_cont;	    if (mp == 0) {		*prevp = 0;		return head;	    }	    cp = mp->b_rptr;	}	n = mp->b_wptr - cp;	if (space == 0) {	    MGET(m, M_DONTWAIT, MT_DATA);	    *prevp = m;	    if (m == 0) {		if (head != 0)		    m_freem(head);		return 0;	    }	    if (len + off > 2 * MLEN) {#ifdef __osf__		MCLGET(m, M_DONTWAIT);#else		MCLGET(m);#endif	    }#ifdef __osf__	    space = ((m->m_flags & M_EXT) ? MCLBYTES : MLEN);#else	    space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;	    m->m_off += off;#endif	    m->m_len = 0;	    len -= space;	    dp = mtod(m, unsigned char *);	    off = 0;	    prevp = &m->m_next;	}	if (n > space)	    n = space;	bcopy(cp, dp, n);	cp += n;	dp += n;	space -= n;	m->m_len += n;    }}/* * Turn an mbuf chain into a STREAMS message. */#define ALLOCB_MAX	4096static mblk_t *make_message(m, off)    struct mbuf *m;    int off;{    mblk_t *head, **prevp, *mp;    int len, space, n, nb;    unsigned char *cp, *dp;    struct mbuf *nm;    len = 0;    for (nm = m; nm != 0; nm = nm->m_next)	len += nm->m_len;    prevp = &head;    space = 0;    cp = mtod(m, unsigned char *);    nb = m->m_len;    for (;;) {	while (nb <= 0) {	    m = m->m_next;	    if (m == 0) {		*prevp = 0;		return head;	    }	    cp = mtod(m, unsigned char *);	    nb = m->m_len;	}	if (space == 0) {	    space = len + off;	    if (space > ALLOCB_MAX)		space = ALLOCB_MAX;	    mp = allocb(space, BPRI_LO);	    *prevp = mp;	    if (mp == 0) {		if (head != 0)		    freemsg(head);		return 0;	    }	    dp = mp->b_rptr += off;	    space -= off;	    len -= space;	    off = 0;	    prevp = &mp->b_cont;	}	n = nb < space? nb: space;	bcopy(cp, dp, n);	cp += n;	dp += n;	nb -= n;	space -= n;	mp->b_wptr = dp;    }}/* * Digital UNIX doesn't allow for removing ifnet structures * from the list.  But then we're not using this as a loadable * module anyway, so that's OK. * * Under SunOS, this should allow the module to be unloaded. * Unfortunately, it doesn't seem to detach all the references, * so your system may well crash after you unload this module :-( */#ifndef __osf__/* * Remove an interface from the system. * This routine contains magic. */#include <net/route.h>#include <netinet/in_pcb.h>#include <netinet/ip_var.h>#include <netinet/tcp.h>#include <netinet/tcp_timer.h>#include <netinet/tcp_var.h>#include <netinet/udp.h>#include <netinet/udp_var.h>static voidppp_if_detach(ifp)    struct ifnet *ifp;{    int s;    struct inpcb *pcb;    struct ifaddr *ifa;    struct in_ifaddr **inap;    struct ifnet **ifpp;    s = splhigh();    /*     * Clear the interface from any routes currently cached in     * TCP or UDP protocol control blocks.     */    for (pcb = tcb.inp_next; pcb != &tcb; pcb = pcb->inp_next)	if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)	    in_losing(pcb);    for (pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next)	if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)	    in_losing(pcb);    /*     * Delete routes through all addresses of the interface.     */    for (ifa = ifp->if_addrlist; ifa != 0; ifa = ifa->ifa_next) {	rtinit(ifa, ifa, SIOCDELRT, RTF_HOST);	rtinit(ifa, ifa, SIOCDELRT, 0);    }    /*     * Unlink the interface's address(es) from the in_ifaddr list.     */    for (inap = &in_ifaddr; *inap != 0; ) {	if ((*inap)->ia_ifa.ifa_ifp == ifp)	    *inap = (*inap)->ia_next;	else	    inap = &(*inap)->ia_next;    }    /*     * Delete the interface from the ifnet list.     */    for (ifpp = &ifnet; (*ifpp) != 0; ) {	if (*ifpp == ifp)	    break;	ifpp = &(*ifpp)->if_next;    }    if (*ifpp == 0)	printf("couldn't find interface ppp%d in ifnet list\n", ifp->if_unit);    else	*ifpp = ifp->if_next;    splx(s);}#endif /* __osf__ */

⌨️ 快捷键说明

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