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

📄 connld.c

📁 7号信令功能代码,为开源代码
💻 C
字号:
/* *  connld.c - unique pipe generator * *  On the first open of this module, a connection to it's stream head *  is made, but nothing else.  On subsequent calls, however, the open *  does the following: *  . generate a unique pipe *  . return one endpoint of the pipe to replace itself, i.e, by returning *    the near endpoint's device number *  . send the far endpoint's file via an M_PASSFP message to the *    the far endpoint of its own pipe, to be picked up via an *    I_RECVFD ioctl. *  Thus, this module can only be pushed on a pipe (not even on *  a single-ended FIFO). * *  Note that this module will never handle message traffic. * *  Copyright (C)  2000  John A. Boyd Jr.  protologos, LLC * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Library General Public *  License as published by the Free Software Foundation; either *  version 2 of the License, or (at your option) any later version. *  *  This library is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *  Library General Public License for more details. *  *  You should have received a copy of the GNU Library General Public *  License along with this library; if not, write to the *  Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge, *  MA 02139, USA. */#ident "@(#) LiS connld.c 1.10 09/24/03"#include <linux/config.h>#include <linux/version.h>#ifdef CONFIG_MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#include <sys/LiS/config.h>#include <sys/stream.h>#include <sys/stropts.h>#include <linux/errno.h>#include <sys/cmn_err.h>#include <sys/LiS/head.h>#include <sys/osif.h>/* *  Some configuration sanity checks */#ifndef CONNLD_#error Not configured#endif#ifndef CONNLD__ID#define CONNLD__ID 0xaabc#endif#define  MOD_ID   CONNLD__ID#define  MOD_NAME "connld"/* *  function prototypes */static int  connld_open(queue_t *, dev_t*, int, int, cred_t *);static int  connld_close(queue_t *, int, cred_t *);static int  connld_wput( queue_t *q, mblk_t *mp );static int  connld_rput( queue_t *q, mblk_t *mp );/* *  module structure */static struct module_info connld_minfo ={     MOD_ID,            /* id */    MOD_NAME,          /* name */    0,                 /* min packet size accepted */    INFPSZ,            /* max packet size accepted */    10240L,            /* highwater mark */    512L               /* lowwater mark */};static struct qinit connld_rinit = {    connld_rput,        /* put */    NULL,               /* service */    connld_open,        /* open */    connld_close,       /* close */    NULL,               /* admin */    &connld_minfo,      /* info */    NULL                /* stat */};static struct qinit connld_winit = {     connld_wput,        /* put */    NULL,               /* service */    NULL,               /* open */    NULL,               /* close */    NULL,               /* admin */    &connld_minfo,      /* info */    NULL                /* stat */};struct streamtab connld_info ={    &connld_rinit,      /* read queue init */    &connld_winit,      /* write queue init */    NULL,               /* lower mux read queue init */    NULL                /* lower mux write queue init */};/* *  open */static int connld_open( q, devp, flag, sflag, credp )queue_t *q;dev_t *devp;int flag, sflag;cred_t *credp;{    stdata_t *head = q->q_str;    if (!head || head->magic != STDATA_MAGIC) {	cmn_err( CE_CONT,		 "connld_open(): bad reference to stream head\n" );	return -EINVAL;    }    if (!F_ISSET(head->sd_flag, STFIFO)) {	cmn_err( CE_CONT,		 "connld_open(): not even a FIFO!!\n" );	return -EPIPE;    }    if (!head->sd_peer || head->sd_peer == head) {	cmn_err( CE_CONT,		 "connld_open(): this STREAM just is a FIFO, not a pipe\n" );	return -EPIPE;    }#ifdef DEBUG    cmn_err(	CE_CONT,	"connld_open(q@0x%p, 0x%x, 0x%x,0x%x, ...)#%d "	"h@0x%p/%d/%d f@0x%p/%d\n",	q, *devp, flag, sflag, (int)q->q_ptr,	head,	(head?LIS_SD_REFCNT(head):0), (head?LIS_SD_OPENCNT(head):0),	head->sd_file,	(head->sd_file?F_COUNT(head->sd_file):0) );#endif    if (q->q_ptr) {	struct file *f0, *f1, *oldf = head->sd_file;	int error;	if (head != FILE_STR(oldf)) {	    cmn_err( CE_CONT,		     "connld_open(): invalid sd_file 0x%p\n", head->sd_file );	    return -EINVAL;	}#ifdef DEBUG	cmn_err( CE_CONT,		 "connld_open(): opening file@0x%p/%d - creating pipe...\n",		 oldf,		 (oldf?F_COUNT(oldf):0) );#endif		if ((error = lis_get_pipe( &f0, &f1 )) < 0) {	    cmn_err( CE_CONT,		     "connld_open(): get_pipe() failed: %d\n", error );	    return error;	}#ifdef DEBUG	cmn_err( CE_CONT,		 "connld_open(...)"		 " >> pipe 0x%x(h@0x%p/%d/%d) <=X=> 0x%x(h@0x%p/%d/%d)\n",		 FILE_INODE(f0)->i_rdev,		 FILE_STR(f0),		 LIS_SD_REFCNT(FILE_STR(f0)), LIS_SD_OPENCNT(FILE_STR(f0)),		 FILE_INODE(f1)->i_rdev,		 FILE_STR(f1),		 LIS_SD_REFCNT(FILE_STR(f1)), LIS_SD_OPENCNT(FILE_STR(f1))		 );#endif		/*	 *  send one of the new pipe's ends to the peer of the connld pipe	 */	if ((error = lis_sendfd( head, -1, f1 )) < 0) {	    cmn_err( CE_CONT,		     "connld_open(): sendfd(h@0x%p,-1,f@0x%p) failed - %d\n",		     head, f1, error );	    lis_strclose( FILE_INODE(f0), f0 );	    lis_strclose( FILE_INODE(f1), f1 );	    return error;	}	/*	 *  replace the current opening file's inode	 */	if (!lis_old_inode( oldf, FILE_INODE(f0) )) {	    lis_strclose( FILE_INODE(f0), f0 );	    return -EINVAL;	}	/*	 *  we now have an unused file pointer to the new pipe end (f0)	 *  we must discard, and we need to get all the reference counts	 *  right for both the original and the new pipe end (net change:	 *  old pipe end: refcnt--, new pipe end: opencnt--) so that	 *  the stropen in progress will finish appropriately using the	 *  new pipe end, with the original left as if no open was even	 *  attempted.	 *	 *  FIXME: stropen() is holding head->sd_opening when it calls	 *  open_mods(), which gets us here, but doclose also tries to	 *  hold it.  To prevent a deadlock, I'm switching the lock here	 *  from the old head to the new one, leaving it open during the	 *  intervening fput(), but it might be better to have stropen	 *  call open_mods() with no locks held...  Dave?... - JB 12/6/02	 */		{	    struct stdata *oldhead = head;	    *devp = KDEV_TO_INT(FILE_INODE(f0)->i_rdev);	    lis_atomic_dec(&oldhead->sd_refcnt);	    head = FILE_STR(f0);	    SET_FILE_STR(oldf, head);	    lis_up(&oldhead->sd_opening);        /* release this before fput */	    lis_atomic_inc(&head->sd_refcnt);	    lis_atomic_inc(&head->sd_opencnt);   /* prevent opencnt->0 */	    fput(f0);                            /* calls strclose */	    lis_atomic_dec(&head->sd_opencnt);	    lis_down(&head->sd_opening);#ifdef DEBUG	    cmn_err( CE_CONT,		     "connld_open(...)"		     " >> replaced h@0x%p/--%d/%d -> h@0x%p/%d/--%d\n",		     oldhead,		     LIS_SD_REFCNT(oldhead), LIS_SD_OPENCNT(oldhead),		     head,		     LIS_SD_REFCNT(head), LIS_SD_OPENCNT(head));#endif	}#ifdef DEBUG	cmn_err(	    CE_CONT,	    "connld_open(q@0x%xp, 0x%x, 0x%x,0x%x, ...)#%d "	    "head@0x%p/%d/%d OK\n",	    q, *devp, flag, sflag, (int)q->q_ptr,	    head, LIS_SD_REFCNT(head), LIS_SD_OPENCNT(head) );#endif	return 0;    } else {	/*	 *  first time in - check STCONNLD flag, then set it	 */	if (F_ISSET(head->sd_flag,STCONNLD)) {	    cmn_err( CE_CONT,		     "connld_open(): previously pushed 'connld'\n" );	    return -EINVAL;	}	SET_SD_FLAG(head,STCONNLD);	/*	 *  set q_ptr as an open count flag	 */	((char *)q->q_ptr)++;	MOD_INC_USE_COUNT;    	return 0;    }}/* *  close */static int connld_close( q, flag, credp )queue_t *q;int flag;cred_t *credp;{    stdata_t *head = q->q_str;#ifdef DEBUG    cmn_err( CE_CONT,	     "connld_close(q@0x%p, 0x%x, ...) head 0x%p\n",	     q, flag, head );#endif    q->q_ptr = NULL;#ifdef MODULE    MOD_DEC_USE_COUNT;#endif    qprocsoff(q);	    if (!head || head->magic != STDATA_MAGIC) {	cmn_err( CE_CONT,		 "connld_open(): bad reference to stream head\n" );	return -EINVAL;    }    CLR_SD_FLAG(head,STCONNLD);    return 0;} /* *  wput */static int connld_wput( queue_t *q, mblk_t *mp ){    /*     *  connld is a module, but will at the bottom of a STREAM,     *  like a driver.  Thus, IOCTLs must be NAK'ed, like a driver,     *  not passed down, like a module.  Otherwise, STREAMS might     *  hang waiting for the IOCTL response message.     *     *  connld should not be expected to process any other message     *  traffic, so we discard all other messages.     */    switch (mp->b_datap->db_type) {    case M_IOCTL:	if (q->q_next && SAMESTR(q->q_next)) {	    putnext( q, mp );	} else {	    mp->b_datap->db_type = M_IOCNAK;	    qreply( q, mp );	}	break;    default:#ifdef DEBUG	cmn_err( CE_CONT,		 "connld_wput(q@0x%p,m@0x%p) message discarded\n",		 q, mp );#endif	freemsg(mp);	break;    }    return 0;}/* *  rput */static int connld_rput( queue_t *q, mblk_t *mp ){    putnext( q, mp );    return 0;}#ifdef MODULE/* *  Linux loadable module interface */int init_module(void){    int ret = lis_register_strmod( &connld_info, MOD_NAME );    if (ret < 0) {	cmn_err( CE_CONT,		 "%s - unable to register module.\n",		 MOD_NAME );	return ret;    }    return 0;}void cleanup_module(void){    if (lis_unregister_strmod(&connld_info) < 0)	cmn_err( CE_CONT,		 "%s - unable to unregister module.\n",		 MOD_NAME );    return;}#endif#if defined(LINUX)			/* linux kernel */#if defined(MODULE_LICENSE)MODULE_LICENSE("GPL and additional rights");#endif#if defined(MODULE_AUTHOR)MODULE_AUTHOR("John A. Boyd Jr");#endif#if defined(MODULE_DESCRIPTION)MODULE_DESCRIPTION("STREAMS unique pipe generator");#endif#endif

⌨️ 快捷键说明

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