?? ip_strm_mod.c
字號:
/************************************************************************* ** Gcom DLPI <-> Linux SKBUF Driver ** *************************************************************************** ** Copyright (C) 1995,1996,1997 Gcom, Inc ** ** ** Author: Among others Mikel L. Matthews Gcom, Inc. ** ** Copyright (C) 1997-1999 Mikel Matthews, Gcom, Inc <mikel@gcom.com> ** Dave Grothe, Gcom, Inc <dave@gcom.com> ** *************************************************************************//* * * 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. * * This is a pushable streams module that bridges a DLPI stream to * an IP masquerading as a network driver. * * The way you use it is as follows: * * Open your DLPI stream file. * * Push this module. * * Do DLPI attach and bind. * * Send SIOCSIFNAME ioctl with the desired interface name. * * The ioctl causes the module to register itself with IP as a network * interface driver. * * Do the appropriate ifconfig and route commands. * * You can tear down the IP side by doing ifconfig <name> off. You can * tear down the whole thing by closing the streams file. *//************************************************************************* SCCS ID *************************************************************************** ** The following strings identify this module as to version info. ** *************************************************************************/#ident "@(#) LiS ip_strm_mod.c 2.21 10/09/02 22:08:57 "#include <linux/config.h>#include <linux/version.h>#ifdef CONFIG_MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/timer.h>#include <linux/pci.h>#include <linux/spinlock.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/ioctl.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/net.h>#include <linux/in.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/ethtool.h>#include <linux/delay.h>#include <linux/types.h>#include <linux/if_arp.h>/* * UNIX includes */#include <sys/stream.h>#include <sys/cmn_err.h>#include <sys/dlpi.h>#include <sys/mkdev.h>#include <sys/ddi.h>#include <sys/cred.h>#include <sys/LiS/mod.h>#include "ip_strm_mod.h"#include <sys/osif.h>/************************************************************************* Function Prototypes *************************************************************************//* * Functions in this file */extern int ip_strm_init(struct ism_dev *dev) ;/************************************************************************* Streams Entry Point Routines *************************************************************************** ** The following section of code contains the entry point routines for ** the streams driver. These are the open, close, put and service ** routines pointed to by the qinit structures above. ** *************************************************************************/extern int ip_to_streams_open(queue_t *,dev_t *,int ,int, cred_t *);extern int ip_to_streams_close(queue_t *, int, cred_t *);extern int ip_to_streams_wput(queue_t *,mblk_t *);extern int ip_to_streams_wsrv(queue_t *);extern int ip_to_streams_rput(queue_t *,mblk_t *);extern int ip_to_streams_rsrv(queue_t *);extern int ip_to_streams_conn_req(ip_to_streams_minor_t *minor_ptr, mblk_t *mp, int retry) ;extern int ip_to_streams_proto(ip_to_streams_minor_t *, mblk_t *, int );#ifdef GCOMextern void netman_hex_mp (mblk_t *, char *);extern void Rsys_print_traced_token (char *bufp) ;extern void Rsys_hex_print(char *, unsigned char *, int);#endif/************************************************************************* Linkage to Streams System *************************************************************************/struct module_info ip_to_streams_minfo = { 0 /* mi_idnum */ , "ip_to_streams" /* mi_idname */ , 0 /* mi_minpsz */ , INFPSZ /* mi_maxpsz */ , 20000 /* mi_hiwat */ , 2000 /* mi_lowat */ };struct qinit ip_to_streams_rinit = { ip_to_streams_rput , ip_to_streams_rsrv /* qi_srvp */ , ip_to_streams_open /* qi_open */ , ip_to_streams_close /* qi_close */ , NULL /* qi_admin */ , &ip_to_streams_minfo /* qi_minfo */ , NULL /* qi_mstat */ };struct qinit ip_to_streams_winit = { ip_to_streams_wput /* qi_putp */ , ip_to_streams_wsrv /* qi_srvp */ , NULL /* qi_open */ , NULL /* qi_close */ , NULL /* qi_admin */ , &ip_to_streams_minfo /* qi_minfo */ , NULL /* qi_mstat */ };struct streamtab ip_to_streams_info = { &ip_to_streams_rinit /* read queue definition */ , &ip_to_streams_winit /* write queue definition */ , NULL /* mux read queue */ , NULL /* mux write queue */ };int ip_to_streamsdevflag = 0;/************************************************************************* Storage Declarations *************************************************************************/unsigned long ip_to_streams_debug_mask = 0;#define IP_STRM_MTU (1500)/************************************************************************* ip_to_streams_open *************************************************************************** ** The streams open routine. Called when this is pushed on to the stack ** *************************************************************************/intip_to_streams_open( queue_t *rdq, dev_t *devp, int flag, int sflag, cred_t *credp){ ip_to_streams_minor_t *minor_ptr ; if ( ip_to_streams_debug_mask & (DBG_OPEN) ) cmn_err(CE_CONT, "\nip_to_streams_open: q=%x sflag=%d", sflag) ; minor_ptr = (ip_to_streams_minor_p) ALLOC(sizeof(ip_to_streams_minor_t)) ; if (minor_ptr == NULL) return(-ENOMEM) ; memset(minor_ptr, 0, sizeof(*minor_ptr)) ; /* clear to zero */ minor_ptr->dl_magic = DL_MAGIC ; rdq->q_ptr = (caddr_t) minor_ptr ; WR(rdq)->q_ptr = (caddr_t) minor_ptr ; minor_ptr->dl_rdq = rdq ; minor_ptr->dl_wrq = WR(rdq) ; minor_ptr->dl_q = rdq; minor_ptr->dl_err_prim = -1 ; /* ensure no retry */ strcpy(minor_ptr->myname, "is") ; /* initial name Ip/Streams */#if defined(KERNEL_2_3) strcpy(minor_ptr->mydev.name, "is") ; /* initial name Ip/Streams */#else minor_ptr->mydev.name = minor_ptr->myname ;#endif minor_ptr->mydev.init = ip_strm_init ; minor_ptr->mydev.priv = minor_ptr ; if ( ip_to_streams_debug_mask & (DBG_OPEN) ) cmn_err(CE_CONT, "\nip_to_streams_open succeeded") ; return (0); /* success */} /* ip_to_streams_open *//************************************************************************* ip_to_streams_close *************************************************************************** ** Called when closing the stream ** *************************************************************************/int ip_to_streams_close(queue_t *q, int dummy, cred_t *credp){ ip_to_streams_minor_t *minor_ptr ; if ( ip_to_streams_debug_mask & (DBG_OPEN) ) cmn_err(CE_CONT, "\nip_to_streams_close: q=%x ", q) ; minor_ptr = (ip_to_streams_minor_t *) q->q_ptr ; if ( minor_ptr != (ip_to_streams_minor_t *) NULL && minor_ptr->dl_magic == DL_MAGIC ) { if ( ip_to_streams_debug_mask & (DBG_OPEN) ) cmn_err(CE_CONT, "ip_to_streams_close: %s\n", minor_ptr->myname) ; if (minor_ptr->dev_registered != 0) /* still open to IP */ unregister_netdev(&minor_ptr->mydev) ; minor_ptr->dl_magic = ~DL_MAGIC ; FREE(minor_ptr) ; } else if ( ip_to_streams_debug_mask & (DBG_OPEN) ) cmn_err(CE_CONT, "ip_to_streams_close: invalid minor ptr q_ptr=%x\n", q->q_ptr) ; q->q_ptr = NULL ; /* zot the q ptrs */ WR(q)->q_ptr = NULL ; /* zot the q ptrs */ return(0) ;} /* ip_to_streams_close *//************************************************************************* ip_to_streams_ioctl *************************************************************************** ** Have a look at an ioctl received from the user. Return 1 if the ** ioctl is to be forwarded downstream. Return 0 if we handled it here. ** *************************************************************************/int ip_to_streams_ioctl(queue_t *q, mblk_t *mp){ struct iocblk *iocp; ip_to_streams_minor_t *minor_ptr ; mblk_t *xmp = mp->b_cont ; int result = 0 ; iocp = (struct iocblk *) mp -> b_rptr; /* the request header */ if ((mp -> b_wptr - mp -> b_rptr) < sizeof (struct iocblk *)) /* small */ return(1) ; /* let driver deal with it */ minor_ptr = (ip_to_streams_minor_t *) q->q_ptr ; switch (iocp -> ioc_cmd) { case SIOCSIFNAME: /* set interface name */ /* * This ioctl is sent by the streams user. It is the last step * in making this stream available to IP. Once we know the * name we register the device with IP as an interface. * * As an added feature, the streams user can set the name * to the empty string and we will unregister from IP. When * we unregister we leave the streams side alone so that a * simple "set if-name" ioctl will make the interface appear * under IP again. */ if (xmp != NULL && *xmp->b_rptr != 0) /* name specified */ { strncpy(minor_ptr->myname, xmp->b_rptr, sizeof(minor_ptr->myname)) ;#if defined(KERNEL_2_3) strcpy(minor_ptr->mydev.name, minor_ptr->myname) ;#else minor_ptr->mydev.name = minor_ptr->myname ;#endif if ((result = register_netdev(&minor_ptr->mydev)) != 0) printk("ip_to_streams_ioctl: " "register_netdev(%s) failed: %d\n", minor_ptr->myname, result); else printk("ip_to_streams_ioctl: SIOCSIFNAME: %s\n", minor_ptr->myname) ; minor_ptr->dev_registered = result == 0 ; } else /* nullify name, unregister */ { unregister_netdev(&minor_ptr->mydev) ; strcpy(minor_ptr->myname, "is") ; minor_ptr->contype = 0; /* not connected */ minor_ptr->ip_open = 0 ; /* not open to IP now */ } if (xmp != NULL) { freemsg(xmp) ; /* don't return any data */ mp->b_cont = NULL ; } break ; default: printk("ip_to_streams_ioctl: undefined ioctl: 0x%x\n", iocp->ioc_cmd) ; result = -EINVAL ; break ; } /* * If you exit the switch then we are going to reply to the * ioctl and not forward it downstream. */ if (result) /* error */ { mp -> b_datap -> db_type = M_IOCNAK; iocp -> ioc_count = 0; /* no data */ } else /* success */ { mp -> b_datap -> db_type = M_IOCACK; if ((xmp = mp -> b_cont) == NULL) /* no chained buf */ iocp -> ioc_count = 0; /* no data */ else /* a response */ iocp -> ioc_count = xmp -> b_wptr - xmp -> b_rptr; } iocp -> ioc_error = result; qreply(q, mp); return(0) ; /* do not forward */} /* ip_to_streams_ioctl *//************************************************************************* ip_to_streams_wput *************************************************************************** ** Write side put routine ** *************************************************************************/int ip_to_streams_wput(queue_t *q, mblk_t *mp){ ip_to_streams_minor_t *minor_ptr ; if ( ip_to_streams_debug_mask & DBG_PUT ) cmn_err(CE_CONT, "\nip_to_streams_wput: q=%x mp=%x\n", q, mp) ; minor_ptr = (ip_to_streams_minor_t *) q->q_ptr ; /* make sure the data structure is valid */ if ( minor_ptr == (ip_to_streams_minor_t *) NULL || minor_ptr->dl_magic != DL_MAGIC ) { if (ip_to_streams_debug_mask & DBG_SQUAWK) cmn_err(CE_NOTE, "ip_to_streams_wput: bad minor") ; freemsg(mp) ; return(0) ; } switch(mp->b_datap->db_type) { case M_DATA: if ( canputnext(q) ) /* data uses flow control */ putnext(q, mp); else putq(q, mp); break; case M_PROTO: case M_PCPROTO: { int err; union DL_primitives *dlp; err = 0; dlp = (union DL_primitives *)mp->b_rptr; switch(dlp->dl_primitive) { case DL_UNITDATA_REQ: { if ( ip_to_streams_debug_mask & DBG_WPUT) printk("ip_to_streams_wput: DL_UNITDATA_REQ:\n"); if ( canputnext(q) ) /* data uses flow control */ putnext(q, mp); else putq(q, mp); return(0) ; } case DL_INFO_REQ: { if ( ip_to_streams_debug_mask & DBG_WPUT) printk("ip_to_streams_wput: DL_INFO_REQ:\n"); putnext(q, mp); break; } case DL_BIND_REQ: { dl_bind_req_t *dlp; if ( ip_to_streams_debug_mask & DBG_WPUT) printk("ip_to_streams_wput:DL_BIND_REQ:\n"); minor_ptr->dlstate = DL_BIND_PENDING; dlp = (dl_bind_req_t *) mp->b_rptr ; minor_ptr->dl_sap = dlp->dl_sap ; /* save SAP */ putnext(q, mp); break; } case DL_UNBIND_REQ: { if ( ip_to_streams_debug_mask & DBG_WPUT) printk("DL_UNBIND_REQ:\n"); minor_ptr->dlstate = DL_UNBIND_PENDING; minor_ptr->dl_sap = 0 ; putnext(q, mp); break; } case DL_ATTACH_REQ: { if ( ip_to_streams_debug_mask & DBG_WPUT) printk("DL_ATTACH_REQ:\n"); minor_ptr->dlstate = DL_ATTACH_PENDING; putnext(q, mp); break; } case DL_DETACH_REQ: { if ( ip_to_streams_debug_mask & DBG_WPUT) printk("DL_DETACH_REQ:\n"); minor_ptr->dlstate = DL_DETACH_PENDING ; putnext(q, mp); break; } break; } break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -