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

📄 qif.c

📁 pfil src. solaris, freebsd
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2000, 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * Copyright 2003 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident "@(#)$Id: qif.c,v 1.47 2004/10/28 13:21:32 darrenr Exp $"#include <sys/systm.h>#include <sys/types.h>#include <sys/param.h>#include <sys/errno.h>#include <sys/uio.h>#include <sys/buf.h>#include <sys/ddi.h>#include <sys/sunddi.h>#include <sys/modctl.h>#include <sys/open.h>#include <sys/kmem.h>#include <sys/conf.h>#include <sys/cmn_err.h>#include <sys/stat.h>#include <sys/cred.h>#include <sys/dditypes.h>#include <sys/stream.h>#include <sys/poll.h>#include <sys/autoconf.h>#include <sys/byteorder.h>#include <sys/socket.h>#include <sys/dlpi.h>#include <sys/stropts.h>#include <sys/sockio.h>#include <sys/ethernet.h>#include <net/if.h>#if SOLARIS2 >= 6# include <net/if_types.h># if SOLARIS2 >= 8#  include <netinet/ip6.h># endif# include <net/if_dl.h>#endif#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <inet/common.h>#undef IPOPT_EOL#undef IPOPT_NOP#undef IPOPT_LSRR#undef IPOPT_SSRR#undef IPOPT_RR#include <inet/ip.h>#include <inet/ip_if.h>#include <inet/ip_ire.h>#include "compat.h"#include "qif.h"#include "pfil.h"#if SOLARIS2 >= 6static	size_t	hdrsizes[57][2] = {	{ 0, 0 },	{ IFT_OTHER, 0 },	{ IFT_1822, 0 },	{ IFT_HDH1822, 0 },	{ IFT_X25DDN, 0 },	{ IFT_X25, 0 },	{ IFT_ETHER, 14 },	{ IFT_ISO88023, 0 },	{ IFT_ISO88024, 0 },	{ IFT_ISO88025, 0 },	{ IFT_ISO88026, 0 },	{ IFT_STARLAN, 0 },	{ IFT_P10, 0 },	{ IFT_P80, 0 },	{ IFT_HY, 0 },	{ IFT_FDDI, 24 },	{ IFT_LAPB, 0 },	{ IFT_SDLC, 0 },	{ IFT_T1, 0 },	{ IFT_CEPT, 0 },	{ IFT_ISDNBASIC, 0 },	{ IFT_ISDNPRIMARY, 0 },	{ IFT_PTPSERIAL, 0 },	{ IFT_PPP, 0 },	{ IFT_LOOP, 0 },	{ IFT_EON, 0 },	{ IFT_XETHER, 0 },	{ IFT_NSIP, 0 },	{ IFT_SLIP, 0 },	{ IFT_ULTRA, 0 },	{ IFT_DS3, 0 },	{ IFT_SIP, 0 },	{ IFT_FRELAY, 0 },	{ IFT_RS232, 0 },	{ IFT_PARA, 0 },	{ IFT_ARCNET, 0 },	{ IFT_ARCNETPLUS, 0 },	{ IFT_ATM, 0 },	{ IFT_MIOX25, 0 },	{ IFT_SONET, 0 },	{ IFT_X25PLE, 0 },	{ IFT_ISO88022LLC, 0 },	{ IFT_LOCALTALK, 0 },	{ IFT_SMDSDXI, 0 },	{ IFT_FRELAYDCE, 0 },	{ IFT_V35, 0 },	{ IFT_HSSI, 0 },	{ IFT_HIPPI, 0 },	{ IFT_MODEM, 0 },	{ IFT_AAL5, 0 },	{ IFT_SONETPATH, 0 },	{ IFT_SONETVT, 0 },	{ IFT_SMDSICIP, 0 },	{ IFT_PROPVIRTUAL, 0 },	{ IFT_PROPMUX, 0 },};#endif /* SOLARIS2 >= 6 */#if SOLARIS2 <= 6# include <sys/kmem_impl.h>#endif#if SOLARIS2 >= 10extern krwlock_t ill_g_lock;#endif#define	SAPNAME(x)	((x)->qf_sap == 0x0800 ? "IPv4" : \			 (x)->qf_sap == 0x86dd ? "IPv6" : "??")static	int		qif_num = 0;static	kmem_cache_t	*qif_cache = NULL;qif_t	*qif_head;int	qif_verbose = 0;/* ------------------------------------------------------------------------ *//* Function:    qif_startup                                                 *//* Returns:     int - 0 == success, -1 == failure                           *//* Parameters:  None.                                                       *//*                                                                          *//* Perform any initialisation of data structures related to managing qif's  *//* that is deemed necessary.                                                *//* ------------------------------------------------------------------------ */int qif_startup(){	qif_head = NULL;	qif_cache = kmem_cache_create("qif_head_cache", sizeof(qif_t), 8,				      NULL, NULL, NULL, NULL, NULL, 0);	if (qif_cache == NULL) {		cmn_err(CE_NOTE, "qif_startup:kmem_cache_create failed");		return -1;	}	return 0;}/* ------------------------------------------------------------------------ *//* Function:    qif_stop                                                    *//* Returns:     void                                                        *//* Parameters:  None.                                                       *//*                                                                          *//* Deallocate all qif_t's allocated and clean up any other data structures  *//* required in order to 'shut down' this part of the pfil module.           *//* ------------------------------------------------------------------------ */void qif_stop(){	kmem_cache_destroy(qif_cache);	qif_cache = NULL;}/* ------------------------------------------------------------------------ *//* Function:    q_to_ill                                                    *//* Returns:     void * - NULL == failure, else pointer to ill               *//* Parameters:  rq(I) - pointer to STREAMS read queue                       *//* Locks:       pfil_rw                                                     *//*                                                                          *//* Given a pointer to a queue, try and find the ill which owns it.          *//* ------------------------------------------------------------------------ */void *q_to_ill(rq)queue_t *rq;{	ill_t *ill = NULL;	queue_t *qu, *wq;	wq = OTHERQ(rq);	if (rq) {#if SOLARIS2 >= 10		ill_walk_context_t ctx;		rw_enter(&ill_g_lock, RW_READER);		for (ill = ILL_START_WALK_ALL(&ctx); ill != NULL;		     ill = ill_next(&ctx, ill))#else		for (ill = ill_g_head; ill != NULL; ill = ill->ill_next)#endif		{			if (ill->ill_rq == NULL || ill->ill_wq == NULL)				continue;			if (ill->ill_rq == RD(rq)->q_next)				break;			for (qu = WR(ill->ill_rq); qu; qu = qu->q_next)				if ((qu->q_ptr == rq->q_ptr) || (qu == wq))					break;			if (qu != NULL)				break;			for (qu = ill->ill_rq; qu; qu = qu->q_next)				if (qu->q_ptr == rq->q_ptr)					break;			if (qu != NULL)				break;		}	}#if SOLARIS2 >= 10	rw_exit(&ill_g_lock);#endif	return ill;}/* ------------------------------------------------------------------------ *//* Function:    qif_ire_walker                                              *//* Returns:     void                                                        *//* Parameters:  ire(I) - pointer to an ire_t                                *//*              arg(I) - pointer to a qif                                   *//*                                                                          *//* This function gets called by the ire-walking function for each ire in    *//* table.  We enumerate through the ire looking for cached fastpath headers *//* on a given NIC (the qif) so we can update qf_hl from its size.           *//* ------------------------------------------------------------------------ */voidqif_ire_walker(ire, arg)	ire_t *ire;	void *arg;{	qif_t *qif = arg;	if ((ire->ire_type == IRE_CACHE) &&#if SOLARIS2 >= 6	    (ire->ire_ipif != NULL) &&	    (ire->ire_ipif->ipif_ill == qif->qf_ill)#else	    (ire_to_ill(ire) == qif->qf_ill)#endif	    ) {#if SOLARIS2 >= 8		mblk_t *m = ire->ire_fp_mp;#else		mblk_t *m = ire->ire_ll_hdr_mp;#endif		if (m != NULL)			qif->qf_hl = m->b_wptr - m->b_rptr;	}}/* ------------------------------------------------------------------------ *//* Function:    qif_attach                                                  *//* Returns:     int  - 0 == success, -1 == error in attaching qif_t to q    *//* Parameters:  rq(I) - pointer to STREAMS read queue                       *//*                                                                          *//* Attempt to bind a qif_t structure to a specific interface given the      *//* queue pointer.  Assumes the queue already has a qif_t structure tagged   *//* against it.                                                              *//* ------------------------------------------------------------------------ */intqif_attach(rq)	queue_t *rq;{	packet_filter_hook_t *pfh;	qif_t *qif;	ill_t *ill;	WRITE_ENTER(&pfil_rw);	/*	 * Can we map the queue to a specific ill?  If not, go no futher, we	 * are only interested in being associated with queues that we can	 * recognise as being used for IP communication of some sort.	 */	ill = q_to_ill(rq);	if (ill == NULL) {		if (qif_verbose > 0)			cmn_err(CE_NOTE,				"PFIL: cannot find interface for rq %p",				(void *)rq);		RW_EXIT(&pfil_rw);		return -1;	}	qif = rq->q_ptr;#if SOLARIS2 < 8	qif->qf_hl = ill->ill_hdr_length;#else	if ((ill->ill_type > 0) && (ill->ill_type < 0x37) &&	    (hdrsizes[ill->ill_type][0] == ill->ill_type))		qif->qf_hl = hdrsizes[ill->ill_type][1];	if (qif->qf_hl == 0 && ill->ill_type != IFT_OTHER) {		cmn_err(CE_WARN,			"!Unknown layer 2 header size for %s type %d sap %x\n",			qif->qf_name, ill->ill_type, ill->ill_sap);	}#endif	/*	 * Protect against the qif_t being bound against an interface, twice	 * by getting a lock on setting qf_bound and don't release it until	 * all the information has been set with qf_bound finally set to 1	 * after that.	 */	if (qif->qf_bound == 1) {		RW_EXIT(&pfil_rw);		return 0;	}	qif->qf_sap = ill->ill_sap;	qif->qf_ppa = ill->ill_ppa;#ifdef icmp_nextmtu	qif->qf_max_frag = ill->ill_max_frag;#endif	(void) strncpy(qif->qf_name, ill->ill_name, sizeof(qif->qf_name));	qif->qf_name[sizeof(qif->qf_name) - 1] = '\0';	qif->qf_ill = ill;	qif->qf_bound = 1;	qif_ipmp_syncslave(qif, qif->qf_sap);	RW_EXIT(&pfil_rw);	READ_ENTER(&pfh_sync.ph_lock);	pfh = pfil_hook_get(PFIL_IN, &pfh_sync);	for (; pfh; pfh = pfh->pfil_next)		if (pfh->pfil_func)			(void) (*pfh->pfil_func)(NULL, 0, qif, 0, qif, NULL);	RW_EXIT(&pfh_sync.ph_lock);	if (qif_verbose > 0)		cmn_err(CE_NOTE, "PFIL: attaching [%s] - %s", qif->qf_name,			SAPNAME(qif));#if SOLARIS2 < 6	ire_walk(qif_ire_walker, qif);#else	ire_walk(qif_ire_walker, (char *)qif);#endif	return 0;}/* ------------------------------------------------------------------------ *//* Function:    qif_new                                                     *//* Returns:     qif_t * - NULL == failure, else pointer to qif_t            *//* Parameters:  q(I) - pointer to STREAMS queue                             *//*                                                                          *//* Allocate a new qif struct, give it a unique number and add it to the     *//* list of registered qif_t's for the given queue.  Along the way, if we    *//* find an existing qif_t for this queue, return that instead.              *//* ------------------------------------------------------------------------ */qif_t *qif_new(q, mflags)	queue_t *q;	int mflags;{	qif_t *qif, *qf;	qif = kmem_cache_alloc(qif_cache, mflags);	if (qif == NULL) {		cmn_err(CE_NOTE, "PFIL: malloc(%d) for qif_t failed",			(int)sizeof(qif_t));		return NULL;	}	bzero((char *)qif, sizeof(*qif));	mutex_init(&qif->qf_ptl.pt_lock, NULL, MUTEX_DRIVER, NULL);	cv_init(&qif->qf_ptl.pt_cv, NULL, CV_DRIVER, NULL);	qif->qf_qifsz = sizeof(*qif);	qif->qf_q = q;	qif->qf_oq = OTHERQ(q);	WRITE_ENTER(&pfil_rw);	qif->qf_num = qif_num++;	qif->qf_next = qif_head;	qif_head = qif;	RW_EXIT(&pfil_rw);	(void) sprintf(qif->qf_name, "QIF%x", qif->qf_num);	return qif;}/* ------------------------------------------------------------------------ *//* Function:    qif_delete                                                  *//* Returns:     void                                                        *//* Parameters:  None.                                                       *//*                                                                          *//* Remove a qif structure from the list of recognised qif's.                *//*                                                                          *//* NOTE: The locking structure used here on qif's is to protect their use   *//* by the pkt.c functions for sending out a packet.  It is possible that a  *//* packet will be processed on one queue and need to be output on another   *//* and given we cannot hold a lock across putnext() we need to use a P-V    *//* like algorithm for locking.  The PT_* macros come from the PTY code.     *//* In the fullness of time, this function should be rewritten to make sure  *//* that it is not posible to find the qif before we call the PT_* macros    *//* and call qprocsoff().                                                    *//* ------------------------------------------------------------------------ *//*ARGSUSED*/void qif_delete(qif, q)

⌨️ 快捷键说明

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