Dynamic Timeout-Rule-Handling vs. 971110 included
This commit is contained in:
parent
9d9814cd49
commit
0c64f33f52
|
@ -7,6 +7,11 @@ if [ "$CONFIG_INET" != "n" ]; then
|
|||
bool 'Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
|
||||
bool 'Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
|
||||
fi
|
||||
bool 'Support dynamic timeout-rules' CONFIG_ISDN_TIMEOUT_RULES
|
||||
if [ "$CONFIG_ISDN_TIMEOUT_RULES" != "n" ]; then
|
||||
bool 'Use masqueraded addresses for rule-matching' CONFIG_ISDN_TIMRU_USE_MASQ
|
||||
fi
|
||||
bool 'Support budget-accounting' CONFIG_ISDN_BUDGET
|
||||
fi
|
||||
bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO
|
||||
if [ "$CONFIG_X25" != "n" ]; then
|
||||
|
|
|
@ -25,6 +25,12 @@ ifeq ($(CONFIG_ISDN),y)
|
|||
ifdef CONFIG_ISDN_AUDIO
|
||||
L_OBJS += isdn_audio.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
L_OBJS += isdn_timru.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_BUDGET
|
||||
L_OBJS += isdn_budget.o
|
||||
endif
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN),m)
|
||||
M_OBJS += isdn.o
|
||||
|
@ -41,6 +47,12 @@ else
|
|||
ifdef CONFIG_ISDN_AUDIO
|
||||
O_OBJS += isdn_audio.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
O_OBJS += isdn_timru.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_BUDGET
|
||||
O_OBJS += isdn_budget.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
/* isdn_budget.c
|
||||
*
|
||||
* Linux ISDN subsystem, budget-accounting for network interfaces.
|
||||
*
|
||||
* Copyright 1997 by Christian Lademann <cal@zls.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
30.06.97:cal:angelegt
|
||||
04.11.97:cal:budget.period: int --> time_t
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#define __NO_VERSION__
|
||||
#include <linux/module.h>
|
||||
#include <linux/isdn.h>
|
||||
#include "isdn_common.h"
|
||||
#include "isdn_net.h"
|
||||
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
|
||||
#define VERBOSE_PRINTK(v, l, p...) { \
|
||||
if(dev->net_verbose >= (v)) { \
|
||||
printk(l ## p); \
|
||||
} else { ; } \
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_net_budget(int type, struct device *ndev) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
int i, ret = 0;
|
||||
|
||||
switch(type) {
|
||||
case ISDN_BUDGET_INIT:
|
||||
for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
|
||||
lp->budget [i] .amount = -1;
|
||||
lp->budget [i] .used = 0;
|
||||
lp->budget [i] .period = (time_t)0;
|
||||
lp->budget [i] .period_started = (time_t)0;
|
||||
lp->budget [i] .last_check = CURRENT_TIME;
|
||||
lp->budget [i] .notified = 0;
|
||||
}
|
||||
|
||||
return(0);
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_CHECK_DIAL:
|
||||
case ISDN_BUDGET_CHECK_CHARGE:
|
||||
case ISDN_BUDGET_CHECK_ONLINE:
|
||||
ret = 0;
|
||||
|
||||
for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
|
||||
if(lp->budget [i] .amount < 0)
|
||||
continue;
|
||||
|
||||
if(lp->budget [i] .period_started + lp->budget [i] .period < CURRENT_TIME) {
|
||||
lp->budget [i] .used = 0;
|
||||
lp->budget [i] .period_started = CURRENT_TIME;
|
||||
lp->budget [i] .notified = 0;
|
||||
}
|
||||
|
||||
if(lp->budget [i] .used >= lp->budget [i] .amount)
|
||||
ret |= (1 << i);
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case ISDN_BUDGET_CHECK_DIAL:
|
||||
if(! ret) {
|
||||
lp->budget [ISDN_BUDGET_DIAL] .used++;
|
||||
lp->budget [ISDN_BUDGET_DIAL] .last_check = CURRENT_TIME;
|
||||
}
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_CHECK_CHARGE:
|
||||
lp->budget [ISDN_BUDGET_CHARGE] .used++;
|
||||
lp->budget [ISDN_BUDGET_CHARGE] .last_check = CURRENT_TIME;
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_CHECK_ONLINE:
|
||||
if(lp->budget [ISDN_BUDGET_ONLINE] .last_check) {
|
||||
lp->budget [ISDN_BUDGET_ONLINE] .used += (CURRENT_TIME - lp->budget [ISDN_BUDGET_ONLINE] .last_check);
|
||||
}
|
||||
|
||||
lp->budget [ISDN_BUDGET_ONLINE] .last_check = CURRENT_TIME;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
if(ret)
|
||||
lp->flags |= ISDN_NET_STOPPED;
|
||||
*/
|
||||
for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
|
||||
if(ret & (1 << i) && ! lp->budget [i] .notified) {
|
||||
switch(i) {
|
||||
case ISDN_BUDGET_DIAL:
|
||||
printk(KERN_WARNING "isdn_budget: dial budget used up.\n");
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_CHARGE:
|
||||
printk(KERN_WARNING "isdn_budget: charge budget used up.\n");
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_ONLINE:
|
||||
printk(KERN_WARNING "isdn_budget: online budget used up.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "isdn_budget: budget #%d used up.\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
lp->budget [i] .notified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_START_ONLINE:
|
||||
lp->budget [ISDN_BUDGET_ONLINE] .last_check = CURRENT_TIME;
|
||||
return(0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_budget_ioctl(isdn_ioctl_budget *iocmd) {
|
||||
isdn_net_dev *p = isdn_net_findif(iocmd->name);
|
||||
|
||||
if(p) {
|
||||
switch(iocmd->command) {
|
||||
case ISDN_BUDGET_SET_BUDGET:
|
||||
if(! suser())
|
||||
return(-EPERM);
|
||||
|
||||
if(iocmd->budget < 0 || iocmd->budget > ISDN_BUDGET_NUM_BUDGET)
|
||||
return(-EINVAL);
|
||||
|
||||
if(iocmd->amount < 0)
|
||||
iocmd->amount = -1;
|
||||
|
||||
p->local->budget [iocmd->budget] .amount = iocmd->amount;
|
||||
p->local->budget [iocmd->budget] .period = iocmd->period;
|
||||
|
||||
if(iocmd->used <= 0)
|
||||
p->local->budget [iocmd->budget] .used = 0;
|
||||
else
|
||||
p->local->budget [iocmd->budget] .used = iocmd->used;
|
||||
|
||||
if(iocmd->period_started == (time_t)0)
|
||||
p->local->budget [iocmd->budget] .period_started = CURRENT_TIME;
|
||||
else
|
||||
p->local->budget [iocmd->budget] .period_started = iocmd->period_started;
|
||||
|
||||
return(0);
|
||||
break;
|
||||
|
||||
case ISDN_BUDGET_GET_BUDGET:
|
||||
if(iocmd->budget < 0 || iocmd->budget > ISDN_BUDGET_NUM_BUDGET)
|
||||
return(-EINVAL);
|
||||
|
||||
iocmd->amount = p->local->budget [iocmd->budget] .amount;
|
||||
iocmd->used = p->local->budget [iocmd->budget] .used;
|
||||
iocmd->period = p->local->budget [iocmd->budget] .period;
|
||||
iocmd->period_started = p->local->budget [iocmd->budget] .period_started;
|
||||
|
||||
return(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return(-EINVAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(-ENODEV);
|
||||
}
|
||||
#endif
|
|
@ -21,6 +21,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.56 1998/02/25 17:49:38 he
|
||||
* Changed return codes caused be failing copy_{to,from}_user to -EFAULT
|
||||
*
|
||||
* Revision 1.55 1998/02/23 23:35:32 fritz
|
||||
* Eliminated some compiler warnings.
|
||||
*
|
||||
|
@ -295,7 +298,7 @@ isdn_MOD_DEC_USE_COUNT(void)
|
|||
MOD_DEC_USE_COUNT;
|
||||
}
|
||||
|
||||
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
|
||||
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) || defined(CONFIG_ISDN_TIMEOUT_RULES)
|
||||
void
|
||||
isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
|
||||
{
|
||||
|
@ -1273,6 +1276,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
|
|||
isdn_ioctl_struct iocts;
|
||||
isdn_net_ioctl_phone phone;
|
||||
isdn_net_ioctl_cfg cfg;
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
isdn_ioctl_timeout_rule timru;
|
||||
#endif /* CONFIG_ISDN_TIMEOUT_RULES */
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
isdn_ioctl_budget budget;
|
||||
#endif /* CONFIG_ISDN_BUDGET */
|
||||
} iocpar;
|
||||
|
||||
#define name iocpar.name
|
||||
|
@ -1280,6 +1289,13 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
|
|||
#define iocts iocpar.iocts
|
||||
#define phone iocpar.phone
|
||||
#define cfg iocpar.cfg
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
# define timru iocpar.timru
|
||||
#endif /* CONFIG_ISDN_TIMEOUT_RULES */
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
# define budget iocpar.budget
|
||||
#endif /* CONFIG_ISDN_BUDGET */
|
||||
|
||||
|
||||
if (minor == ISDN_MINOR_STATUS) {
|
||||
switch (cmd) {
|
||||
|
@ -1429,6 +1445,57 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
|
|||
return -EFAULT;
|
||||
return isdn_net_force_hangup(name);
|
||||
break;
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
case IIOCNETARU:
|
||||
/* Add a rule to a network-interface */
|
||||
if (arg) {
|
||||
if((ret = copy_from_user((char *) &timru, (char *) arg, sizeof(timru))))
|
||||
return(ret);
|
||||
return(isdn_timru_ioctl_add_rule(&timru));
|
||||
} else
|
||||
return(-EINVAL);
|
||||
case IIOCNETDRU:
|
||||
/* Delete a rule from a network-interface */
|
||||
if (arg) {
|
||||
if((ret = copy_from_user((char *) &timru, (char *) arg, sizeof(timru))))
|
||||
return(ret);
|
||||
return(isdn_timru_ioctl_del_rule(&timru));
|
||||
} else
|
||||
return(-EINVAL);
|
||||
case IIOCNETGRU:
|
||||
/* Get a rule of a network-interface */
|
||||
if (arg) {
|
||||
if((ret = copy_from_user((char *)&timru, (char *)arg, sizeof(timru))))
|
||||
return(ret);
|
||||
|
||||
if((ret = isdn_timru_ioctl_get_rule(&timru)))
|
||||
return(ret);
|
||||
|
||||
if((ret = copy_to_user((char *)arg, (char *)&timru, sizeof(timru))))
|
||||
return(ret);
|
||||
|
||||
return(0);
|
||||
} else
|
||||
return(-EINVAL);
|
||||
#endif /* CONFIG_ISDN_TIMEOUT_RULES */
|
||||
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
case IIOCNETBUD:
|
||||
/* handle budget-accounting of a network-interface */
|
||||
if (arg) {
|
||||
if((ret = copy_from_user((char *)&budget, (char *)arg, sizeof(budget))))
|
||||
return(ret);
|
||||
|
||||
if((ret = isdn_budget_ioctl(&budget)))
|
||||
return(ret);
|
||||
|
||||
if((ret = copy_to_user((char *)arg, (char *)&budget, sizeof(budget))))
|
||||
return(ret);
|
||||
|
||||
return(0);
|
||||
} else
|
||||
return(-EINVAL);
|
||||
#endif /* CONFIG_ISDN_BUDGET */
|
||||
#endif /* CONFIG_NETDEVICES */
|
||||
case IIOCSETVER:
|
||||
dev->net_verbose = arg;
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 1998/02/20 17:19:01 fritz
|
||||
* Added common stub for sending commands to lowlevel.
|
||||
*
|
||||
* Revision 1.8 1997/10/09 21:28:49 fritz
|
||||
* New HL<->LL interface:
|
||||
* New BSENT callback with nr. of bytes included.
|
||||
|
@ -87,6 +90,6 @@ extern int isdn_readbchan(int, int, u_char *, u_char *, int, int);
|
|||
extern int isdn_get_free_channel(int, int, int, int, int);
|
||||
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
|
||||
extern int register_isdn(isdn_if * i);
|
||||
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
|
||||
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) || defined(CONFIG_ISDN_TIMEOUT_RULES)
|
||||
extern void isdn_dumppkt(char *, u_char *, int, int);
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.57 1998/02/25 18:31:13 fritz
|
||||
* Added debugging output in adjust_header.
|
||||
*
|
||||
* Revision 1.56 1998/02/25 17:49:42 he
|
||||
* Changed return codes caused be failing copy_{to,from}_user to -EFAULT
|
||||
*
|
||||
|
@ -280,9 +283,24 @@ char *isdn_net_revision = "$Revision$";
|
|||
static void
|
||||
isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "isdn_net: %s: %s, send ICMP\n",
|
||||
dev->name, reason);
|
||||
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
|
||||
|
||||
if(skb)
|
||||
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
|
||||
|
||||
#if 0
|
||||
for(i = 0; i < DEV_NUMBUFFS; i++) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
while((skb = skb_dequeue(&dev->buffs[i]))) {
|
||||
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -434,7 +452,11 @@ isdn_net_autohup()
|
|||
if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
|
||||
anymore = 1;
|
||||
l->huptimer++;
|
||||
if ((l->onhtime) && (l->huptimer > l->onhtime))
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
if ((l->timeout_rules || l->huptimeout) && l->huptimer > l->huptimeout)
|
||||
#else
|
||||
if ((l->onhtime) && (l->huptimer > l->onhtime))
|
||||
#endif
|
||||
if (l->hupflags & ISDN_MANCHARGE &&
|
||||
l->hupflags & ISDN_CHARGEHUP) {
|
||||
while (jiffies - l->chargetime > l->chargeint)
|
||||
|
@ -458,6 +480,17 @@ isdn_net_autohup()
|
|||
isdn_net_hangup(&p->dev);
|
||||
} else if (l->hupflags & ISDN_INHUP)
|
||||
isdn_net_hangup(&p->dev);
|
||||
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
if(isdn_net_budget(ISDN_BUDGET_CHECK_ONLINE, &p->dev)) {
|
||||
isdn_net_hangup(&p->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(dev->global_flags & ISDN_GLOBAL_STOPPED || l->flags & ISDN_NET_STOPPED) {
|
||||
isdn_net_hangup(&p->dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
p = (isdn_net_dev *) p->next;
|
||||
}
|
||||
|
@ -596,6 +629,16 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
|
|||
lp->chargetime = jiffies;
|
||||
printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
|
||||
lp->name, lp->chargetime);
|
||||
|
||||
/* reset dial-timeout */
|
||||
lp->dialstarted = 0;
|
||||
lp->dialwait_timer = 0;
|
||||
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
(void)isdn_net_budget(ISDN_BUDGET_START_ONLINE, &p->dev);
|
||||
(void)isdn_net_budget(ISDN_BUDGET_CHECK_CHARGE, &p->dev);
|
||||
#endif
|
||||
|
||||
/* Immediately send first skb to speed up arp */
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
||||
|
@ -613,6 +656,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
|
|||
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
|
||||
lp->first_skb = NULL;
|
||||
}
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
else {
|
||||
/* recalc initial huptimeout,
|
||||
there is no packet to match the rules. */
|
||||
isdn_net_recalc_timeout(ISDN_TIMRU_BRINGUP, ISDN_TIMRU_PACKET_NONE, &p->dev, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
@ -638,6 +688,11 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
|
|||
lp->chargetime = jiffies;
|
||||
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %d\n",
|
||||
lp->name, lp->chargetime);
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
if(isdn_net_budget(ISDN_BUDGET_CHECK_CHARGE, &p->dev)) {
|
||||
isdn_net_hangup(&p->dev);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -703,6 +758,13 @@ isdn_net_dial(void)
|
|||
break;
|
||||
}
|
||||
anymore = 1;
|
||||
|
||||
if(lp->dialtimeout > 0)
|
||||
if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
|
||||
lp->dialstarted = jiffies;
|
||||
lp->dialwait_timer = 0;
|
||||
}
|
||||
|
||||
lp->dialstate++;
|
||||
/* Fall through */
|
||||
case 2:
|
||||
|
@ -723,6 +785,12 @@ isdn_net_dial(void)
|
|||
* If list of phone-numbers is exhausted, increment
|
||||
* retry-counter.
|
||||
*/
|
||||
if(dev->global_flags & ISDN_GLOBAL_STOPPED || lp->flags & ISDN_NET_STOPPED) {
|
||||
isdn_net_unreachable(&p->dev, lp->first_skb, "dial suppressed: isdn stopped");
|
||||
isdn_net_hangup(&p->dev);
|
||||
break;
|
||||
}
|
||||
|
||||
cmd.driver = lp->isdn_device;
|
||||
cmd.command = ISDN_CMD_SETL2;
|
||||
cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
|
||||
|
@ -747,6 +815,24 @@ isdn_net_dial(void)
|
|||
lp->dialstate = 4;
|
||||
printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
|
||||
} else {
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
if(isdn_net_budget(ISDN_BUDGET_CHECK_DIAL, &p->dev)) {
|
||||
restore_flags(flags);
|
||||
isdn_net_unreachable(&p->dev, lp->first_skb, "dial: budget(s) used up");
|
||||
isdn_net_hangup(&p->dev);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if(lp->dialtimeout > 0)
|
||||
if(jiffies > (lp->dialstarted + lp->dialtimeout)) {
|
||||
restore_flags(flags);
|
||||
lp->dialwait_timer = jiffies + lp->dialwait;
|
||||
lp->dialstarted = 0;
|
||||
isdn_net_unreachable(&p->dev, lp->first_skb, "dial: timed out");
|
||||
isdn_net_hangup(&p->dev);
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(cmd.parm.setup.phone, "%s", lp->dial->num);
|
||||
/*
|
||||
* Switch to next number or back to start if at end of list.
|
||||
|
@ -754,6 +840,17 @@ isdn_net_dial(void)
|
|||
if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
|
||||
lp->dial = lp->phone[1];
|
||||
lp->dialretry++;
|
||||
|
||||
if (lp->dialretry > lp->dialmax) {
|
||||
restore_flags(flags);
|
||||
if (lp->dialtimeout == 0) {
|
||||
lp->dialwait_timer = jiffies + lp->dialwait;
|
||||
lp->dialstarted = 0;
|
||||
isdn_net_unreachable(&p->dev, lp->first_skb, "dial: tried all numbers dialmax times");
|
||||
}
|
||||
isdn_net_hangup(&p->dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
cmd.driver = lp->isdn_device;
|
||||
|
@ -768,7 +865,7 @@ isdn_net_dial(void)
|
|||
isdn_info_update();
|
||||
}
|
||||
printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
|
||||
lp->dialretry - 1, cmd.parm.setup.phone);
|
||||
lp->dialretry, cmd.parm.setup.phone);
|
||||
lp->dtimer = 0;
|
||||
#ifdef ISDN_DEBUG_NET_DIAL
|
||||
printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
|
||||
|
@ -792,14 +889,11 @@ isdn_net_dial(void)
|
|||
break;
|
||||
case 4:
|
||||
/* Wait for D-Channel-connect.
|
||||
* If timeout and max retries not
|
||||
* reached, switch back to state 3.
|
||||
* If timeout, switch back to state 3.
|
||||
* Dialmax-handling moved to state 3.
|
||||
*/
|
||||
if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
|
||||
if (lp->dialretry < lp->dialmax) {
|
||||
lp->dialstate = 3;
|
||||
} else
|
||||
isdn_net_hangup(&p->dev);
|
||||
lp->dialstate = 3;
|
||||
anymore = 1;
|
||||
break;
|
||||
case 5:
|
||||
|
@ -1071,14 +1165,21 @@ isdn_net_xmit(struct device *ndev, isdn_net_local * lp, struct sk_buff *skb)
|
|||
{
|
||||
int ret;
|
||||
|
||||
#if CONFIG_ISDN_TIMEOUT_RULES
|
||||
(void)isdn_net_recalc_timeout(ISDN_TIMRU_KEEPUP_OUT,
|
||||
ISDN_TIMRU_PACKET_SKB, ndev, skb, 0);
|
||||
#endif
|
||||
|
||||
/* For the other encaps the header has already been built */
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
|
||||
return isdn_ppp_xmit(skb, ndev);
|
||||
}
|
||||
#endif
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
/* Reset hangup-timeout */
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
if (lp->cps > lp->triggercps) {
|
||||
/* Device overloaded */
|
||||
|
||||
|
@ -1190,6 +1291,32 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
|
|||
ulong flags;
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
if(isdn_net_recalc_timeout(ISDN_TIMRU_BRINGUP,
|
||||
ISDN_TIMRU_PACKET_SKB, ndev, skb, 0) <= 0) {
|
||||
isdn_net_unreachable(ndev, skb, "dial rejected: packet may not bring up connection");
|
||||
dev_kfree_skb(skb);
|
||||
ndev->tbusy = 0;
|
||||
restore_flags(flags);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if(lp->dialwait_timer <= 0)
|
||||
if(lp->dialstarted > 0 && lp->dialtimeout > 0 && jiffies < lp->dialstarted + lp->dialtimeout + lp->dialwait)
|
||||
lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
|
||||
|
||||
if(lp->dialwait_timer > 0) {
|
||||
if(jiffies < lp->dialwait_timer) {
|
||||
isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
|
||||
dev_kfree_skb(skb);
|
||||
ndev->tbusy = 0;
|
||||
restore_flags(flags);
|
||||
return 0;
|
||||
} else
|
||||
lp->dialwait_timer = 0;
|
||||
}
|
||||
|
||||
/* Grab a free ISDN-Channel */
|
||||
if ((chi =
|
||||
isdn_get_free_channel(ISDN_USAGE_NET,
|
||||
|
@ -1464,8 +1591,10 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
|
|||
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
|
||||
isdn_net_local *olp = lp; /* original 'lp' */
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
int proto = PPP_PROTOCOL(skb->data);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_X25
|
||||
struct concap_proto *cprot = lp -> netdev -> cprot;
|
||||
#endif
|
||||
|
@ -1494,20 +1623,26 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
|
|||
switch (lp->p_encap) {
|
||||
case ISDN_NET_ENCAP_ETHER:
|
||||
/* Ethernet over ISDN */
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
olp->huptimer = 0;
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
skb->protocol = isdn_net_type_trans(skb, ndev);
|
||||
break;
|
||||
case ISDN_NET_ENCAP_UIHDLC:
|
||||
/* HDLC with UI-frame (for ispa with -h1 option) */
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
olp->huptimer = 0;
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
skb_pull(skb, 2);
|
||||
/* Fall through */
|
||||
case ISDN_NET_ENCAP_RAWIP:
|
||||
/* RAW-IP without MAC-Header */
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
olp->huptimer = 0;
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
break;
|
||||
case ISDN_NET_ENCAP_CISCOHDLCK:
|
||||
|
@ -1547,8 +1682,10 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
|
|||
/* Fall through */
|
||||
case ISDN_NET_ENCAP_IPTYP:
|
||||
/* IP with type field */
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
olp->huptimer = 0;
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
skb->protocol = *(unsigned short *) &(skb->data[0]);
|
||||
skb_pull(skb, 2);
|
||||
if (*(unsigned short *) skb->data == 0xFFFF)
|
||||
|
@ -1556,6 +1693,7 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
|
|||
break;
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
case ISDN_NET_ENCAP_SYNCPPP:
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
/*
|
||||
* If encapsulation is syncppp, don't reset
|
||||
* huptimer on LCP packets.
|
||||
|
@ -1564,6 +1702,7 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
|
|||
olp->huptimer = 0;
|
||||
lp->huptimer = 0;
|
||||
}
|
||||
#endif
|
||||
isdn_ppp_receive(lp->netdev, olp, skb);
|
||||
return;
|
||||
#endif
|
||||
|
@ -1581,6 +1720,13 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
|
|||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
isdn_net_recalc_timeout(ISDN_TIMRU_KEEPUP_IN,
|
||||
ISDN_TIMRU_PACKET_SKB, ndev, skb, 0);
|
||||
/* FIXME: olp->huptimer = lp->huptimer ? */
|
||||
#endif
|
||||
|
||||
netif_rx(skb);
|
||||
return;
|
||||
}
|
||||
|
@ -2232,6 +2378,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
|
|||
ulong flags;
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
/* Grab a free ISDN-Channel */
|
||||
if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
|
||||
lp->l3_proto,
|
||||
|
@ -2364,6 +2511,19 @@ isdn_net_new(char *name, struct device *master)
|
|||
netdev->local->dialmax = 1;
|
||||
netdev->local->flags = ISDN_NET_CBHUP; /* Hangup before Callback */
|
||||
netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */
|
||||
netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */
|
||||
netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
|
||||
netdev->local->dialstarted = 0; /* Jiffies of last dial-start */
|
||||
netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
netdev->local->timeout_rules = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
(void)isdn_net_budget(ISDN_BUDGET_INIT, &netdev->dev);
|
||||
#endif
|
||||
|
||||
/* Put into to netdev-chain */
|
||||
netdev->next = (void *) dev->netdev;
|
||||
dev->netdev = netdev;
|
||||
|
@ -2562,6 +2722,8 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
|
|||
lp->triggercps = cfg->triggercps;
|
||||
lp->slavedelay = cfg->slavedelay * HZ;
|
||||
lp->pppbind = cfg->pppbind;
|
||||
lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
|
||||
lp->dialwait = cfg->dialwait * HZ;
|
||||
if (cfg->secure)
|
||||
lp->flags |= ISDN_NET_SECURE;
|
||||
else
|
||||
|
@ -2583,6 +2745,10 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
|
|||
lp->flags &= ~ISDN_NET_CALLBACK;
|
||||
break;
|
||||
}
|
||||
if (cfg->stopped)
|
||||
lp->flags |= ISDN_NET_STOPPED;
|
||||
else
|
||||
lp->flags &= ~ISDN_NET_STOPPED;
|
||||
if (cfg->chargehup)
|
||||
lp->hupflags |= ISDN_CHARGEHUP;
|
||||
else
|
||||
|
@ -2650,6 +2816,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
|
|||
if (lp->flags & ISDN_NET_CBOUT)
|
||||
cfg->callback = 2;
|
||||
cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
|
||||
cfg->stopped = (lp->flags & ISDN_NET_STOPPED) ? 1 : 0;
|
||||
cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
|
||||
cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
|
||||
cfg->cbdelay = lp->cbdelay;
|
||||
|
@ -2659,6 +2826,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
|
|||
cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
|
||||
(lp->chargeint / HZ) : 0;
|
||||
cfg->pppbind = lp->pppbind;
|
||||
cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
|
||||
cfg->dialwait = lp->dialwait / HZ;
|
||||
if (lp->slave)
|
||||
strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
|
||||
else
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.34 1998/02/25 17:49:48 he
|
||||
* Changed return codes caused be failing copy_{to,from}_user to -EFAULT
|
||||
*
|
||||
* Revision 1.33 1998/02/20 17:11:54 fritz
|
||||
* Changes for recent kernels.
|
||||
*
|
||||
|
@ -832,8 +835,10 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
|
|||
{
|
||||
isdn_net_local *lp;
|
||||
struct ippp_struct *is;
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
int proto;
|
||||
unsigned char protobuf[4];
|
||||
#endif
|
||||
|
||||
is = file->private_data;
|
||||
|
||||
|
@ -847,6 +852,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
|
|||
if (!lp)
|
||||
printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
|
||||
else {
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
/*
|
||||
* Don't reset huptimer for
|
||||
* LCP packets. (Echo requests).
|
||||
|
@ -856,6 +862,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
|
|||
proto = PPP_PROTOCOL(protobuf);
|
||||
if (proto != PPP_LCP)
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
|
||||
if (lp->isdn_device < 0 || lp->isdn_channel < 0)
|
||||
return 0;
|
||||
|
@ -875,6 +882,12 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
|
|||
printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
|
||||
isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
(void)isdn_net_recalc_timeout(ISDN_TIMRU_KEEPUP_OUT,
|
||||
ISDN_TIMRU_PACKET_PPP, &lp->netdev->dev, skb->data, 0);
|
||||
#endif
|
||||
|
||||
if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
|
||||
if (lp->sav_skb) {
|
||||
dev_kfree_skb(lp->sav_skb);
|
||||
|
@ -1225,15 +1238,24 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
|
|||
isdn_ppp_receive_ccp(net_dev,lp,skb);
|
||||
/* fall through */
|
||||
default:
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
(void)isdn_net_recalc_timeout(ISDN_TIMRU_KEEPUP_IN,
|
||||
ISDN_TIMRU_PACKET_PPP_NO_HEADER, dev, skb->data, proto);
|
||||
#endif
|
||||
isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
(void)isdn_net_recalc_timeout(ISDN_TIMRU_KEEPUP_IN,
|
||||
ISDN_TIMRU_PACKET_SKB, dev, skb, 0);
|
||||
#else
|
||||
/* Reset hangup-timer */
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
netif_rx(skb);
|
||||
/* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */
|
||||
/* Reset hangup-timer */
|
||||
lp->huptimer = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1335,7 +1357,9 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
|
|||
}
|
||||
ipt = ippp_table[lp->ppp_slot];
|
||||
|
||||
#ifndef CONFIG_ISDN_TIMEOUT_RULES
|
||||
lp->huptimer = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* after this line .. requeueing in the device queue is no longer allowed!!!
|
||||
|
|
|
@ -0,0 +1,905 @@
|
|||
/* isdn_timru.c
|
||||
*
|
||||
* Linux ISDN subsystem, timeout-rules for network interfaces.
|
||||
*
|
||||
* Copyright 1997 by Christian Lademann <cal@zls.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
02.06.97:cal:
|
||||
- ISDN_TIMRU_PACKET_NONE = 0 definiert, die anderen ISDN_TIMRU_PACKET_* -
|
||||
Definitionen jeweils inkrementiert
|
||||
|
||||
- isdn_net_recalc_timeout():
|
||||
- In der Schleife zum Finden einer passenden Regel wurde in jedem Fall
|
||||
die Wildcard-Kette durchsucht. Jetzt nicht mehr.
|
||||
- beim Testen einer Bringup-Regel wird der anfaengliche Timeout auf den
|
||||
Hangup-Timeout des Devices gesetzt (lp->onhtime).
|
||||
|
||||
10.06.97:cal:
|
||||
- isdn_net_recalc_timeout(): rule->neg-Handling gesaeubert: eine Regel passt
|
||||
genau dann, wenn match(rule) XOR rule->neg und das bei allen Regeltypen.
|
||||
- isdn_net_add_rule(): rule->timeout bei BRINGUP immer 1, sonst > 0.
|
||||
- alle return(-1), die zu ioctl-Calls zurueckgehen --> return(-EINVAL).
|
||||
- div. Leerzeilen geloescht / eingefuegt; alle return's "geklammert".
|
||||
|
||||
12.06.97:cal:
|
||||
- isdn_net_recalc_timeout(): Falls IP-Masquerading verwendet wird, kann mit
|
||||
der neuen Option CONFIG_TIMRU_USE_MASQ der Regel-Match auf die ursprueng-
|
||||
lichen Adressen und nicht auf die der Firewall angewendet werden. Dazu ist
|
||||
ein Patch in net/ipv4/ip_masq.c notwendig: ip_masq_in_get_2 muss
|
||||
exportiert werden.
|
||||
|
||||
26.06.97:cal:
|
||||
- isdn_net_add_rule(): rule->timeout darf bei BRINGUP >= 0 sein. Damit
|
||||
laesst sich folgende Systax erreichen: "Falls Paket passt, starte die
|
||||
Verbindung NICHT", wie es im Stand 970602 moeglich war.
|
||||
- isdn_net_recalc_timeout(): BRINGUP: initial timeout wird auf den in der
|
||||
passenden Regel gefundenen Timeout gesetzt. Ist dieser 0, so wird die
|
||||
Verbindung nicht aufgebaut.
|
||||
|
||||
16.10.97:cal:
|
||||
- isdn_net_recalc_timeout(): beachte Fake-Header, der bei ausgehenden
|
||||
SyncPPP-Paketen eingesetzt wird;
|
||||
TimRu's "recalc timeout:" - Meldungen in einer Zeile
|
||||
|
||||
04.11.97:cal:
|
||||
- isdn_net.c, isdn_net_new(): Timeout-Rules nicht mehr automatisch
|
||||
alloziieren;
|
||||
- isdn_net.c, isdn_net_autohup(): AutoHup auch durchfuehren, wenn keine
|
||||
Timeout-Rules alloziiert sind.
|
||||
*/
|
||||
/*
|
||||
TODO:
|
||||
|
||||
- Masq-Adressen statt Paketadresse ausgeben, falls die Masq-Adressen verwendet
|
||||
werden.
|
||||
|
||||
- Masq-Adressen-Verwendung als Option in den Regeln vorsehen
|
||||
|
||||
- TCP-Flags als Regel-Optionen
|
||||
|
||||
- weitere Verfeinerungen fuer Nicht-TCP/IP-Pakete
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#define __NO_VERSION__
|
||||
#include <linux/module.h>
|
||||
#include <linux/isdn.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/in.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
#ifdef CONFIG_ISDN_TIMRU_USE_MASQ
|
||||
#ifdef CONFIG_IP_MASQUERADE
|
||||
#include <net/ip_masq.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "isdn_common.h"
|
||||
#include "isdn_net.h"
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
#include "isdn_ppp.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
|
||||
static int
|
||||
isdn_timru_match(isdn_timeout_rule *this, isdn_timeout_rule *rule);
|
||||
|
||||
|
||||
#define printk_ip(a) printk("%ld.%ld.%ld.%ld",(ntohl(a)>>24)&0xFF,\
|
||||
(ntohl(a)>>16)&0xFF,\
|
||||
(ntohl(a)>>8)&0xFF,\
|
||||
(ntohl(a))&0xFF)
|
||||
#define printk_port(a) printk("%d",ntohs(a))
|
||||
|
||||
|
||||
#define VERBOSE_PRINTK(v, l, p...) { \
|
||||
if(dev->net_verbose >= (v)) { \
|
||||
printk(l ## p); \
|
||||
} else { ; } \
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_net_recalc_timeout(int type, int prot, struct device *ndev, void *buf, ulong arg) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
struct sk_buff *skb;
|
||||
struct iphdr *ip;
|
||||
struct icmphdr *icmp;
|
||||
struct tcphdr *tcp;
|
||||
struct udphdr *udp;
|
||||
#ifdef CONFIG_ISDN_TIMRU_USE_MASQ
|
||||
#ifdef CONFIG_IP_MASQUERADE
|
||||
struct ip_masq *masq;
|
||||
int m_prot;
|
||||
__u32 m_saddr, m_daddr;
|
||||
__u16 m_sport, m_dport;
|
||||
int check_for_masq;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
isdn_timeout_rule match_rule;
|
||||
|
||||
/*
|
||||
char *cbuf;
|
||||
*/
|
||||
int ppp_proto, ppp_hdrlen = 0, new_timeout;
|
||||
|
||||
|
||||
match_rule.type = type;
|
||||
match_rule.protfam = ISDN_TIMRU_PROTFAM_WILDCARD;
|
||||
|
||||
if(dev->net_verbose > 4) {
|
||||
printk(KERN_DEBUG "recalc_timeout:");
|
||||
switch(type) {
|
||||
case ISDN_TIMRU_BRINGUP: printk("BRINGUP, "); break;
|
||||
case ISDN_TIMRU_KEEPUP_IN: printk("KEEPUP_IN, "); break;
|
||||
case ISDN_TIMRU_KEEPUP_OUT: printk("KEEPUP_OUT, "); break;
|
||||
default:
|
||||
printk("ERROR\n");
|
||||
return(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(prot) {
|
||||
case ISDN_TIMRU_PACKET_PPP:
|
||||
case ISDN_TIMRU_PACKET_PPP_NO_HEADER:
|
||||
if(prot == ISDN_TIMRU_PACKET_PPP) {
|
||||
ppp_proto = PPP_PROTOCOL((char *)buf);
|
||||
/*
|
||||
cbuf = (char *)(buf + PPP_HDRLEN);
|
||||
*/
|
||||
} else {
|
||||
ppp_proto = (int)arg;
|
||||
/*
|
||||
cbuf = (char *)buf;
|
||||
*/
|
||||
}
|
||||
|
||||
match_rule.protfam = ISDN_TIMRU_PROTFAM_PPP;
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_WILDCARD;
|
||||
|
||||
switch(ppp_proto) {
|
||||
case PPP_IPCP:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_IPCP;
|
||||
VERBOSE_PRINTK(5, "", "PPP/IPCP\n");
|
||||
break;
|
||||
|
||||
case PPP_IPXCP:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_IPXCP;
|
||||
VERBOSE_PRINTK(5, "", "PPP/IPXCP\n");
|
||||
break;
|
||||
|
||||
case PPP_CCP:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_CCP;
|
||||
VERBOSE_PRINTK(5, "", "PPP/CCP\n");
|
||||
break;
|
||||
|
||||
case PPP_LCP:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_LCP;
|
||||
VERBOSE_PRINTK(5, "", "PPP/LCP\n");
|
||||
break;
|
||||
|
||||
case PPP_PAP:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_PAP;
|
||||
VERBOSE_PRINTK(5, "", "PPP/PAP\n");
|
||||
break;
|
||||
|
||||
case PPP_LQR:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_LQR;
|
||||
VERBOSE_PRINTK(5, "", "PPP/LQR\n");
|
||||
break;
|
||||
|
||||
case PPP_CHAP:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_CHAP;
|
||||
VERBOSE_PRINTK(5, "", "PPP/CHAP\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
match_rule.rule.ppp.protocol = ISDN_TIMRU_PPP_WILDCARD;
|
||||
|
||||
if(dev->net_verbose >= 5) {
|
||||
printk("PPP/? (%x)\n", ppp_proto);
|
||||
isdn_dumppkt("R:", (u_char *)buf, 40, 40);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_PACKET_SKB:
|
||||
skb = (struct sk_buff *)buf;
|
||||
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
if((type == ISDN_TIMRU_BRINGUP ||
|
||||
type == ISDN_TIMRU_KEEPUP_OUT) &&
|
||||
lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
|
||||
/* jump over fake header. */
|
||||
ppp_hdrlen = IPPP_MAX_HEADER;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
switch(ntohs(skb->protocol)) {
|
||||
case ETH_P_IP:
|
||||
/*
|
||||
if(!(ip = skb->ip_hdr))
|
||||
*/
|
||||
ip = (struct iphdr *)(skb->data + ppp_hdrlen);
|
||||
|
||||
match_rule.protfam = ISDN_TIMRU_PROTFAM_IP;
|
||||
match_rule.rule.ip.saddr.s_addr = ip->saddr;
|
||||
match_rule.rule.ip.daddr.s_addr = ip->daddr;
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
|
||||
switch(ip->protocol) {
|
||||
case IPPROTO_ICMP:
|
||||
if(!(icmp = (struct icmphdr *)((unsigned long *)ip+ip->ihl))) {
|
||||
VERBOSE_PRINTK(5, "", "IP/ICMP HDR-ERR\n");
|
||||
} else {
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_ICMP;
|
||||
match_rule.rule.ip.pt.type.from = icmp->type;
|
||||
|
||||
if(dev->net_verbose >= 5) {
|
||||
printk("IP/ICMP ");
|
||||
printk_ip(ip->saddr);
|
||||
printk(" --> ");
|
||||
printk_ip(ip->daddr);
|
||||
printk("/");
|
||||
printk_port(icmp->type);
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_IGMP:
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
VERBOSE_PRINTK(5, "", "IP/IGMP\n");
|
||||
break;
|
||||
|
||||
case IPPROTO_IPIP:
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
VERBOSE_PRINTK(5, "", "IP/IPIP\n");
|
||||
break;
|
||||
|
||||
case IPPROTO_TCP:
|
||||
if(!(tcp = (struct tcphdr *)((unsigned long *)ip+ip->ihl))) {
|
||||
VERBOSE_PRINTK(5, "", "IP/TCP HDR-ERR\n");
|
||||
} else {
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_TCP;
|
||||
match_rule.rule.ip.pt.port.s_from = tcp->source;
|
||||
match_rule.rule.ip.pt.port.d_from = tcp->dest;
|
||||
|
||||
if(dev->net_verbose >= 5) {
|
||||
printk("IP/TCP ");
|
||||
printk_ip(ip->saddr);
|
||||
printk("/");
|
||||
printk_port(tcp->source);
|
||||
printk(" --> ");
|
||||
printk_ip(ip->daddr);
|
||||
printk("/");
|
||||
printk_port(tcp->dest);
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_EGP:
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
VERBOSE_PRINTK(5, "", "IP/EGP\n");
|
||||
break;
|
||||
|
||||
case IPPROTO_PUP:
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
VERBOSE_PRINTK(5, "" "IP/PUP\n");
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
if(!(udp=(struct udphdr *)((unsigned long *)ip+ip->ihl))) {
|
||||
VERBOSE_PRINTK(5, "", "IP/UDP HDR-ERR\n");
|
||||
} else {
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_UDP;
|
||||
match_rule.rule.ip.pt.port.s_from = udp->source;
|
||||
match_rule.rule.ip.pt.port.d_from = udp->dest;
|
||||
|
||||
if(dev->net_verbose >= 5) {
|
||||
printk("IP/UDP ");
|
||||
printk_ip(ip->saddr);
|
||||
printk("/");
|
||||
printk_port(udp->source);
|
||||
printk(" --> ");
|
||||
printk_ip(ip->daddr);
|
||||
printk("/");
|
||||
printk_port(udp->dest);
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_IDP:
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
VERBOSE_PRINTK(5, "", "IP/IDP\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
match_rule.rule.ip.protocol = ISDN_TIMRU_IP_WILDCARD;
|
||||
if(dev->net_verbose >= 5) {
|
||||
printk("IP/? (%x)\n", ip->protocol);
|
||||
isdn_dumppkt("R:", (u_char *)skb, skb->len, 180);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ETH_P_ARP:
|
||||
VERBOSE_PRINTK(5, "", "ARP/?\n");
|
||||
break;
|
||||
|
||||
case ETH_P_IPX:
|
||||
VERBOSE_PRINTK(5, "", "IPX/?\n");
|
||||
break;
|
||||
|
||||
case ETH_P_802_2:
|
||||
VERBOSE_PRINTK(5, "", "802.2/?\n");
|
||||
break;
|
||||
|
||||
case ETH_P_802_3:
|
||||
VERBOSE_PRINTK(5, "", "802.3/?\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
if(dev->net_verbose >= 5) {
|
||||
printk("?/? (%x)\n", ntohs(skb->protocol));
|
||||
isdn_dumppkt("R:", (u_char *)skb, skb->len, 1800);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMRU_USE_MASQ
|
||||
#ifdef CONFIG_IP_MASQUERADE
|
||||
check_for_masq = 0;
|
||||
m_saddr = m_daddr = (__u32)0;
|
||||
m_sport = m_dport = (__u16)0;
|
||||
m_prot = 0;
|
||||
|
||||
switch(match_rule.protfam) {
|
||||
case ISDN_TIMRU_PROTFAM_IP:
|
||||
m_saddr = match_rule.rule.ip.saddr.s_addr;
|
||||
m_daddr = match_rule.rule.ip.daddr.s_addr;
|
||||
|
||||
switch(match_rule.rule.ip.protocol) {
|
||||
case ISDN_TIMRU_IP_TCP:
|
||||
m_prot = IPPROTO_TCP;
|
||||
m_sport = match_rule.rule.ip.pt.port.s_from;
|
||||
m_dport = match_rule.rule.ip.pt.port.d_from;
|
||||
check_for_masq = 1;
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_IP_UDP:
|
||||
m_prot = IPPROTO_UDP;
|
||||
m_sport = match_rule.rule.ip.pt.port.s_from;
|
||||
m_dport = match_rule.rule.ip.pt.port.d_from;
|
||||
check_for_masq = 1;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
#ifdef CONFIG_IP_MASQUERADE_ICMP
|
||||
case ISDN_TIMRU_IP_ICMP:
|
||||
m_sport = match_rule.rule.ip.pt.type.from;
|
||||
m_dport = 0;
|
||||
check_for_masq = 1;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(check_for_masq) {
|
||||
masq = NULL;
|
||||
|
||||
switch(type) {
|
||||
case ISDN_TIMRU_BRINGUP:
|
||||
case ISDN_TIMRU_KEEPUP_OUT:
|
||||
if((masq = ip_masq_in_get_2(m_prot, m_daddr, m_dport, m_saddr, m_sport))) {
|
||||
match_rule.rule.ip.saddr.s_addr = m_saddr;
|
||||
match_rule.rule.ip.daddr.s_addr = m_daddr;
|
||||
switch(m_prot) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
match_rule.rule.ip.pt.port.s_from = m_sport;
|
||||
match_rule.rule.ip.pt.port.d_from = m_dport;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_KEEPUP_IN:
|
||||
if((masq = ip_masq_in_get_2(m_prot, m_saddr, m_sport, m_daddr, m_dport))) {
|
||||
match_rule.rule.ip.saddr.s_addr = m_daddr;
|
||||
match_rule.rule.ip.daddr.s_addr = m_saddr;
|
||||
switch(m_prot) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
match_rule.rule.ip.pt.port.s_from = m_sport;
|
||||
match_rule.rule.ip.pt.port.d_from = m_dport;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(masq && dev->net_verbose >= 5) {
|
||||
printk(KERN_DEBUG "MASQ-TIMRU: ");
|
||||
printk_ip(masq->maddr);
|
||||
printk("/");
|
||||
printk_port(masq->mport);
|
||||
printk(": ");
|
||||
printk_ip(masq->saddr);
|
||||
printk("/");
|
||||
printk_port(masq->sport);
|
||||
printk(" --> ");
|
||||
printk_ip(masq->daddr);
|
||||
printk("/");
|
||||
printk_port(masq->dport);
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
new_timeout = lp->onhtime;
|
||||
|
||||
if(prot && lp->timeout_rules) {
|
||||
isdn_timeout_rule *head, *tor;
|
||||
int pf, found_match, i;
|
||||
|
||||
pf = match_rule.protfam;
|
||||
found_match = 0;
|
||||
|
||||
while(1) {
|
||||
head = tor = lp->timeout_rules->timru[type][pf];
|
||||
i = 0;
|
||||
while(tor) {
|
||||
if((isdn_timru_match(&match_rule, tor) > 0) ^ (tor->neg > 0)) {
|
||||
found_match = 1;
|
||||
new_timeout = tor->timeout;
|
||||
}
|
||||
|
||||
if(found_match) {
|
||||
#ifdef DEBUG_RULES
|
||||
printk(KERN_DEBUG "Rule %d-%d-%d matches\n", type, pf, i);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if(tor->next == head)
|
||||
tor = NULL;
|
||||
else {
|
||||
tor = tor->next;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(! found_match && pf != ISDN_TIMRU_PROTFAM_WILDCARD)
|
||||
pf = ISDN_TIMRU_PROTFAM_WILDCARD;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if(! found_match) {
|
||||
new_timeout = lp->timeout_rules->defaults[type];
|
||||
#ifdef DEBUG_RULES
|
||||
printk("No rule matches: using default\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(type == ISDN_TIMRU_BRINGUP) {
|
||||
if(new_timeout > 0) {
|
||||
lp->huptimeout = new_timeout;
|
||||
lp->huptimer = 0;
|
||||
}
|
||||
} else {
|
||||
if(new_timeout > lp->huptimeout
|
||||
|| lp->huptimeout - lp->huptimer < new_timeout) {
|
||||
lp->huptimeout = new_timeout;
|
||||
lp->huptimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return(new_timeout);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
isdn_timru_match(isdn_timeout_rule *this, isdn_timeout_rule *rule) {
|
||||
if(this->protfam != rule->protfam)
|
||||
return(0);
|
||||
|
||||
switch(rule->protfam) {
|
||||
case ISDN_TIMRU_PROTFAM_WILDCARD:
|
||||
return(1);
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_PROTFAM_PPP:
|
||||
if(rule->rule.ppp.protocol == ISDN_TIMRU_PPP_WILDCARD
|
||||
|| rule->rule.ppp.protocol == this->rule.ppp.protocol)
|
||||
return(1);
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_PROTFAM_IP:
|
||||
if((this->rule.ip.saddr.s_addr & rule->rule.ip.smask.s_addr) != rule->rule.ip.saddr.s_addr
|
||||
|| (this->rule.ip.daddr.s_addr & rule->rule.ip.dmask.s_addr) != rule->rule.ip.daddr.s_addr)
|
||||
return(0);
|
||||
|
||||
if(rule->rule.ip.protocol == ISDN_TIMRU_IP_WILDCARD)
|
||||
return(1);
|
||||
|
||||
if(rule->rule.ip.protocol != this->rule.ip.protocol)
|
||||
return(0);
|
||||
|
||||
switch(rule->rule.ip.protocol) {
|
||||
case ISDN_TIMRU_IP_ICMP:
|
||||
if(this->rule.ip.pt.type.from < rule->rule.ip.pt.type.from
|
||||
|| this->rule.ip.pt.type.from > rule->rule.ip.pt.type.to)
|
||||
return(0);
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_IP_TCP:
|
||||
case ISDN_TIMRU_IP_UDP:
|
||||
if(this->rule.ip.pt.port.s_from < rule->rule.ip.pt.port.s_from
|
||||
|| this->rule.ip.pt.port.s_from > rule->rule.ip.pt.port.s_to)
|
||||
return(0);
|
||||
|
||||
if(this->rule.ip.pt.port.d_from < rule->rule.ip.pt.port.d_from
|
||||
|| this->rule.ip.pt.port.d_from > rule->rule.ip.pt.port.d_to)
|
||||
return(0);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
isdn_timru_rule_equals(isdn_timeout_rule *this, isdn_timeout_rule *rule) {
|
||||
if(this->neg != rule->neg
|
||||
|| this->protfam != rule->protfam)
|
||||
return(0);
|
||||
|
||||
switch(rule->protfam) {
|
||||
case ISDN_TIMRU_PROTFAM_PPP:
|
||||
if(this->rule.ppp.protocol != rule->rule.ppp.protocol)
|
||||
return(0);
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_PROTFAM_IP:
|
||||
if(this->rule.ip.protocol != rule->rule.ip.protocol
|
||||
|| this->rule.ip.saddr.s_addr != rule->rule.ip.saddr.s_addr
|
||||
|| this->rule.ip.smask.s_addr != rule->rule.ip.smask.s_addr
|
||||
|| this->rule.ip.daddr.s_addr != rule->rule.ip.daddr.s_addr
|
||||
|| this->rule.ip.dmask.s_addr != rule->rule.ip.dmask.s_addr)
|
||||
return(0);
|
||||
|
||||
switch(rule->rule.ip.protocol) {
|
||||
case ISDN_TIMRU_IP_ICMP:
|
||||
if(this->rule.ip.pt.type.from != rule->rule.ip.pt.type.from
|
||||
|| this->rule.ip.pt.type.to != rule->rule.ip.pt.type.to)
|
||||
return(0);
|
||||
break;
|
||||
|
||||
case ISDN_TIMRU_IP_TCP:
|
||||
case ISDN_TIMRU_IP_UDP:
|
||||
if(this->rule.ip.pt.port.s_from != rule->rule.ip.pt.port.s_from
|
||||
|| this->rule.ip.pt.port.s_to != rule->rule.ip.pt.port.s_to
|
||||
|| this->rule.ip.pt.port.d_from != rule->rule.ip.pt.port.d_from
|
||||
|| this->rule.ip.pt.port.d_to != rule->rule.ip.pt.port.d_to)
|
||||
return(0);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_alloc_timeout_rules(struct device *ndev) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
int i, j;
|
||||
ulong flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if(!(lp->timeout_rules = (struct isdn_timeout_rules *)kmalloc(sizeof(struct isdn_timeout_rules), GFP_KERNEL))) {
|
||||
restore_flags(flags);
|
||||
printk(KERN_WARNING "isdn_timru: failed to allocate memory.\n");
|
||||
return(-ENOMEM);
|
||||
}
|
||||
|
||||
memset((char *)lp->timeout_rules, 0, sizeof(struct isdn_timeout_rules));
|
||||
|
||||
for(i = 0; i < ISDN_TIMRU_NUM_CHECK; i++) {
|
||||
lp->timeout_rules->defaults[i] = lp->onhtime;
|
||||
for(j = 0; j < ISDN_TIMRU_NUM_PROTFAM; j++)
|
||||
lp->timeout_rules->timru[i][j] = NULL;
|
||||
}
|
||||
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_free_timeout_rules(struct device *ndev) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
isdn_timeout_rule *head, *this, *next;
|
||||
int i, j;
|
||||
ulong flags;
|
||||
|
||||
if(!lp->timeout_rules)
|
||||
return(-1);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
for(i = 0; i < ISDN_TIMRU_NUM_CHECK; i++)
|
||||
for(j = 0; j < ISDN_TIMRU_NUM_CHECK; j++)
|
||||
if((head = lp->timeout_rules->timru[i][j])) {
|
||||
this = head;
|
||||
do {
|
||||
next = this->next;
|
||||
kfree(this);
|
||||
} while(next == head);
|
||||
}
|
||||
|
||||
kfree(lp->timeout_rules);
|
||||
lp->timeout_rules = NULL;
|
||||
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_add_rule(int where, struct device *ndev, isdn_timeout_rule *rule) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
isdn_timeout_rule **head;
|
||||
ulong flags;
|
||||
int ret;
|
||||
|
||||
if(!lp->timeout_rules)
|
||||
if((ret = isdn_timru_alloc_timeout_rules(ndev)))
|
||||
return(ret);
|
||||
|
||||
if(rule->timeout < 0)
|
||||
return(-EINVAL);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
head = &(lp->timeout_rules->timru[rule->type][rule->protfam]);
|
||||
|
||||
if(! *head)
|
||||
rule->next = rule->prev = *head = rule;
|
||||
else {
|
||||
rule->next = *head;
|
||||
rule->prev = (*head)->prev;
|
||||
(*head)->prev->next = rule;
|
||||
(*head)->prev = rule;
|
||||
|
||||
if(where == 0) /* add to head of chain */
|
||||
*head = rule;
|
||||
}
|
||||
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_del_rule(struct device *ndev, isdn_timeout_rule *rule) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
isdn_timeout_rule **head, *this;
|
||||
ulong flags;
|
||||
|
||||
if(!lp->timeout_rules)
|
||||
return(-EINVAL);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
head = &(lp->timeout_rules->timru[rule->type][rule->protfam]);
|
||||
|
||||
if(! *head) {
|
||||
restore_flags(flags);
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
this = *head;
|
||||
do {
|
||||
if(isdn_timru_rule_equals(this, rule)) {
|
||||
if(this->next != this) { /* more than one rule */
|
||||
this->prev->next = this->next;
|
||||
this->next->prev = this->prev;
|
||||
|
||||
if(this == *head)
|
||||
*head = this->next;
|
||||
} else
|
||||
*head = NULL;
|
||||
|
||||
kfree(this);
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
} else
|
||||
this = this->next;
|
||||
} while(this == *head);
|
||||
|
||||
restore_flags(flags);
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_set_default(int type, struct device *ndev, int def) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
ulong flags;
|
||||
int ret;
|
||||
|
||||
if(!lp->timeout_rules)
|
||||
if((ret = isdn_timru_alloc_timeout_rules(ndev)))
|
||||
return(ret);
|
||||
|
||||
if(def < 0)
|
||||
return(-EINVAL);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
lp->timeout_rules->defaults[type] = def;
|
||||
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_get_rule(struct device *ndev, isdn_timeout_rule **rule, int i, int j, int k) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
isdn_timeout_rule *head, *this;
|
||||
int l;
|
||||
ulong flags;
|
||||
|
||||
if(!lp->timeout_rules
|
||||
|| i < 0 || i > ISDN_TIMRU_NUM_CHECK
|
||||
|| j < 0 || j > ISDN_TIMRU_NUM_PROTFAM
|
||||
|| k < 0)
|
||||
return(-EINVAL);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
if(!(this = head = lp->timeout_rules->timru[i][j])) {
|
||||
restore_flags(flags);
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
for(l = 0; l < k; l++) {
|
||||
if(this->next == head) {
|
||||
restore_flags(flags);
|
||||
return(-EINVAL);
|
||||
}
|
||||
this = this->next;
|
||||
}
|
||||
|
||||
*rule = this;
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_get_default(int type, struct device *ndev, int *ret) {
|
||||
isdn_net_local *lp = (isdn_net_local *)ndev->priv;
|
||||
ulong flags;
|
||||
|
||||
if(!lp->timeout_rules)
|
||||
return(-EINVAL);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
*ret = lp->timeout_rules->defaults[type];
|
||||
|
||||
restore_flags(flags);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_ioctl_add_rule(isdn_ioctl_timeout_rule *iorule)
|
||||
{
|
||||
isdn_net_dev *p = isdn_net_findif(iorule->name);
|
||||
isdn_timeout_rule *r;
|
||||
|
||||
if(p) {
|
||||
if(iorule->where < 0) { /* set default */
|
||||
return(isdn_timru_set_default(iorule->type, &p->dev, iorule->defval));
|
||||
} else {
|
||||
if(!(r = (isdn_timeout_rule *) kmalloc(sizeof(isdn_timeout_rule), GFP_KERNEL)))
|
||||
return(-ENOMEM);
|
||||
memcpy((char *)r, (char *)&iorule->rule, sizeof(isdn_timeout_rule));
|
||||
return(isdn_timru_add_rule(iorule->where, &p->dev, r));
|
||||
}
|
||||
}
|
||||
return(-ENODEV);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_ioctl_del_rule(isdn_ioctl_timeout_rule *iorule)
|
||||
{
|
||||
isdn_net_dev *p = isdn_net_findif(iorule->name);
|
||||
isdn_timeout_rule *r;
|
||||
|
||||
if(p) {
|
||||
if(!(r = (isdn_timeout_rule *) kmalloc(sizeof(isdn_timeout_rule), GFP_KERNEL)))
|
||||
return(-ENOMEM);
|
||||
memcpy((char *)r, (char *)&iorule->rule, sizeof(isdn_timeout_rule));
|
||||
return(isdn_timru_del_rule(&p->dev, r));
|
||||
}
|
||||
return(-ENODEV);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isdn_timru_ioctl_get_rule(isdn_ioctl_timeout_rule *iorule)
|
||||
{
|
||||
int ret, def;
|
||||
isdn_net_dev *p = isdn_net_findif(iorule->name);
|
||||
isdn_timeout_rule *r;
|
||||
|
||||
if(p) {
|
||||
if(iorule->where < 0) { /* get default */
|
||||
if((ret = isdn_timru_get_default(iorule->type, &p->dev, &def)) < 0)
|
||||
return(ret);
|
||||
|
||||
iorule->protfam = p->local->huptimer;
|
||||
iorule->index = p->local->huptimeout;
|
||||
iorule->defval = def;
|
||||
} else {
|
||||
if(isdn_timru_get_rule(&p->dev, &r, iorule->type, iorule->protfam, iorule->index))
|
||||
return(-ENOMEM);
|
||||
|
||||
memcpy((char *)&iorule->rule, (char *)r, sizeof(isdn_timeout_rule));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
return(-ENODEV);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -27,6 +27,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.37 1998/02/22 19:45:24 fritz
|
||||
* Some changes regarding V.110
|
||||
*
|
||||
* Revision 1.36 1998/02/20 17:35:55 fritz
|
||||
* Added V.110 stuff.
|
||||
*
|
||||
|
@ -206,6 +209,11 @@
|
|||
#define IIOCNETDIL _IO('I',20)
|
||||
#define IIOCGETCPS _IO('I',21)
|
||||
#define IIOCGETDVR _IO('I',22)
|
||||
#define IIOCNETARU _IO('I',23)
|
||||
#define IIOCNETDRU _IO('I',24)
|
||||
#define IIOCNETGRU _IO('I',25)
|
||||
|
||||
#define IIOCNETBUD _IO('I',26)
|
||||
|
||||
#define IIOCNETALN _IO('I',32)
|
||||
#define IIOCNETDLN _IO('I',33)
|
||||
|
@ -281,6 +289,9 @@ typedef struct {
|
|||
int pppbind; /* ippp device for bindings */
|
||||
int chargeint; /* Use fixed charge interval length */
|
||||
int triggercps; /* BogoCPS needed for triggering slave */
|
||||
int dialtimeout; /* Dial-Timeout */
|
||||
int dialwait; /* Time to wait after failed dial */
|
||||
int stopped; /* Flag: Stopped */
|
||||
} isdn_net_ioctl_cfg;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
@ -397,6 +408,9 @@ typedef struct {
|
|||
#define ISDN_NET_TMP 0x10 /* tmp interface until getting an IP */
|
||||
#define ISDN_NET_DYNAMIC 0x20 /* this link is dynamically allocated */
|
||||
#endif
|
||||
|
||||
#define ISDN_NET_STOPPED 0x40 /* this interface is stopped */
|
||||
|
||||
#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
|
||||
|
||||
/* Phone-list-element */
|
||||
|
@ -405,6 +419,28 @@ typedef struct {
|
|||
char num[ISDN_MSNLEN];
|
||||
} isdn_net_phone;
|
||||
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
#include <linux/isdn_timru.h>
|
||||
|
||||
struct isdn_timeout_rules {
|
||||
isdn_timeout_rule *timru[ISDN_TIMRU_NUM_CHECK][ISDN_TIMRU_NUM_PROTFAM];
|
||||
int defaults[ISDN_TIMRU_NUM_CHECK];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
#include <linux/isdn_budget.h>
|
||||
|
||||
typedef struct {
|
||||
int amount, /* usable amount */
|
||||
used, /* used so far */
|
||||
period, /* length of period */
|
||||
notified; /* flag: notified user about low budget */
|
||||
time_t period_started, /* when did the current period start? */
|
||||
last_check; /* last time checked */
|
||||
} isdn_budget;
|
||||
#endif
|
||||
|
||||
/*
|
||||
Principles when extending structures for generic encapsulation protocol
|
||||
("concap") support:
|
||||
|
@ -487,6 +523,17 @@ typedef struct isdn_net_local_s {
|
|||
struct device *,
|
||||
unsigned char *);
|
||||
int pppbind; /* ippp device for bindings */
|
||||
int dialtimeout; /* How long shall we try on dialing? (jiffies) */
|
||||
int dialwait; /* How long shall we wait after failed attempt? (jiffies) */
|
||||
ulong dialstarted; /* jiffies of first dialing-attempt */
|
||||
ulong dialwait_timer; /* jiffies of earliest next dialing-attempt */
|
||||
int huptimeout; /* How long will the connection be up? (seconds) */
|
||||
#ifdef CONFIG_ISDN_TIMEOUT_RULES
|
||||
struct isdn_timeout_rules *timeout_rules;
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_BUDGET
|
||||
isdn_budget budget [ISDN_BUDGET_NUM_BUDGET];
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_X25
|
||||
struct concap_device_ops *dops; /* callbacks used by encapsulator */
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* isdn_budget.h
|
||||
*
|
||||
* Linux ISDN subsystem, budget-accounting for network interfaces.
|
||||
*
|
||||
* Copyright 1997 by Christian Lademann <cal@zls.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
30.06.97:cal:angelegt
|
||||
04.11.97:cal:budget.period: int --> time_t
|
||||
*/
|
||||
|
||||
#ifndef __isdn_budget_h__
|
||||
#define __isdn_budget_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define ISDN_BUDGET_DIAL 0
|
||||
#define ISDN_BUDGET_CHARGE 1
|
||||
#define ISDN_BUDGET_ONLINE 2
|
||||
#define ISDN_BUDGET_NUM_BUDGET 3
|
||||
|
||||
#define ISDN_BUDGET_INIT 0
|
||||
#define ISDN_BUDGET_CHECK_DIAL 1
|
||||
#define ISDN_BUDGET_CHECK_CHARGE 2
|
||||
#define ISDN_BUDGET_CHECK_ONLINE 3
|
||||
#define ISDN_BUDGET_START_ONLINE 10
|
||||
|
||||
#define ISDN_BUDGET_SET_BUDGET 0
|
||||
#define ISDN_BUDGET_GET_BUDGET 1
|
||||
|
||||
typedef struct {
|
||||
char name [9]; /* Interface */
|
||||
int command, /* subcommand */
|
||||
budget, /* budget-nr. */
|
||||
amount, /* set/get budget-amount */
|
||||
used; /* set/get used amount */
|
||||
time_t period, /* set/get length of period */
|
||||
period_started; /* set/get startpoint of period */
|
||||
} isdn_ioctl_budget;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
extern int isdn_net_budget(int, struct device *);
|
||||
extern int isdn_budget_ioctl(isdn_ioctl_budget *);
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __isdn_budget_h__ */
|
|
@ -0,0 +1,119 @@
|
|||
/* isdn_timru.h
|
||||
*
|
||||
* Linux ISDN subsystem, timeout-rules for network interfaces.
|
||||
*
|
||||
* Copyright 1997 by Christian Lademann <cal@zls.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
02.06.97:cal:ISDN_TIMRU_PACKET_NONE def., ISDN_TIMRU_PACKET_* inkr.
|
||||
*/
|
||||
|
||||
#ifndef __isdn_timru_h__
|
||||
#define __isdn_timru_h__
|
||||
|
||||
#define ISDN_TIMRU_PACKET_NONE 0
|
||||
#define ISDN_TIMRU_PACKET_SKB 1
|
||||
#define ISDN_TIMRU_PACKET_PPP 2
|
||||
#define ISDN_TIMRU_PACKET_PPP_NO_HEADER 3
|
||||
|
||||
#define ISDN_TIMRU_BRINGUP 0
|
||||
#define ISDN_TIMRU_KEEPUP_IN 1
|
||||
#define ISDN_TIMRU_KEEPUP_OUT 2
|
||||
#define ISDN_TIMRU_BRINGDOWN 3
|
||||
#define ISDN_TIMRU_NUM_CHECK 4
|
||||
|
||||
#define ISDN_TIMRU_PROTFAM_WILDCARD 0
|
||||
#define ISDN_TIMRU_PROTFAM_IP 1
|
||||
#define ISDN_TIMRU_PROTFAM_PPP 2
|
||||
#define ISDN_TIMRU_PROTFAM_IPX 3
|
||||
#define ISDN_TIMRU_NUM_PROTFAM 4
|
||||
|
||||
#define ISDN_TIMRU_IP_WILDCARD 0
|
||||
#define ISDN_TIMRU_IP_ICMP 1
|
||||
#define ISDN_TIMRU_IP_TCP 2
|
||||
#define ISDN_TIMRU_IP_UDP 3
|
||||
|
||||
#define ISDN_TIMRU_PPP_WILDCARD 0
|
||||
#define ISDN_TIMRU_PPP_IPCP 1
|
||||
#define ISDN_TIMRU_PPP_IPXCP 2
|
||||
#define ISDN_TIMRU_PPP_CCP 3
|
||||
#define ISDN_TIMRU_PPP_LCP 4
|
||||
#define ISDN_TIMRU_PPP_PAP 5
|
||||
#define ISDN_TIMRU_PPP_LQR 6
|
||||
#define ISDN_TIMRU_PPP_CHAP 7
|
||||
|
||||
typedef struct {
|
||||
struct in_addr saddr, /* Source Address */
|
||||
smask, /* Source Subnetmask */
|
||||
daddr, /* Dest. Address */
|
||||
dmask; /* Dest. Subnetmask */
|
||||
ushort protocol; /* TCP, UDP, ... */
|
||||
union {
|
||||
struct {
|
||||
__u16 s_from, /* Source Port */
|
||||
s_to,
|
||||
d_from,
|
||||
d_to;
|
||||
} port;
|
||||
struct {
|
||||
__u8 from, /* ICMP-Type */
|
||||
to;
|
||||
} type;
|
||||
} pt;
|
||||
} isdn_timeout_rule_ip;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ushort protocol; /* IPCP, LCP, ... */
|
||||
} isdn_timeout_rule_ppp;
|
||||
|
||||
|
||||
typedef struct isdn_timeout_rule_s {
|
||||
struct isdn_timeout_rule_s *next, /* Pointer to next rule */
|
||||
*prev; /* Pointer to previous rule */
|
||||
ushort type, /* BRINGUP, KEEPUP_*, ... */
|
||||
neg;
|
||||
int timeout; /* Timeout value */
|
||||
ushort protfam; /* IP, IPX, PPP, ... */
|
||||
union {
|
||||
isdn_timeout_rule_ip ip; /* IP-Rule */
|
||||
isdn_timeout_rule_ppp ppp; /* PPP-Rule */
|
||||
} rule; /* Prot.-specific rule */
|
||||
} isdn_timeout_rule;
|
||||
|
||||
|
||||
typedef struct {
|
||||
char name [9]; /* Interface */
|
||||
int where, /* 0/1: add to start/end of list, -1: handle default */
|
||||
type,
|
||||
protfam,
|
||||
index,
|
||||
defval;
|
||||
isdn_timeout_rule rule; /* Rule */
|
||||
} isdn_ioctl_timeout_rule;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
extern int isdn_net_recalc_timeout(int, int, struct device *, void *, ulong);
|
||||
extern int isdn_timru_alloc_timeout_rules(struct device *);
|
||||
extern int isdn_timru_ioctl_add_rule(isdn_ioctl_timeout_rule *);
|
||||
extern int isdn_timru_ioctl_del_rule(isdn_ioctl_timeout_rule *);
|
||||
extern int isdn_timru_ioctl_get_rule(isdn_ioctl_timeout_rule *);
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __isdn_timru_h__ */
|
Loading…
Reference in New Issue