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

📄 ppp.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	     * to their DL_INFO_REQ.  Fortunately, they will update the	     * MTU if we send an unsolicited DL_INFO_ACK up.	     */	    if ((mq = allocb(sizeof(dl_info_req_t), BPRI_HI)) == 0)		break;		/* should do bufcall */	    ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;	    mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);	    dlpi_request(q, mq, us);	    error = 0;	    break;	case SIOCGIFNETMASK:	case SIOCSIFNETMASK:	case SIOCGIFADDR:	case SIOCGIFDSTADDR:	case SIOCSIFDSTADDR:	case SIOCGIFMETRIC:	    error = 0;	    break;#endif /* LACHTCP */	default:	    if (us->ppa == 0 || us->ppa->lowerq == 0)		break;	    us->ioc_id = iop->ioc_id;	    error = -1;	    switch (iop->ioc_cmd) {	    case PPPIO_GETSTAT:	    case PPPIO_GETCSTAT:		if (us->flags & US_LASTMOD) {		    error = EINVAL;		    break;		}		putnext(us->ppa->lowerq, mp);		break;	    default:		if (us->flags & US_PRIV)		    putnext(us->ppa->lowerq, mp);		else {		    DPRINT1("ppp ioctl %x rejected\n", iop->ioc_cmd);		    error = EPERM;		}		break;	    }	    break;	}	if (error > 0) {	    iop->ioc_error = error;	    mp->b_datap->db_type = M_IOCNAK;	    qreply(q, mp);	} else if (error == 0) {	    mp->b_datap->db_type = M_IOCACK;	    qreply(q, mp);	}	break;    case M_FLUSH:	if (us->flags & US_DBGLOG)	    DPRINT2("ppp/%d: flush %x\n", us->mn, *mp->b_rptr);	if (*mp->b_rptr & FLUSHW)	    flushq(q, FLUSHDATA);	if (*mp->b_rptr & FLUSHR) {	    *mp->b_rptr &= ~FLUSHW;	    qreply(q, mp);	} else	    freemsg(mp);	break;    default:	freemsg(mp);	break;    }    return 0;}#ifndef NO_DLPIstatic voiddlpi_request(q, mp, us)    queue_t *q;    mblk_t *mp;    upperstr_t *us;{    union DL_primitives *d = (union DL_primitives *) mp->b_rptr;    int size = mp->b_wptr - mp->b_rptr;    mblk_t *reply, *np;    upperstr_t *ppa, *os;    int sap, len;    dl_info_ack_t *info;    dl_bind_ack_t *ackp;#if DL_CURRENT_VERSION >= 2    dl_phys_addr_ack_t	*paddrack;    static struct ether_addr eaddr = {0};#endif    if (us->flags & US_DBGLOG)	DPRINT3("ppp/%d: dlpi prim %x len=%d\n", us->mn,		d->dl_primitive, size);    switch (d->dl_primitive) {    case DL_INFO_REQ:	if (size < sizeof(dl_info_req_t))	    goto badprim;	if ((reply = allocb(sizeof(dl_info_ack_t), BPRI_HI)) == 0)	    break;		/* should do bufcall */	reply->b_datap->db_type = M_PCPROTO;	info = (dl_info_ack_t *) reply->b_wptr;	reply->b_wptr += sizeof(dl_info_ack_t);	bzero((caddr_t) info, sizeof(dl_info_ack_t));	info->dl_primitive = DL_INFO_ACK;	info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;	info->dl_min_sdu = 1;	info->dl_addr_length = sizeof(uint);	info->dl_mac_type = DL_ETHER;	/* a bigger lie */	info->dl_current_state = us->state;	info->dl_service_mode = DL_CLDLS;	info->dl_provider_style = DL_STYLE2;#if DL_CURRENT_VERSION >= 2	info->dl_sap_length = sizeof(uint);	info->dl_version = DL_CURRENT_VERSION;#endif	qreply(q, reply);	break;    case DL_ATTACH_REQ:	if (size < sizeof(dl_attach_req_t))	    goto badprim;	if (us->state != DL_UNATTACHED || us->ppa != 0) {	    dlpi_error(q, us, DL_ATTACH_REQ, DL_OUTSTATE, 0);	    break;	}	for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)	    if (ppa->ppa_id == d->attach_req.dl_ppa)		break;	if (ppa == 0) {	    dlpi_error(q, us, DL_ATTACH_REQ, DL_BADPPA, 0);	    break;	}	us->ppa = ppa;	qwriter(q, mp, attach_ppa, PERIM_OUTER);	return;    case DL_DETACH_REQ:	if (size < sizeof(dl_detach_req_t))	    goto badprim;	if (us->state != DL_UNBOUND || us->ppa == 0) {	    dlpi_error(q, us, DL_DETACH_REQ, DL_OUTSTATE, 0);	    break;	}	qwriter(q, mp, detach_ppa, PERIM_OUTER);	return;    case DL_BIND_REQ:	if (size < sizeof(dl_bind_req_t))	    goto badprim;	if (us->state != DL_UNBOUND || us->ppa == 0) {	    dlpi_error(q, us, DL_BIND_REQ, DL_OUTSTATE, 0);	    break;	}#if 0	/* apparently this test fails (unnecessarily?) on some systems */	if (d->bind_req.dl_service_mode != DL_CLDLS) {	    dlpi_error(q, us, DL_BIND_REQ, DL_UNSUPPORTED, 0);	    break;	}#endif	/* saps must be valid PPP network protocol numbers,	   except that we accept ETHERTYPE_IP in place of PPP_IP. */	sap = d->bind_req.dl_sap;	us->req_sap = sap;#if defined(SOL2)	if (us->flags & US_DBGLOG)	    DPRINT2("DL_BIND_REQ: ip gives sap = 0x%x, us = 0x%x", sap, us);	if (sap == ETHERTYPE_IP)	    /* normal IFF_IPV4 */	    sap = PPP_IP;	else if (sap == ETHERTYPE_IPV6)	    /* when IFF_IPV6 is set */	    sap = PPP_IPV6;	else if (sap == ETHERTYPE_ALLSAP)   /* snoop gives sap of 0 */	    sap = PPP_ALLSAP;	else {	    DPRINT2("DL_BIND_REQ: unrecognized sap = 0x%x, us = 0x%x", sap, us);	    dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);	    break;	}#else	if (sap == ETHERTYPE_IP)	    sap = PPP_IP;	if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {	    dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);	    break;	}#endif /* defined(SOL2) */	/* check that no other stream is bound to this sap already. */	for (os = us->ppa; os != 0; os = os->next)	    if (os->sap == sap)		break;	if (os != 0) {	    dlpi_error(q, us, DL_BIND_REQ, DL_NOADDR, 0);	    break;	}	us->sap = sap;	us->state = DL_IDLE;	if ((reply = allocb(sizeof(dl_bind_ack_t) + sizeof(uint),			    BPRI_HI)) == 0)	    break;		/* should do bufcall */	ackp = (dl_bind_ack_t *) reply->b_wptr;	reply->b_wptr += sizeof(dl_bind_ack_t) + sizeof(uint);	reply->b_datap->db_type = M_PCPROTO;	bzero((caddr_t) ackp, sizeof(dl_bind_ack_t));	ackp->dl_primitive = DL_BIND_ACK;	ackp->dl_sap = sap;	ackp->dl_addr_length = sizeof(uint);	ackp->dl_addr_offset = sizeof(dl_bind_ack_t);	*(uint *)(ackp+1) = sap;	qreply(q, reply);	break;    case DL_UNBIND_REQ:	if (size < sizeof(dl_unbind_req_t))	    goto badprim;	if (us->state != DL_IDLE) {	    dlpi_error(q, us, DL_UNBIND_REQ, DL_OUTSTATE, 0);	    break;	}	us->sap = -1;	us->state = DL_UNBOUND;#ifdef LACHTCP	us->ppa->ifstats.ifs_active = 0;#endif	dlpi_ok(q, DL_UNBIND_REQ);	break;    case DL_UNITDATA_REQ:	if (size < sizeof(dl_unitdata_req_t))	    goto badprim;	if (us->state != DL_IDLE) {	    dlpi_error(q, us, DL_UNITDATA_REQ, DL_OUTSTATE, 0);	    break;	}	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 > ppa->mtu) {	    DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);	    break;	}#if defined(SOL2)	/*	 * Should there be any promiscuous stream(s), send the data	 * up for each promiscuous stream that we recognize.	 */	if (mp->b_cont)	    promisc_sendup(ppa, mp->b_cont, us->sap, 0);#endif /* defined(SOL2) */	mp->b_band = 0;#ifdef PRIOQ        /* Extract s_port & d_port from IP-packet, the code is a bit           dirty here, but so am I, too... */        if (mp->b_datap->db_type == M_PROTO && us->sap == PPP_IP	    && mp->b_cont != 0) {	    u_char *bb, *tlh;	    int iphlen, len;	    u_short *ptr;	    u_char band_unset, cur_band, syn;	    u_short s_port, d_port;            bb = mp->b_cont->b_rptr; /* bb points to IP-header*/	    len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;            syn = 0;	    s_port = IPPORT_DEFAULT;	    d_port = IPPORT_DEFAULT;	    if (len >= 20) {	/* 20 = minimum length of IP header */		iphlen = (bb[0] & 0x0f) * 4;		tlh = bb + iphlen;		len -= iphlen;		switch (bb[9]) {		case IPPROTO_TCP:		    if (len >= 20) {	      /* min length of TCP header */			s_port = (tlh[0] << 8) + tlh[1];			d_port = (tlh[2] << 8) + tlh[3];			syn = tlh[13] & 0x02;		    }		    break;		case IPPROTO_UDP:		    if (len >= 8) {	      /* min length of UDP header */			s_port = (tlh[0] << 8) + tlh[1];			d_port = (tlh[2] << 8) + tlh[3];		    }		    break;		}	    }            /*	     * Now calculate b_band for this packet from the	     * port-priority table.	     */            ptr = prioq_table;            cur_band = max_band;            band_unset = 1;            while (*ptr) {                while (*ptr && band_unset)                    if (s_port == *ptr || d_port == *ptr++) {                        mp->b_band = cur_band;                        band_unset = 0;                        break;		    }                ptr++;                cur_band--;	    }            if (band_unset)		mp->b_band = def_band;            /* It may be usable to urge SYN packets a bit */            if (syn)		mp->b_band++;	}#endif	/* PRIOQ */	/* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */	if (mp->b_datap->db_ref > 1) {	    np = allocb(PPP_HDRLEN, BPRI_HI);	    if (np == 0)		break;		/* gak! */	    np->b_cont = mp->b_cont;	    mp->b_cont = 0;	    freeb(mp);	    mp = np;	} else	    mp->b_datap->db_type = M_DATA;	/* XXX should use dl_dest_addr_offset/length here,	   but we would have to translate ETHERTYPE_IP -> PPP_IP */	mp->b_wptr = mp->b_rptr + PPP_HDRLEN;	mp->b_rptr[0] = PPP_ALLSTATIONS;	mp->b_rptr[1] = PPP_UI;	mp->b_rptr[2] = us->sap >> 8;	mp->b_rptr[3] = us->sap;	if (pass_packet(us, mp, 1)) {	    if (!send_data(mp, us))		putq(q, mp);	}	return;#if DL_CURRENT_VERSION >= 2    case DL_PHYS_ADDR_REQ:	if (size < sizeof(dl_phys_addr_req_t))	    goto badprim;	/*	 * Don't check state because ifconfig sends this one down too	 */	if ((reply = allocb(sizeof(dl_phys_addr_ack_t)+ETHERADDRL, 			BPRI_HI)) == 0)	    break;		/* should do bufcall */	reply->b_datap->db_type = M_PCPROTO;	paddrack = (dl_phys_addr_ack_t *) reply->b_wptr;	reply->b_wptr += sizeof(dl_phys_addr_ack_t);	bzero((caddr_t) paddrack, sizeof(dl_phys_addr_ack_t)+ETHERADDRL);	paddrack->dl_primitive = DL_PHYS_ADDR_ACK;	paddrack->dl_addr_length = ETHERADDRL;	paddrack->dl_addr_offset = sizeof(dl_phys_addr_ack_t);	bcopy(&eaddr, reply->b_wptr, ETHERADDRL);	reply->b_wptr += ETHERADDRL;	qreply(q, reply);	break;#if defined(SOL2)    case DL_PROMISCON_REQ:	if (size < sizeof(dl_promiscon_req_t))	    goto badprim;	us->flags |= US_PROMISC;	dlpi_ok(q, DL_PROMISCON_REQ);	break;    case DL_PROMISCOFF_REQ:	if (size < sizeof(dl_promiscoff_req_t))	    goto badprim;	us->flags &= ~US_PROMISC;	dlpi_ok(q, DL_PROMISCOFF_REQ);	break;#else    case DL_PROMISCON_REQ:	    /* fall thru */    case DL_PROMISCOFF_REQ:	    /* fall thru */#endif /* defined(SOL2) */#endif /* DL_CURRENT_VERSION >= 2 */#if DL_CURRENT_VERSION >= 2    case DL_SET_PHYS_ADDR_REQ:    case DL_SUBS_BIND_REQ:    case DL_SUBS_UNBIND_REQ:    case DL_ENABMULTI_REQ:    case DL_DISABMULTI_REQ:    case DL_XID_REQ:    case DL_TEST_REQ:    case DL_REPLY_UPDATE_REQ:    case DL_REPLY_REQ:    case DL_DATA_ACK_REQ:#endif    case DL_CONNECT_REQ:    case DL_TOKEN_REQ:	dlpi_error(q, us, d->dl_primitive, DL_NOTSUPPORTED, 0);	break;    case DL_CONNECT_RES:    case DL_DISCONNECT_REQ:    case DL_RESET_REQ:    case DL_RESET_RES:	dlpi_error(q, us, d->dl_primitive, DL_OUTSTATE, 0);	break;    case DL_UDQOS_REQ:	dlpi_error(q, us, d->dl_primitive, DL_BADQOSTYPE, 0);	break;#if DL_CURRENT_VERSION >= 2    case DL_TEST_RES:    case DL_XID_RES:	break;#endif    default:	cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);	/* fall through */    badprim:	dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);	break;    }    freemsg(mp);}static voiddlpi_error(q, us, prim, err, uerr)    queue_t *q;    upperstr_t *us;    int prim, err, uerr;{    mblk_t *reply;    dl_error_ack_t *errp;    if (us->flags & US_DBGLOG)        DPRINT3("ppp/%d: dlpi error, prim=%x, err=%x\n", us->mn, prim, err);    reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);    if (reply == 0)	return;			/* XXX should do bufcall */    reply->b_datap->db_type = M_PCPROTO;    errp = (dl_error_ack_t *) reply->b_wptr;    reply->b_wptr += sizeof(dl_error_ack_t);    errp->dl_primitive = DL_ERROR_ACK;    errp->dl_error_primitive = prim;    errp->dl_errno = err;    errp->dl_unix_errno = uerr;    qreply(q, reply);}static voiddlpi_ok(q, prim)    queue_t *q;    int prim;{    mblk_t *reply;    dl_ok_ack_t *okp;    reply = allocb(sizeof(dl_ok_ack_t), BPRI_HI);    if (reply == 0)	return;			/* XXX should do bufcall */    reply->b_datap->db_type = M_PCPROTO;    okp = (dl_ok_ack_t *) reply->b_wptr;    reply->b_wptr += sizeof(dl_ok_ack_t);    okp->dl_primitive = DL_OK_ACK;    okp->dl_correct_primitive = prim;    qreply(q, reply);}#endif /* NO_DLPI */static intpass_packet(us, mp, outbound)    upperstr_t *us;    mblk_t *mp;    int outbound;{    int pass;    upperstr_t *ppa;    if ((ppa = us->ppa) == 0) {	freemsg(mp);	return 0;    }#ifdef FILTER_PACKETS    pass = ip_hard_filter(us, mp, outbound);#else

⌨️ 快捷键说明

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