📄 qif.c
字号:
/* * 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 + -