📄 sl_udp.c
字号:
/***************************************************************************** @(#) sl_udp.c,v 0.7 2000/11/25 07:18:52 brian Exp ----------------------------------------------------------------------------- Copyright (C) 2000 Brian Bidulock. All Rights Reserved. PUBLIC LICENSE This license is provided without fee, provided that the above copy- right notice and this public license must be retained on all copies, extracts, compilations and derivative works. Use or distribution of this work in a manner that restricts its use except as provided here will render this license void. The author(s) hereby waive any and all other restrictions in respect of their copyright in this software and its associated documentation. The authors(s) of this software place in the public domain any novel methods or processes which are embodied in this software. The author(s) undertook to write it for the sake of the advancement of the Arts and Sciences, but it is provided as is, and the author(s) will not take any responsibility in it. ----------------------------------------------------------------------------- Last Modified 2000/11/25 07:18:52 by brian sl_udp.c,v Revision 0.7 2000/11/25 07:18:52 brian Stab at sl driver for UDP. *****************************************************************************/#ident @(#) sl_udp.c,v 0.7 2000/11/25 07:18:52 brian Expstatic char const ident[] = "sl_udp.c,v 0.7 2000/11/25 07:18:52 brian Exp";/* * This is an SLI driver which provides Signalling Link emulation over UDP. * It is a Style 2 PPA driver which must be attached to a local and remote * IP Address and Port. */#include <sys/ss7/sli.h>#include <sys/ss7/sli_ioctl.h>#define SL_DESCRIP "SS7/SL/UDP (Signalling Link over UDP) STREAMS MODULE"#define SL_COPYRIGHT "Copyright (c) 1997-2000 Brian Bidulock. All Rights Reserved."#define SL_DEVICES "Supports Linux Kernel UDP sockets."#define SL_CONTACT "Brian Bidulock <bidulock@openss7.org>"#define SL_BANNER SL_DESCRIP "\n" \ SL_COPYRIGHT "\n" \ SL_DEVICES "\n" \ SL_CONTACT "\n"#ifdef MODULEMODULE_AUTHOR(SL_CONTACT);MODULE_DESCRIPTION(SL_DESCRIP);MODULE_SUPPORTED_DEVICES(SL_DEVICES);#define MODULE_STATIC static#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#define MODULE_STATIC#endif#ifndef SL_DEBUG#define SL_DEBUG 2#endifstatic int sl_debug = SL_DEBUG;/* * ======================================== * * STREAMS Definitions * * ======================================== */#define SL_DEVICE "sl_udp"#define SL_MOD_ID 0x2221#define SL_MIN_PDU 3#define SL_MAX_PDU 277#define SL_HIWATER 1#define SL_LOWATER 0static struct module_info sl_minfo ={ SL_MOD_NUMBER, SL_DEVICE, SL_MIN_PDU, SL_MAX_PDU, SL_HIWATER, SL_LOWATER};static int sl_open (queue_t *, dev_t *, int, int, cred_t *);static int sl_close(queue_t *, int, cred_t *);static void sl_rput (queue_t *, mblk_t *);static void sl_rsrv (queue_t *);static void sl_wput (queue_t *, mblk_t *);static void sl_wsrv (queue_t *);static struct qinit sl_rinit ={ sl_rput, sl_rsrv, sl_open, sl_close, NULL, &sl_minfo, NULL};static struct qinit sl_winit ={ sl_wput, sl_wsrv, NULL, NULL, &sl_winfo, NULL};MODULE_STATICstruct streamtab sl_info ={ sl_rinit, sl_winit, NULL, NULL};typedef struct { sl_device_t device; struct sockaddr_in loc_addr; struct sockaddr_in rem_addr; struct socket *udpsock;} sdl_udpdev_t;typedef struct { sl_t *next; sl_ushort minor; queue_t *q; sl_ulong state; sl_ulong flags; sl_config_t config; sl_statem_t statem; sl_stats_t stats; sl_notify_t notify; sl_udpdev_t device;} sl_t;#define SL_N_MINOR 256 /* for now */MODULE_STATICsl_t *sl_udp_list = NULL;static int sl_initialized = 0;void sl_udp_init(void){ if ( sl_initialized ) return; sl_initialized = 1; printk(KERN_INFO, SL_BANNER); /* console splash */};void sl_udp_terminate(void){ if ( !sl_initialized ) return; sl_initialized = 0;};static sl_config_t sl_config_default = { 0, /* FIXME: fill out defaults */};static sl_device_t sl_device_default = { 0, /* FIXME: fill out defaults */};#define SL_UDP_PPA_SIZE 2*sizeof(struct sockaddr)static int sl_dev_open (sl_udpdev_t *); /* opens device */static void sl_dev_close(sl_udpdev_t *); /* close device */static intsl_open(q, devp, flag, sflag, crp) queue_t *q; dev_t *devp; int flag; int sflag; cred_t *crp;{ int minor, err; sl_t **slp, *sl; if ( q->q_ptr != NULL) return(0); if ( sflag == MODOPEN || WR(q)->q_next != NULL ) return ENXIO; if ( sflag == CLONEOPEN ) { for ( minor = 0, slp = &sl_udp_list; minor < SL_N_MINOR, *sdp; slp = &(*slp)->next ) { if ( minor < (*slp)->minor ) break; if ( minor == (*slp)->minor ) minor++; } if ( minor >= SL_N_MINOR ) return ENXIO; *devp = makedevice(getmajor(*devp), minor); } else { if ( (minor = getminor(*devp)) >= SL_N_MINOR ) return ENXIO; for ( slp = &sl_udp_list; *slp; slp=&(*slp)->next ) { if ( minor < (*slp)->minor ) break; if ( minor == (*slp)->minor ) return EBUSY; } } MOD_INC_USE_COUNT; if ( !(sl = kmalloc(sizeof(sl_t), GFP_KERNEL)) ) { MOD_DEC_USE_COUNT; return ENOMEM; } bzero(sl, sizeof(*sl)); sl->next = *slp; *slp = sl; sl->minor = minor; sl->q = q; sl->state = SL_UNATTACHED; /* Style 2 */ sl->flags = 0; bcopy(&sl->config, &sl_config_default, sizeof(sl_config_default)); bcopy(&sl->device, &sl_device_default, sizeof(sl_device_default)); if ( (err = sl_dev_open(&sl->device)) ) { *slp = sl->next; kfree(sl); MOD_DEC_USE_COUNT; return err; } q->q_ptr = WR(q)->q_ptr = sl; return (0);}static int sl_dev_enable (sl_t *);static void sl_dev_disable(sl_t *);static intsl_close(q, flag, crp) queue_t *q; int flag; cred_t *crp;{ sl_t **slp, *sl = (sl_t *)q->q_ptr; for ( slp = &sl_udp_list; *slp; slp = &(*slp)->next ) if ( *slp == sl ) break; if ( !*slp ) return ENXIO; /* where is it? */ if ( sl->state == SL_ENABLED ) sl_dev_disable(sl); q->q_ptr = WR(q)->q_ptr = NULL; sl_dev_close(&sl->device); *slp = sl->next; kfree(sl); MOD_DEC_USE_COUNT; return(0);}static voidsl_wput (queue_t *q, mblk_t *mp){ int err=0; switch ( mp->b_data->db_type ) { case M_DATA: if ( (err = sl_m_data(q, mp)) ) break; return; case M_PROTO: case M_PCPROTO: if ( (err = sl_m_proto(q, mp)) ) break; return; case M_FLUSH: if ( *mp->b_rptr & FLUSHW ) { flushq(q, FLUSHALL); *mp->b_rptr &= ~FLUSHW; } if ( *mp->b_rptr & FLUSHR ) { flushq(RD(q), FLUSHALL); qreply(q, mp); return; } break; case M_CTL: if ( (err = sl_m_ctl(q, mp)) ) break; return; case M_IOCTL: if ( (err = sl_m_ioctl(q, mp)) ) break; return; } if ( err == EAGAIN ) { putq(q, mp); return; } freemsg(mp); return;}static voidsl_wsrv (queue_t *q){ int err=0; while ( (mp = getq(q)) ) { switch ( mp->b_data->db_type ) { case M_DATA: if ( (err = sl_m_data(q, mp)) ) break; continue; case M_PROTO: case M_PCPROTO: if ( (err = sl_m_proto(q, mp)) ) break; continue; case M_CTL: if ( (err = sl_m_ctl(q, mp)) ) break; continue; case M_IOCTL: if ( (err = sl_m_ioctl(q, mp)) ) break; continue; } if ( err == EAGAIN ) { putbq(q, mp); return; } freemsg(mp); }}static voidsl_rput (queue_t *q, mblk_t *mp){ sl_t *sl = q->q_ptr; if ( mp->b_data->db_type >= QPCTL ) { putnext(q, mp); return; } if ( !q->q_count && canputnext(q) ) { /* process received frame */ putnext(q); return; } putq(q, mp); sl->statem.Cr++; return;}static voidsl_rsrv (queue_t *q){ mblk_t *mp; sl_t *sl = (sl_t *)q->q_ptr; int backlog = sl->statem.Cr; while ( (mp = getq(q)) ) { sl->statem.Cr--; if ( mp->b_datap->db_type >= QPCTL ) { /* process received frame */ putnext(q, mp); continue; } if ( canputnext(q) ) { /* process received frame */ putnext(q); continue; } sl->statem.Cr++; putbq(q, mp); break; } if ( !q->q_count ) sl->statem.Cr = 0; if ( sl->statem.Cr != backlog ) sl_rb_congestion_function(sl); return;}/* * ============================================== * * DEVICE SPECIFIC Procedures * * ============================================== */static intsl_dev_open(sl_udpdev_t *dev){ return(0);}static voidsl_dev_close(sl_udpdev_t *dev){ return;}static intsl_dev_enable(sl_t *sl){ int err; struct socket *sock = NULL; struct sockaddr *sa = (struct sockaddr *)&sl->device.loc_addr; if ( (err = sock_create(PF_INET, SOCK_DGRAM, 0, &sock)) < 0 ) return err; sock->sk->reuse = 1; sock->sk->allocation = GFP_ATOMIC; if ( (err = sock->bind(sock, sa, sizeof(*sa))) < 0 ) { sock_release(sock); return err; } sock->protinfo.destruct_hook = sl; /* might be bad idea */ sock->sk->data_ready = sl_udp_data_ready; sl->device.udpsock = sock; sl->state = SL_ENABLED; return(0);}static voidsl_dev_disable(sl_t *sl){ struct socket *sock = sl->device.udpsock; sl->statem.daedt_state = SL_STATE_IDLE; if ( sock ) { sock->protinfo.destruct_hook = NULL; sock_release(sock); sl->device.udpsock = NULL; } sl->statem.daedr_state = SL_STATE_IDLE; sl->state = SL_DISABLED;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -