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

📄 pfildrv.c

📁 pfil src. solaris, freebsd
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;}/************************************************************************ * STREAMS module functions *//* ------------------------------------------------------------------------ *//* Function:    pfilmodopen                                                 *//* Returns:     int      - 0 == success, else error                         *//* Parameters:  q(I)     - pointer to read-side STREAMS queue               *//*              devp(I)  - pointer to a device number                       *//*              oflag(I) - file status open flags (always 0 for module open)*//*              sflag(I) - flag indicating how the open is being made       *//*              crp(I)   - pointer to message credentials from the user     *//*                                                                          *//* open() entry hook for the STREAMS module.                                *//* ------------------------------------------------------------------------ *//*ARGSUSED*/static int pfilmodopen(queue_t *q, dev_t *devp, int oflag, int sflag,		       cred_t *crp){	/* LINTED: E_CONSTANT_CONDITION */	PRINT(3,(CE_CONT, "!pfilmodopen(%p,%p,%x,%x,%p) [%s]\n",		 (void *)q, (void *)devp, oflag, sflag, (void *)crp, QTONM(q)));	/*	 * As per recommendation on man page open(9e)	 */	if (sflag != MODOPEN)		return ENXIO;	q->q_ptr = qif_new(q, KM_SLEEP);	WR(q)->q_ptr = q->q_ptr;	qprocson(q);	return 0;}/* ------------------------------------------------------------------------ *//* Function:    pfilmodclose                                                *//* Returns:     int     - always returns 0.                                 *//* Parameters:  q(I)    - pointer to read-side STREAMS queue                *//*              flag(I) - file status flag                                  *//*              crp(I)  - pointer to message credentials from the user      *//*                                                                          *//* close() entry hook for the STREAMS module. qif_delete() takes care of    *//* setting q_ptr back to NULL for both this and the write side queue.       *//* ------------------------------------------------------------------------ *//*ARGSUSED*/static int pfilmodclose(queue_t *q, int flag, cred_t *crp){	/* LINTED: E_CONSTANT_CONDITION */	PRINT(3,(CE_CONT, "!pfilmodclose(%p,%x,%p) [%s]\n",		 (void *)q, flag, (void *)crp, QTONM(q)));	qprocsoff(q);	qif_delete(q->q_ptr, q);	return 0;}/************************************************************************ * other support functions *//* ------------------------------------------------------------------------ *//* Function:    pfil_precheck                                               *//* Returns:     int - < 0 pass packet because it's not a type subject to    *//*                    firewall rules (i.e. internal STREAMS messages),      *//*                    0 == pass packet, else > 0 indicates passing          *//*                    prohibited (possibly due to an error occuring in      *//*                    this function.)                                       *//* Parameters:  q(I)   - pointer to STREAMS queue                           *//*              mp(I)  - pointer to STREAMS message                         *//*              qif(I) - pointer to per-queue interface information         *//* Locks:       pfil_rw                                                     *//*                                                                          *//* In here we attempt to determine if there is an IP packet within an mblk  *//* that is being passed along and if there is, ensure that it falls on a 32 *//* bit aligned address and at least all of the layer 3 header is in one     *//* buffer, preferably all the layer 4 too if we recognise it.  Finally, if  *//* we can be sure that the buffer passes some sanity checks, pass it on to  *//* the registered callbacks for the particular protocol/direction.          *//* ------------------------------------------------------------------------ *//*ARGSUSED*/int pfil_precheck(queue_t *q, mblk_t **mp, int flags, qif_t *qif){	register struct ip *ip;	size_t hlen, len, off, mlen, iphlen, plen;	packet_filter_hook_t *pfh;	qpktinfo_t qpkt, *qpi;	struct pfil_head *ph;	mblk_t *m, *mt = *mp;	int err, out, sap;	u_char *bp;#if SOLARIS2 >= 8	ip6_t *ip6;#endif#ifndef	sparc	u_short __ipoff, __iplen;#endif	qpi = &qpkt;	qpi->qpi_q = q;	qpi->qpi_off = 0;	qpi->qpi_name = qif->qf_name;	qpi->qpi_real = qif;	qpi->qpi_ill = qif->qf_ill;	qpi->qpi_hl = qif->qf_hl;	qpi->qpi_ppa = qif->qf_ppa;	qpi->qpi_num = qif->qf_num;	qpi->qpi_flags = qif->qf_flags;	qpi->qpi_max_frag = qif->qf_max_frag;	if ((flags & PFIL_GROUP) != 0)		qpi->qpi_flags |= QF_GROUP;	/*	 * If there is only M_DATA for a packet going out, then any header	 * information (which would otherwise appear in an M_PROTO mblk before	 * the M_DATA) is prepended before the IP header.  We need to set the	 * offset to account for this.	 */	out = (flags & PFIL_OUT) ? 1 : 0;	off = (out) ? qpi->qpi_hl : 0;	ip = NULL;	m = NULL;	/*	 * If the message protocol block indicates that there isn't a data	 * block following it, just return back.	 */	bp = (u_char *)ALIGN32(mt->b_rptr);	switch (MTYPE(mt))	{	case M_PROTO :	case M_PCPROTO :	    {		dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;		if ((dl->dl_primitive != DL_UNITDATA_IND) &&		    (dl->dl_primitive != DL_UNITDATA_REQ)) {			ip = (struct ip *)dl;			if ((ip->ip_v == IPVERSION) &&			    (ip->ip_hl == (sizeof(*ip) >> 2)) &&			    (ntohs(ip->ip_len) == mt->b_wptr - mt->b_rptr)) {				off = 0;				m = mt;			} else {				atomic_add_long(&qif->qf_notdata, 1);				return -1;			}		} else {			m = mt->b_cont;			if (m == NULL) {				atomic_add_long(&qif->qf_nodata, 1);				return -3;	/* No data blocks */			}		}		break;	    }	case M_DATA :		m = mt;		break;	default :		atomic_add_long(&qif->qf_notdata, 1);		return -2;	}	/*	 * Find the first data block, count the data blocks in this chain and	 * the total amount of data.	 */	if (ip == NULL)		for (m = mt; m && (MTYPE(m) != M_DATA); m = m->b_cont)			off = 0;	/* Any non-M_DATA cancels the offset */	if (m == NULL) {		atomic_add_long(&qif->qf_nodata, 1);		return -3;	/* No data blocks */	}	/*	 * This is a complete kludge to try and work around some bizarre	 * packets which drop through into pfil_donotip.	 */	if ((mt != m) && (MTYPE(mt) == M_PROTO || MTYPE(mt) == M_PCPROTO)) {		dl_unitdata_ind_t *dl = (dl_unitdata_ind_t *)bp;		if ((dl->dl_primitive == DL_UNITDATA_IND) &&		    (dl->dl_group_address == 1)) {			qpi->qpi_flags |= QF_GROUP;			if (((*((u_char *)m->b_rptr) == 0x0) &&			    ((*((u_char *)m->b_rptr + 2) == 0x45))))				off += 2;		}	}	/*	 * We might have a 1st data block which is really M_PROTO, i.e. it is	 * only big enough for the link layer header	 */	while ((len = m->b_wptr - m->b_rptr) <= off) {		off -= len;		m = m->b_cont;		if (m == NULL) {			atomic_add_long(&qif->qf_nodata, 1);			return -4;	/* not enough data for IP */		}	}	ip = (struct ip *)(m->b_rptr + off);	len = m->b_wptr - m->b_rptr - off;	mlen = msgdsize(m);	sap = qif->qf_sap;	if (mlen == 0)		mlen = m->b_wptr - m->b_rptr;	mlen -= off;#ifdef PFILDEBUG	/*LINTED: E_CONSTANT_CONDITION*/	PRINT(10,(CE_CONT,		  "!IP Filter[%s]: out %d len %ld/%ld sap %d ip %p b_rptr %p off %ld m %p/%d/%ld/%p mt %p/%d/%ld/%p\n",		  qif->qf_name, out, len, mlen, sap,		  (void *)ip, (void *)m->b_rptr, off, 		  (void *)m, MTYPE(m), MLEN(m), (void *)m->b_cont,		  (void *)mt, MTYPE(mt), MLEN(mt), (void *)mt->b_cont));#endif	/*	 * If there is more than one copy of this message traversing the	 * STREAMS stack (ie the packet is being used for snoop data), the	 * IP header isn't on a 32bit aligned address, or the IP header	 * isn't contain within a single block, then make a copy which	 * meets our requirements and do a freemsg on the one passed in	 * since we're no longer using it or passing it up.	 */	if ((pfil_delayed_copy == 0 && m->b_datap->db_ref > 1)	    || ((u_int)ip & 0x3) || len < sizeof(*ip)	    || (sap != ETHERTYPE_IP#if SOLARIS2 >= 8		&& sap != IP6_DL_SAP#endif	        )) {		mblk_t *b;		mblk_t *nm;		mblk_t *nmt;		mblk_t *previous_nm;forced_copy:		nmt = NULL;		previous_nm = NULL;		/*		 * Duplicate the message block descriptors up to (and		 * including if the offset is non-zero) the block where		 * IP begins.		 */		for (b = mt; b != m || off; b = b->b_cont) {			nm = dupb(b);			if (nm == NULL) {				atomic_add_long(&qif->qf_copyfail, 1);				if (nmt)					freemsg(nmt);				return ENOBUFS;			}			nm->b_cont = NULL;			if (nmt)				linkb(previous_nm, nm);			else				nmt = nm;			previous_nm = nm;			/*			 * Set the length so the block only contains what			 * appears before IP.			 */			if (b == m) {				nm->b_wptr = nm->b_rptr + off;				break;			}		}		m->b_rptr += off;		nm = msgpullup(m, -1);		m->b_rptr -= off;		if (nm == NULL) {			atomic_add_long(&qif->qf_copyfail, 1);			if (nmt)				freemsg(nmt);			return ENOBUFS;		}		if (nmt)			linkb(previous_nm, nm);		else			nmt = nm;		freemsg(mt);		*mp = nmt;		mt = nmt;		m = nm;		ip = (struct ip *)m->b_rptr;		len = m->b_wptr - m->b_rptr;		mlen = len;		off = 0;	}	if (sap == ETHERTYPE_IP) {		u_short tlen;		hlen = sizeof(*ip);		/* XXX - might not be aligned (from ppp?) */		((char *)&tlen)[0] = ((char *)&ip->ip_len)[0];		((char *)&tlen)[1] = ((char *)&ip->ip_len)[1];		plen = ntohs(tlen);		ph = &pfh_inet4;	}#if SOLARIS2 >= 8	else if (sap == IP6_DL_SAP) {		u_short tlen;		hlen = sizeof(ip6_t);		ip6 = (ip6_t *)ip;		/* XXX - might not be aligned (from ppp?) */		((char *)&tlen)[0] = ((char *)&ip6->ip6_plen)[0];		((char *)&tlen)[1] = ((char *)&ip6->ip6_plen)[1];		plen = ntohs(tlen);		if (plen == 0)			return EMSGSIZE;	/* Jumbo gram */		ph = &pfh_inet6;	}#endif 	else {

⌨️ 快捷键说明

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