diff options
Diffstat (limited to 'drivers/isdn/divert')
-rw-r--r-- | drivers/isdn/divert/Makefile | 10 | ||||
-rw-r--r-- | drivers/isdn/divert/divert_init.c | 82 | ||||
-rw-r--r-- | drivers/isdn/divert/divert_procfs.c | 336 | ||||
-rw-r--r-- | drivers/isdn/divert/isdn_divert.c | 846 | ||||
-rw-r--r-- | drivers/isdn/divert/isdn_divert.h | 132 |
5 files changed, 0 insertions, 1406 deletions
diff --git a/drivers/isdn/divert/Makefile b/drivers/isdn/divert/Makefile deleted file mode 100644 index 07684fe53537..000000000000 --- a/drivers/isdn/divert/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Makefile for the dss1_divert ISDN module - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_DIVERSION) += dss1_divert.o - -# Multipart objects. - -dss1_divert-y := isdn_divert.o divert_procfs.o divert_init.o diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c deleted file mode 100644 index 267dede13bfd..000000000000 --- a/drivers/isdn/divert/divert_init.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id divert_init.c,v 1.5.6.2 2001/01/24 22:18:17 kai Exp $ - * - * Module init for DSS1 diversion services for i4l. - * - * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> - -#include "isdn_divert.h" - -MODULE_DESCRIPTION("ISDN4Linux: Call diversion support"); -MODULE_AUTHOR("Werner Cornelius"); -MODULE_LICENSE("GPL"); - -/****************************************/ -/* structure containing interface to hl */ -/****************************************/ -isdn_divert_if divert_if = { - DIVERT_IF_MAGIC, /* magic value */ - DIVERT_CMD_REG, /* register cmd */ - ll_callback, /* callback routine from ll */ - NULL, /* command still not specified */ - NULL, /* drv_to_name */ - NULL, /* name_to_drv */ -}; - -/*************************/ -/* Module interface code */ -/* no cmd line parms */ -/*************************/ -static int __init divert_init(void) -{ - int i; - - if (divert_dev_init()) { - printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n"); - return (-EIO); - } - if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) { - divert_dev_deinit(); - printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i); - return (-EIO); - } - printk(KERN_INFO "dss1_divert module successfully installed\n"); - return (0); -} - -/**********************/ -/* Module deinit code */ -/**********************/ -static void __exit divert_exit(void) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&divert_lock, flags); - divert_if.cmd = DIVERT_CMD_REL; /* release */ - if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) { - printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i); - spin_unlock_irqrestore(&divert_lock, flags); - return; - } - if (divert_dev_deinit()) { - printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); - spin_unlock_irqrestore(&divert_lock, flags); - return; - } - spin_unlock_irqrestore(&divert_lock, flags); - deleterule(-1); /* delete all rules and free mem */ - deleteprocs(); - printk(KERN_INFO "dss1_divert module successfully removed \n"); -} - -module_init(divert_init); -module_exit(divert_exit); diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c deleted file mode 100644 index 342585e04fd3..000000000000 --- a/drivers/isdn/divert/divert_procfs.c +++ /dev/null @@ -1,336 +0,0 @@ -/* $Id: divert_procfs.c,v 1.11.6.2 2001/09/23 22:24:36 kai Exp $ - * - * Filesystem handling for the diversion supplementary services. - * - * Copyright 1998 by Werner Cornelius (werner@isdn4linux.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include <linux/module.h> -#include <linux/poll.h> -#include <linux/slab.h> -#ifdef CONFIG_PROC_FS -#include <linux/proc_fs.h> -#else -#include <linux/fs.h> -#endif -#include <linux/sched.h> -#include <linux/isdnif.h> -#include <net/net_namespace.h> -#include <linux/mutex.h> -#include "isdn_divert.h" - - -/*********************************/ -/* Variables for interface queue */ -/*********************************/ -ulong if_used = 0; /* number of interface users */ -static DEFINE_MUTEX(isdn_divert_mutex); -static struct divert_info *divert_info_head = NULL; /* head of queue */ -static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */ -static DEFINE_SPINLOCK(divert_info_lock);/* lock for queue */ -static wait_queue_head_t rd_queue; - -/*********************************/ -/* put an info buffer into queue */ -/*********************************/ -void -put_info_buffer(char *cp) -{ - struct divert_info *ib; - unsigned long flags; - - if (if_used <= 0) - return; - if (!cp) - return; - if (!*cp) - return; - if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC))) - return; /* no memory */ - strcpy(ib->info_start, cp); /* set output string */ - ib->next = NULL; - spin_lock_irqsave(&divert_info_lock, flags); - ib->usage_cnt = if_used; - if (!divert_info_head) - divert_info_head = ib; /* new head */ - else - divert_info_tail->next = ib; /* follows existing messages */ - divert_info_tail = ib; /* new tail */ - - /* delete old entrys */ - while (divert_info_head->next) { - if ((divert_info_head->usage_cnt <= 0) && - (divert_info_head->next->usage_cnt <= 0)) { - ib = divert_info_head; - divert_info_head = divert_info_head->next; - kfree(ib); - } else - break; - } /* divert_info_head->next */ - spin_unlock_irqrestore(&divert_info_lock, flags); - wake_up_interruptible(&(rd_queue)); -} /* put_info_buffer */ - -#ifdef CONFIG_PROC_FS - -/**********************************/ -/* deflection device read routine */ -/**********************************/ -static ssize_t -isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t *off) -{ - struct divert_info *inf; - int len; - - if (!(inf = *((struct divert_info **) file->private_data))) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - wait_event_interruptible(rd_queue, (inf = - *((struct divert_info **) file->private_data))); - } - if (!inf) - return (0); - - inf->usage_cnt--; /* new usage count */ - file->private_data = &inf->next; /* next structure */ - if ((len = strlen(inf->info_start)) <= count) { - if (copy_to_user(buf, inf->info_start, len)) - return -EFAULT; - *off += len; - return (len); - } - return (0); -} /* isdn_divert_read */ - -/**********************************/ -/* deflection device write routine */ -/**********************************/ -static ssize_t -isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_t *off) -{ - return (-ENODEV); -} /* isdn_divert_write */ - - -/***************************************/ -/* select routines for various kernels */ -/***************************************/ -static __poll_t -isdn_divert_poll(struct file *file, poll_table *wait) -{ - __poll_t mask = 0; - - poll_wait(file, &(rd_queue), wait); - /* mask = EPOLLOUT | EPOLLWRNORM; */ - if (*((struct divert_info **) file->private_data)) { - mask |= EPOLLIN | EPOLLRDNORM; - } - return mask; -} /* isdn_divert_poll */ - -/****************/ -/* Open routine */ -/****************/ -static int -isdn_divert_open(struct inode *ino, struct file *filep) -{ - unsigned long flags; - - spin_lock_irqsave(&divert_info_lock, flags); - if_used++; - if (divert_info_head) - filep->private_data = &(divert_info_tail->next); - else - filep->private_data = &divert_info_head; - spin_unlock_irqrestore(&divert_info_lock, flags); - /* start_divert(); */ - return nonseekable_open(ino, filep); -} /* isdn_divert_open */ - -/*******************/ -/* close routine */ -/*******************/ -static int -isdn_divert_close(struct inode *ino, struct file *filep) -{ - struct divert_info *inf; - unsigned long flags; - - spin_lock_irqsave(&divert_info_lock, flags); - if_used--; - inf = *((struct divert_info **) filep->private_data); - while (inf) { - inf->usage_cnt--; - inf = inf->next; - } - if (if_used <= 0) - while (divert_info_head) { - inf = divert_info_head; - divert_info_head = divert_info_head->next; - kfree(inf); - } - spin_unlock_irqrestore(&divert_info_lock, flags); - return (0); -} /* isdn_divert_close */ - -/*********/ -/* IOCTL */ -/*********/ -static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg) -{ - divert_ioctl dioctl; - int i; - unsigned long flags; - divert_rule *rulep; - char *cp; - - if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl))) - return -EFAULT; - - switch (cmd) { - case IIOCGETVER: - dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */ - break; - - case IIOCGETDRV: - if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) - return (-EINVAL); - break; - - case IIOCGETNAM: - cp = divert_if.drv_to_name(dioctl.getid.drvid); - if (!cp) - return (-EINVAL); - if (!*cp) - return (-EINVAL); - strcpy(dioctl.getid.drvnam, cp); - break; - - case IIOCGETRULE: - if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) - return (-EINVAL); - dioctl.getsetrule.rule = *rulep; /* copy data */ - break; - - case IIOCMODRULE: - if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) - return (-EINVAL); - spin_lock_irqsave(&divert_lock, flags); - *rulep = dioctl.getsetrule.rule; /* copy data */ - spin_unlock_irqrestore(&divert_lock, flags); - return (0); /* no copy required */ - break; - - case IIOCINSRULE: - return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule)); - break; - - case IIOCDELRULE: - return (deleterule(dioctl.getsetrule.ruleidx)); - break; - - case IIOCDODFACT: - return (deflect_extern_action(dioctl.fwd_ctrl.subcmd, - dioctl.fwd_ctrl.callid, - dioctl.fwd_ctrl.to_nr)); - - case IIOCDOCFACT: - case IIOCDOCFDIS: - case IIOCDOCFINT: - if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) - return (-EINVAL); /* invalid driver */ - if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) == - sizeof(dioctl.cf_ctrl.msn)) - return -EINVAL; - if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) == - sizeof(dioctl.cf_ctrl.fwd_nr)) - return -EINVAL; - if ((i = cf_command(dioctl.cf_ctrl.drvid, - (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2, - dioctl.cf_ctrl.cfproc, - dioctl.cf_ctrl.msn, - dioctl.cf_ctrl.service, - dioctl.cf_ctrl.fwd_nr, - &dioctl.cf_ctrl.procid))) - return (i); - break; - - default: - return (-EINVAL); - } /* switch cmd */ - return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0; -} /* isdn_divert_ioctl */ - -static long isdn_divert_ioctl(struct file *file, uint cmd, ulong arg) -{ - long ret; - - mutex_lock(&isdn_divert_mutex); - ret = isdn_divert_ioctl_unlocked(file, cmd, arg); - mutex_unlock(&isdn_divert_mutex); - - return ret; -} - -static const struct file_operations isdn_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = isdn_divert_read, - .write = isdn_divert_write, - .poll = isdn_divert_poll, - .unlocked_ioctl = isdn_divert_ioctl, - .open = isdn_divert_open, - .release = isdn_divert_close, -}; - -/****************************/ -/* isdn subdir in /proc/net */ -/****************************/ -static struct proc_dir_entry *isdn_proc_entry = NULL; -static struct proc_dir_entry *isdn_divert_entry = NULL; -#endif /* CONFIG_PROC_FS */ - -/***************************************************************************/ -/* divert_dev_init must be called before the proc filesystem may be used */ -/***************************************************************************/ -int -divert_dev_init(void) -{ - - init_waitqueue_head(&rd_queue); - -#ifdef CONFIG_PROC_FS - isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net); - if (!isdn_proc_entry) - return (-1); - isdn_divert_entry = proc_create("divert", S_IFREG | S_IRUGO, - isdn_proc_entry, &isdn_fops); - if (!isdn_divert_entry) { - remove_proc_entry("isdn", init_net.proc_net); - return (-1); - } -#endif /* CONFIG_PROC_FS */ - - return (0); -} /* divert_dev_init */ - -/***************************************************************************/ -/* divert_dev_deinit must be called before leaving isdn when included as */ -/* a module. */ -/***************************************************************************/ -int -divert_dev_deinit(void) -{ - -#ifdef CONFIG_PROC_FS - remove_proc_entry("divert", isdn_proc_entry); - remove_proc_entry("isdn", init_net.proc_net); -#endif /* CONFIG_PROC_FS */ - - return (0); -} /* divert_dev_deinit */ diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c deleted file mode 100644 index 5620fd2c6009..000000000000 --- a/drivers/isdn/divert/isdn_divert.c +++ /dev/null @@ -1,846 +0,0 @@ -/* $Id: isdn_divert.c,v 1.6.6.3 2001/09/23 22:24:36 kai Exp $ - * - * DSS1 main diversion supplementary handling for i4l. - * - * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include <linux/proc_fs.h> -#include <linux/slab.h> -#include <linux/timer.h> -#include <linux/jiffies.h> - -#include "isdn_divert.h" - -/**********************************/ -/* structure keeping calling info */ -/**********************************/ -struct call_struc { - isdn_ctrl ics; /* delivered setup + driver parameters */ - ulong divert_id; /* Id delivered to user */ - unsigned char akt_state; /* actual state */ - char deflect_dest[35]; /* deflection destination */ - struct timer_list timer; /* timer control structure */ - char info[90]; /* device info output */ - struct call_struc *next; /* pointer to next entry */ - struct call_struc *prev; -}; - - -/********************************************/ -/* structure keeping deflection table entry */ -/********************************************/ -struct deflect_struc { - struct deflect_struc *next, *prev; - divert_rule rule; /* used rule */ -}; - - -/*****************************************/ -/* variables for main diversion services */ -/*****************************************/ -/* diversion/deflection processes */ -static struct call_struc *divert_head = NULL; /* head of remembered entrys */ -static ulong next_id = 1; /* next info id */ -static struct deflect_struc *table_head = NULL; -static struct deflect_struc *table_tail = NULL; -static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ - -DEFINE_SPINLOCK(divert_lock); - -/***************************/ -/* timer callback function */ -/***************************/ -static void deflect_timer_expire(struct timer_list *t) -{ - unsigned long flags; - struct call_struc *cs = from_timer(cs, t, timer); - - spin_lock_irqsave(&divert_lock, flags); - del_timer(&cs->timer); /* delete active timer */ - spin_unlock_irqrestore(&divert_lock, flags); - - switch (cs->akt_state) { - case DEFLECT_PROCEED: - cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ - divert_if.ll_cmd(&cs->ics); - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - break; - - case DEFLECT_ALERT: - cs->ics.command = ISDN_CMD_REDIR; /* protocol */ - strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone)); - strcpy(cs->ics.parm.setup.eazmsn, "Testtext delayed"); - divert_if.ll_cmd(&cs->ics); - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - break; - - case DEFLECT_AUTODEL: - default: - spin_lock_irqsave(&divert_lock, flags); - if (cs->prev) - cs->prev->next = cs->next; /* forward link */ - else - divert_head = cs->next; - if (cs->next) - cs->next->prev = cs->prev; /* back link */ - spin_unlock_irqrestore(&divert_lock, flags); - kfree(cs); - return; - - } /* switch */ -} /* deflect_timer_func */ - - -/*****************************************/ -/* handle call forwarding de/activations */ -/* 0 = deact, 1 = act, 2 = interrogate */ -/*****************************************/ -int cf_command(int drvid, int mode, - u_char proc, char *msn, - u_char service, char *fwd_nr, ulong *procid) -{ - unsigned long flags; - int retval, msnlen; - int fwd_len; - char *p, *ielenp, tmp[60]; - struct call_struc *cs; - - if (strchr(msn, '.')) return (-EINVAL); /* subaddress not allowed in msn */ - if ((proc & 0x7F) > 2) return (-EINVAL); - proc &= 3; - p = tmp; - *p++ = 0x30; /* enumeration */ - ielenp = p++; /* remember total length position */ - *p++ = 0xa; /* proc tag */ - *p++ = 1; /* length */ - *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */ - *p++ = 0xa; /* service tag */ - *p++ = 1; /* length */ - *p++ = service; /* service to handle */ - - if (mode == 1) { - if (!*fwd_nr) return (-EINVAL); /* destination missing */ - if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */ - fwd_len = strlen(fwd_nr); - *p++ = 0x30; /* number enumeration */ - *p++ = fwd_len + 2; /* complete forward to len */ - *p++ = 0x80; /* fwd to nr */ - *p++ = fwd_len; /* length of number */ - strcpy(p, fwd_nr); /* copy number */ - p += fwd_len; /* pointer beyond fwd */ - } /* activate */ - - msnlen = strlen(msn); - *p++ = 0x80; /* msn number */ - if (msnlen > 1) { - *p++ = msnlen; /* length */ - strcpy(p, msn); - p += msnlen; - } else - *p++ = 0; - - *ielenp = p - ielenp - 1; /* set total IE length */ - - /* allocate mem for information struct */ - if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) - return (-ENOMEM); /* no memory */ - timer_setup(&cs->timer, deflect_timer_expire, 0); - cs->info[0] = '\0'; - cs->ics.driver = drvid; - cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */ - cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */ - cs->ics.parm.dss1_io.proc = (mode == 1) ? 7 : (mode == 2) ? 11 : 8; /* operation */ - cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */ - cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ - cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ - - spin_lock_irqsave(&divert_lock, flags); - cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ - spin_unlock_irqrestore(&divert_lock, flags); - *procid = cs->ics.parm.dss1_io.ll_id; - - sprintf(cs->info, "%d 0x%lx %s%s 0 %s %02x %d%s%s\n", - (!mode) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT, - cs->ics.parm.dss1_io.ll_id, - (mode != 2) ? "" : "0 ", - divert_if.drv_to_name(cs->ics.driver), - msn, - service & 0xFF, - proc, - (mode != 1) ? "" : " 0 ", - (mode != 1) ? "" : fwd_nr); - - retval = divert_if.ll_cmd(&cs->ics); /* execute command */ - - if (!retval) { - cs->prev = NULL; - spin_lock_irqsave(&divert_lock, flags); - cs->next = divert_head; - divert_head = cs; - spin_unlock_irqrestore(&divert_lock, flags); - } else - kfree(cs); - return (retval); -} /* cf_command */ - - -/****************************************/ -/* handle a external deflection command */ -/****************************************/ -int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) -{ - struct call_struc *cs; - isdn_ctrl ic; - unsigned long flags; - int i; - - if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */ - cs = divert_head; /* start of parameter list */ - while (cs) { - if (cs->divert_id == callid) break; /* found */ - cs = cs->next; - } /* search entry */ - if (!cs) return (-EINVAL); /* invalid callid */ - - ic.driver = cs->ics.driver; - ic.arg = cs->ics.arg; - i = -EINVAL; - if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */ - switch (cmd & 0x7F) { - case 0: /* hangup */ - del_timer(&cs->timer); - ic.command = ISDN_CMD_HANGUP; - i = divert_if.ll_cmd(&ic); - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - break; - - case 1: /* alert */ - if (cs->akt_state == DEFLECT_ALERT) return (0); - cmd &= 0x7F; /* never wait */ - del_timer(&cs->timer); - ic.command = ISDN_CMD_ALERT; - if ((i = divert_if.ll_cmd(&ic))) { - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - } else - cs->akt_state = DEFLECT_ALERT; - break; - - case 2: /* redir */ - del_timer(&cs->timer); - strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone)); - strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); - ic.command = ISDN_CMD_REDIR; - if ((i = divert_if.ll_cmd(&ic))) { - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - } else - cs->akt_state = DEFLECT_ALERT; - break; - - } /* switch */ - return (i); -} /* deflect_extern_action */ - -/********************************/ -/* insert a new rule before idx */ -/********************************/ -int insertrule(int idx, divert_rule *newrule) -{ - struct deflect_struc *ds, *ds1 = NULL; - unsigned long flags; - - if (!(ds = kmalloc(sizeof(struct deflect_struc), GFP_KERNEL))) - return (-ENOMEM); /* no memory */ - - ds->rule = *newrule; /* set rule */ - - spin_lock_irqsave(&divert_lock, flags); - - if (idx >= 0) { - ds1 = table_head; - while ((ds1) && (idx > 0)) - { idx--; - ds1 = ds1->next; - } - if (!ds1) idx = -1; - } - - if (idx < 0) { - ds->prev = table_tail; /* previous entry */ - ds->next = NULL; /* end of chain */ - if (ds->prev) - ds->prev->next = ds; /* last forward */ - else - table_head = ds; /* is first entry */ - table_tail = ds; /* end of queue */ - } else { - ds->next = ds1; /* next entry */ - ds->prev = ds1->prev; /* prev entry */ - ds1->prev = ds; /* backward chain old element */ - if (!ds->prev) - table_head = ds; /* first element */ - } - - spin_unlock_irqrestore(&divert_lock, flags); - return (0); -} /* insertrule */ - -/***********************************/ -/* delete the rule at position idx */ -/***********************************/ -int deleterule(int idx) -{ - struct deflect_struc *ds, *ds1; - unsigned long flags; - - if (idx < 0) { - spin_lock_irqsave(&divert_lock, flags); - ds = table_head; - table_head = NULL; - table_tail = NULL; - spin_unlock_irqrestore(&divert_lock, flags); - while (ds) { - ds1 = ds; - ds = ds->next; - kfree(ds1); - } - return (0); - } - - spin_lock_irqsave(&divert_lock, flags); - ds = table_head; - - while ((ds) && (idx > 0)) { - idx--; - ds = ds->next; - } - - if (!ds) { - spin_unlock_irqrestore(&divert_lock, flags); - return (-EINVAL); - } - - if (ds->next) - ds->next->prev = ds->prev; /* backward chain */ - else - table_tail = ds->prev; /* end of chain */ - - if (ds->prev) - ds->prev->next = ds->next; /* forward chain */ - else - table_head = ds->next; /* start of chain */ - - spin_unlock_irqrestore(&divert_lock, flags); - kfree(ds); - return (0); -} /* deleterule */ - -/*******************************************/ -/* get a pointer to a specific rule number */ -/*******************************************/ -divert_rule *getruleptr(int idx) -{ - struct deflect_struc *ds = table_head; - - if (idx < 0) return (NULL); - while ((ds) && (idx >= 0)) { - if (!(idx--)) { - return (&ds->rule); - break; - } - ds = ds->next; - } - return (NULL); -} /* getruleptr */ - -/*************************************************/ -/* called from common module on an incoming call */ -/*************************************************/ -static int isdn_divert_icall(isdn_ctrl *ic) -{ - int retval = 0; - unsigned long flags; - struct call_struc *cs = NULL; - struct deflect_struc *dv; - char *p, *p1; - u_char accept; - - /* first check the internal deflection table */ - for (dv = table_head; dv; dv = dv->next) { - /* scan table */ - if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) || - ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL))) - continue; /* call option check */ - if (!(dv->rule.drvid & (1L << ic->driver))) - continue; /* driver not matching */ - if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) - continue; /* si1 not matching */ - if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) - continue; /* si2 not matching */ - - p = dv->rule.my_msn; - p1 = ic->parm.setup.eazmsn; - accept = 0; - while (*p) { - /* complete compare */ - if (*p == '-') { - accept = 1; /* call accepted */ - break; - } - if (*p++ != *p1++) - break; /* not accepted */ - if ((!*p) && (!*p1)) - accept = 1; - } /* complete compare */ - if (!accept) continue; /* not accepted */ - - if ((strcmp(dv->rule.caller, "0")) || - (ic->parm.setup.phone[0])) { - p = dv->rule.caller; - p1 = ic->parm.setup.phone; - accept = 0; - while (*p) { - /* complete compare */ - if (*p == '-') { - accept = 1; /* call accepted */ - break; - } - if (*p++ != *p1++) - break; /* not accepted */ - if ((!*p) && (!*p1)) - accept = 1; - } /* complete compare */ - if (!accept) continue; /* not accepted */ - } - - switch (dv->rule.action) { - case DEFLECT_IGNORE: - return 0; - - case DEFLECT_ALERT: - case DEFLECT_PROCEED: - case DEFLECT_REPORT: - case DEFLECT_REJECT: - if (dv->rule.action == DEFLECT_PROCEED) - if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) - return (0); /* no external deflection needed */ - if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) - return (0); /* no memory */ - timer_setup(&cs->timer, deflect_timer_expire, 0); - cs->info[0] = '\0'; - - cs->ics = *ic; /* copy incoming data */ - if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone, "0"); - if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn, "0"); - cs->ics.parm.setup.screen = dv->rule.screen; - if (dv->rule.waittime) - cs->timer.expires = jiffies + (HZ * dv->rule.waittime); - else if (dv->rule.action == DEFLECT_PROCEED) - cs->timer.expires = jiffies + (HZ * extern_wait_max); - else - cs->timer.expires = 0; - cs->akt_state = dv->rule.action; - spin_lock_irqsave(&divert_lock, flags); - cs->divert_id = next_id++; /* new sequence number */ - spin_unlock_irqrestore(&divert_lock, flags); - cs->prev = NULL; - if (cs->akt_state == DEFLECT_ALERT) { - strcpy(cs->deflect_dest, dv->rule.to_nr); - if (!cs->timer.expires) { - strcpy(ic->parm.setup.eazmsn, - "Testtext direct"); - ic->parm.setup.screen = dv->rule.screen; - strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone)); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - retval = 5; - } else - retval = 1; /* alerting */ - } else { - cs->deflect_dest[0] = '\0'; - retval = 4; /* only proceed */ - } - snprintf(cs->info, sizeof(cs->info), - "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", - cs->akt_state, - cs->divert_id, - divert_if.drv_to_name(cs->ics.driver), - (ic->command == ISDN_STAT_ICALLW) ? "1" : "0", - cs->ics.parm.setup.phone, - cs->ics.parm.setup.eazmsn, - cs->ics.parm.setup.si1, - cs->ics.parm.setup.si2, - cs->ics.parm.setup.screen, - dv->rule.waittime, - cs->deflect_dest); - if ((dv->rule.action == DEFLECT_REPORT) || - (dv->rule.action == DEFLECT_REJECT)) { - put_info_buffer(cs->info); - kfree(cs); /* remove */ - return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */ - } - break; - - default: - return 0; /* ignore call */ - } /* switch action */ - break; /* will break the 'for' looping */ - } /* scan_table */ - - if (cs) { - cs->prev = NULL; - spin_lock_irqsave(&divert_lock, flags); - cs->next = divert_head; - divert_head = cs; - if (cs->timer.expires) add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - - put_info_buffer(cs->info); - return (retval); - } else - return (0); -} /* isdn_divert_icall */ - - -void deleteprocs(void) -{ - struct call_struc *cs, *cs1; - unsigned long flags; - - spin_lock_irqsave(&divert_lock, flags); - cs = divert_head; - divert_head = NULL; - while (cs) { - del_timer(&cs->timer); - cs1 = cs; - cs = cs->next; - kfree(cs1); - } - spin_unlock_irqrestore(&divert_lock, flags); -} /* deleteprocs */ - -/****************************************************/ -/* put a address including address type into buffer */ -/****************************************************/ -static int put_address(char *st, u_char *p, int len) -{ - u_char retval = 0; - u_char adr_typ = 0; /* network standard */ - - if (len < 2) return (retval); - if (*p == 0xA1) { - retval = *(++p) + 2; /* total length */ - if (retval > len) return (0); /* too short */ - len = retval - 2; /* remaining length */ - if (len < 3) return (0); - if ((*(++p) != 0x0A) || (*(++p) != 1)) return (0); - adr_typ = *(++p); - len -= 3; - p++; - if (len < 2) return (0); - if (*p++ != 0x12) return (0); - if (*p > len) return (0); /* check number length */ - len = *p++; - } else if (*p == 0x80) { - retval = *(++p) + 2; /* total length */ - if (retval > len) return (0); - len = retval - 2; - p++; - } else - return (0); /* invalid address information */ - - sprintf(st, "%d ", adr_typ); - st += strlen(st); - if (!len) - *st++ = '-'; - else - while (len--) - *st++ = *p++; - *st = '\0'; - return (retval); -} /* put_address */ - -/*************************************/ -/* report a successful interrogation */ -/*************************************/ -static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) -{ - char *src = ic->parm.dss1_io.data; - int restlen = ic->parm.dss1_io.datalen; - int cnt = 1; - u_char n, n1; - char st[90], *p, *stp; - - if (restlen < 2) return (-100); /* frame too short */ - if (*src++ != 0x30) return (-101); - if ((n = *src++) > 0x81) return (-102); /* invalid length field */ - restlen -= 2; /* remaining bytes */ - if (n == 0x80) { - if (restlen < 2) return (-103); - if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104); - restlen -= 2; - } else if (n == 0x81) { - n = *src++; - restlen--; - if (n > restlen) return (-105); - restlen = n; - } else if (n > restlen) - return (-106); - else - restlen = n; /* standard format */ - if (restlen < 3) return (-107); /* no procedure */ - if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108); - restlen -= 3; - if (restlen < 2) return (-109); /* list missing */ - if (*src == 0x31) { - src++; - if ((n = *src++) > 0x81) return (-110); /* invalid length field */ - restlen -= 2; /* remaining bytes */ - if (n == 0x80) { - if (restlen < 2) return (-111); - if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112); - restlen -= 2; - } else if (n == 0x81) { - n = *src++; - restlen--; - if (n > restlen) return (-113); - restlen = n; - } else if (n > restlen) - return (-114); - else - restlen = n; /* standard format */ - } /* result list header */ - - while (restlen >= 2) { - stp = st; - sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id, - cnt++, divert_if.drv_to_name(ic->driver)); - stp += strlen(stp); - if (*src++ != 0x30) return (-115); /* invalid enum */ - n = *src++; - restlen -= 2; - if (n > restlen) return (-116); /* enum length wrong */ - restlen -= n; - p = src; /* one entry */ - src += n; - if (!(n1 = put_address(stp, p, n & 0xFF))) continue; - stp += strlen(stp); - p += n1; - n -= n1; - if (n < 6) continue; /* no service and proc */ - if ((*p++ != 0x0A) || (*p++ != 1)) continue; - sprintf(stp, " 0x%02x ", (*p++) & 0xFF); - stp += strlen(stp); - if ((*p++ != 0x0A) || (*p++ != 1)) continue; - sprintf(stp, "%d ", (*p++) & 0xFF); - stp += strlen(stp); - n -= 6; - if (n > 2) { - if (*p++ != 0x30) continue; - if (*p > (n - 2)) continue; - n = *p++; - if (!(n1 = put_address(stp, p, n & 0xFF))) continue; - stp += strlen(stp); - } - sprintf(stp, "\n"); - put_info_buffer(st); - } /* while restlen */ - if (restlen) return (-117); - return (0); -} /* interrogate_success */ - -/*********************************************/ -/* callback for protocol specific extensions */ -/*********************************************/ -static int prot_stat_callback(isdn_ctrl *ic) -{ - struct call_struc *cs, *cs1; - int i; - unsigned long flags; - - cs = divert_head; /* start of list */ - cs1 = NULL; - while (cs) { - if (ic->driver == cs->ics.driver) { - switch (cs->ics.arg) { - case DSS1_CMD_INVOKE: - if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && - (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) { - switch (ic->arg) { - case DSS1_STAT_INVOKE_ERR: - sprintf(cs->info, "128 0x%lx 0x%x\n", - ic->parm.dss1_io.ll_id, - ic->parm.dss1_io.timeout); - put_info_buffer(cs->info); - break; - - case DSS1_STAT_INVOKE_RES: - switch (cs->ics.parm.dss1_io.proc) { - case 7: - case 8: - put_info_buffer(cs->info); - break; - - case 11: - i = interrogate_success(ic, cs); - if (i) - sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT, - ic->parm.dss1_io.ll_id, i); - put_info_buffer(cs->info); - break; - - default: - printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc); - break; - } - - break; - - default: - printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg); - break; - } - cs1 = cs; /* remember structure */ - cs = NULL; - continue; /* abort search */ - } /* id found */ - break; - - case DSS1_CMD_INVOKE_ABORT: - printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); - break; - - default: - printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n", cs->ics.arg); - break; - } /* switch ics.arg */ - cs = cs->next; - } /* driver ok */ - } - - if (!cs1) { - printk(KERN_WARNING "dss1_divert unhandled process\n"); - return (0); - } - - if (cs1->ics.driver == -1) { - spin_lock_irqsave(&divert_lock, flags); - del_timer(&cs1->timer); - if (cs1->prev) - cs1->prev->next = cs1->next; /* forward link */ - else - divert_head = cs1->next; - if (cs1->next) - cs1->next->prev = cs1->prev; /* back link */ - spin_unlock_irqrestore(&divert_lock, flags); - kfree(cs1); - } - - return (0); -} /* prot_stat_callback */ - - -/***************************/ -/* status callback from HL */ -/***************************/ -static int isdn_divert_stat_callback(isdn_ctrl *ic) -{ - struct call_struc *cs, *cs1; - unsigned long flags; - int retval; - - retval = -1; - cs = divert_head; /* start of list */ - while (cs) { - if ((ic->driver == cs->ics.driver) && - (ic->arg == cs->ics.arg)) { - switch (ic->command) { - case ISDN_STAT_DHUP: - sprintf(cs->info, "129 0x%lx\n", cs->divert_id); - del_timer(&cs->timer); - cs->ics.driver = -1; - break; - - case ISDN_STAT_CAUSE: - sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num); - break; - - case ISDN_STAT_REDIR: - sprintf(cs->info, "131 0x%lx\n", cs->divert_id); - del_timer(&cs->timer); - cs->ics.driver = -1; - break; - - default: - sprintf(cs->info, "999 0x%lx 0x%x\n", cs->divert_id, (int)(ic->command)); - break; - } - put_info_buffer(cs->info); - retval = 0; - } - cs1 = cs; - cs = cs->next; - if (cs1->ics.driver == -1) { - spin_lock_irqsave(&divert_lock, flags); - if (cs1->prev) - cs1->prev->next = cs1->next; /* forward link */ - else - divert_head = cs1->next; - if (cs1->next) - cs1->next->prev = cs1->prev; /* back link */ - spin_unlock_irqrestore(&divert_lock, flags); - kfree(cs1); - } - } - return (retval); /* not found */ -} /* isdn_divert_stat_callback */ - - -/********************/ -/* callback from ll */ -/********************/ -int ll_callback(isdn_ctrl *ic) -{ - switch (ic->command) { - case ISDN_STAT_ICALL: - case ISDN_STAT_ICALLW: - return (isdn_divert_icall(ic)); - break; - - case ISDN_STAT_PROT: - if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) { - if (ic->arg != DSS1_STAT_INVOKE_BRD) - return (prot_stat_callback(ic)); - else - return (0); /* DSS1 invoke broadcast */ - } else - return (-1); /* protocol not euro */ - - default: - return (isdn_divert_stat_callback(ic)); - } -} /* ll_callback */ diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h deleted file mode 100644 index 55033dd872c0..000000000000 --- a/drivers/isdn/divert/isdn_divert.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id: isdn_divert.h,v 1.5.6.1 2001/09/23 22:24:36 kai Exp $ - * - * Header for the diversion supplementary ioctl interface. - * - * Copyright 1998 by Werner Cornelius (werner@ikt.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include <linux/ioctl.h> -#include <linux/types.h> - -/******************************************/ -/* IOCTL codes for interface to user prog */ -/******************************************/ -#define DIVERT_IIOC_VERSION 0x01 /* actual version */ -#define IIOCGETVER _IO('I', 1) /* get version of interface */ -#define IIOCGETDRV _IO('I', 2) /* get driver number */ -#define IIOCGETNAM _IO('I', 3) /* get driver name */ -#define IIOCGETRULE _IO('I', 4) /* read one rule */ -#define IIOCMODRULE _IO('I', 5) /* modify/replace a rule */ -#define IIOCINSRULE _IO('I', 6) /* insert/append one rule */ -#define IIOCDELRULE _IO('I', 7) /* delete a rule */ -#define IIOCDODFACT _IO('I', 8) /* hangup/reject/alert/immediately deflect a call */ -#define IIOCDOCFACT _IO('I', 9) /* activate control forwarding in PBX */ -#define IIOCDOCFDIS _IO('I', 10) /* deactivate control forwarding in PBX */ -#define IIOCDOCFINT _IO('I', 11) /* interrogate control forwarding in PBX */ - -/*************************************/ -/* states reported through interface */ -/*************************************/ -#define DEFLECT_IGNORE 0 /* ignore incoming call */ -#define DEFLECT_REPORT 1 /* only report */ -#define DEFLECT_PROCEED 2 /* deflect when externally triggered */ -#define DEFLECT_ALERT 3 /* alert and deflect after delay */ -#define DEFLECT_REJECT 4 /* reject immediately */ -#define DIVERT_ACTIVATE 5 /* diversion activate */ -#define DIVERT_DEACTIVATE 6 /* diversion deactivate */ -#define DIVERT_REPORT 7 /* interrogation result */ -#define DEFLECT_AUTODEL 255 /* only for internal use */ - -#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */ - -typedef struct { - ulong drvid; /* driver ids, bit mapped */ - char my_msn[35]; /* desired msn, subaddr allowed */ - char caller[35]; /* caller id, partial string with * + subaddr allowed */ - char to_nr[35]; /* deflected to number incl. subaddress */ - u_char si1, si2; /* service indicators, si1=bitmask, si1+2 0 = all */ - u_char screen; /* screening: 0 = no info, 1 = info, 2 = nfo with nr */ - u_char callopt; /* option for call handling: - 0 = all calls - 1 = only non waiting calls - 2 = only waiting calls */ - u_char action; /* desired action: - 0 = don't report call -> ignore - 1 = report call, do not allow/proceed for deflection - 2 = report call, send proceed, wait max waittime secs - 3 = report call, alert and deflect after waittime - 4 = report call, reject immediately - actions 1-2 only take place if interface is opened - */ - u_char waittime; /* maximum wait time for proceeding */ -} divert_rule; - -typedef union { - int drv_version; /* return of driver version */ - struct { - int drvid; /* id of driver */ - char drvnam[30]; /* name of driver */ - } getid; - struct { - int ruleidx; /* index of rule */ - divert_rule rule; /* rule parms */ - } getsetrule; - struct { - u_char subcmd; /* 0 = hangup/reject, - 1 = alert, - 2 = deflect */ - ulong callid; /* id of call delivered by ascii output */ - char to_nr[35]; /* destination when deflect, - else uus1 string (maxlen 31), - data from rule used if empty */ - } fwd_ctrl; - struct { - int drvid; /* id of driver */ - u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */ - ulong procid; /* process id returned when no error */ - u_char service; /* basically coded service, 0 = all */ - char msn[25]; /* desired msn, empty = all */ - char fwd_nr[35];/* forwarded to number + subaddress */ - } cf_ctrl; -} divert_ioctl; - -#ifdef __KERNEL__ - -#include <linux/isdnif.h> -#include <linux/isdn_divertif.h> - -#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */ - -/**************************************************/ -/* structure keeping ascii info for device output */ -/**************************************************/ -struct divert_info { - struct divert_info *next; - ulong usage_cnt; /* number of files still to work */ - char info_start[2]; /* info string start */ -}; - - -/**************/ -/* Prototypes */ -/**************/ -extern spinlock_t divert_lock; - -extern ulong if_used; /* number of interface users */ -extern int divert_dev_deinit(void); -extern int divert_dev_init(void); -extern void put_info_buffer(char *); -extern int ll_callback(isdn_ctrl *); -extern isdn_divert_if divert_if; -extern divert_rule *getruleptr(int); -extern int insertrule(int, divert_rule *); -extern int deleterule(int); -extern void deleteprocs(void); -extern int deflect_extern_action(u_char, ulong, char *); -extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *); - -#endif /* __KERNEL__ */ |