Commit 36743e75 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: cleanup ISDN net / ioctl code

Try to convert the setup of network interfaces into something readable.
In particular, use dummy inline functions to get rid of
#ifdef CONFIG_ISDN_* spread all over the place everywhere and separate 
stuff into smaller functions.
parent 67cba4d4
...@@ -106,3 +106,39 @@ struct concap_proto * isdn_concap_new( int encap ) ...@@ -106,3 +106,39 @@ struct concap_proto * isdn_concap_new( int encap )
} }
return NULL; return NULL;
} }
void isdn_x25_encap_changed(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg)
{
isdn_net_local *lp = &p->local;
struct concap_proto * cprot = p -> cprot;
unsigned long flags;
/* delete old encapsulation protocol if present ... */
save_flags(flags);
cli(); /* avoid races with incoming events trying to
call cprot->pops methods */
if( cprot && cprot -> pops )
cprot -> pops -> proto_del ( cprot );
p -> cprot = NULL;
lp -> dops = NULL;
restore_flags(flags);
/* ... , prepare for configuration of new one ... */
switch ( cfg -> p_encap ){
case ISDN_NET_ENCAP_X25IFACE:
lp -> dops = &isdn_concap_reliable_dl_dops;
}
/* ... and allocate new one ... */
p -> cprot = isdn_concap_new( cfg -> p_encap );
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
/* the protocol is not configured yet; this will
happen later when isdn_net_reset() is called */
}
int isdn_x25_setup_dev(isdn_net_dev *p)
{
p->dev.type = ARPHRD_X25; /* change ARP type */
p->dev.addr_len = 0;
return 0;
}
...@@ -9,6 +9,27 @@ ...@@ -9,6 +9,27 @@
extern struct concap_device_ops isdn_concap_reliable_dl_dops; extern struct concap_device_ops isdn_concap_reliable_dl_dops;
extern struct concap_device_ops isdn_concap_demand_dial_dops; extern struct concap_device_ops isdn_concap_demand_dial_dops;
extern struct concap_proto * isdn_concap_new( int );
struct concap_proto *isdn_concap_new(int);
#ifdef CONFIG_ISDN_X25
void isdn_x25_encap_changed(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg);
int isdn_x25_setup_dev(isdn_net_dev *p);
#else
static inline void
isdn_x25_encap_changed(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg)
{
}
static inline int
isdn_x25_setup_dev(isdn_net_dev *p)
{
printk(KERN_WARNING "ISDN: SyncPPP support not configured\n");
return -EINVAL;
}
#endif
...@@ -30,13 +30,9 @@ ...@@ -30,13 +30,9 @@
#include <linux/inetdevice.h> #include <linux/inetdevice.h>
#include "isdn_common.h" #include "isdn_common.h"
#include "isdn_net.h" #include "isdn_net.h"
#ifdef CONFIG_ISDN_PPP
#include "isdn_ppp.h" #include "isdn_ppp.h"
#endif
#ifdef CONFIG_ISDN_X25
#include <linux/concap.h> #include <linux/concap.h>
#include "isdn_concap.h" #include "isdn_concap.h"
#endif
enum { enum {
ST_NULL, ST_NULL,
...@@ -1754,6 +1750,13 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb) ...@@ -1754,6 +1750,13 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
int isdn_ciscohdlck_setup_dev(isdn_net_dev *p)
{
p->dev.do_ioctl = isdn_ciscohdlck_dev_ioctl;
return 0;
}
/* /*
* Got a packet from ISDN-Channel. * Got a packet from ISDN-Channel.
*/ */
...@@ -2586,7 +2589,7 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -2586,7 +2589,7 @@ isdn_net_new(char *name, struct net_device *master)
netdev->local.isdn_slot = -1; netdev->local.isdn_slot = -1;
netdev->local.pre_device = -1; netdev->local.pre_device = -1;
netdev->local.pre_channel = -1; netdev->local.pre_channel = -1;
netdev->local.exclusive = -1; netdev->local.exclusive = 0;
netdev->local.ppp_slot = -1; netdev->local.ppp_slot = -1;
netdev->local.pppbind = -1; netdev->local.pppbind = -1;
skb_queue_head_init(&netdev->local.super_tx_queue); skb_queue_head_init(&netdev->local.super_tx_queue);
...@@ -2638,163 +2641,180 @@ isdn_net_newslave(char *parm) ...@@ -2638,163 +2641,180 @@ isdn_net_newslave(char *parm)
return isdn_net_new(p+1, &m->dev); return isdn_net_new(p+1, &m->dev);
} }
/* static int
* Set interface-parameters. isdn_net_set_encap(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg)
* Always set all parameters, so the user-level application is responsible
* for not overwriting existing setups. It has to get the current
* setup first, if only selected parameters are to be changed.
*/
int
isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
{ {
isdn_net_dev *p = isdn_net_findif(cfg->name);
ulong features;
int i;
int drvidx;
int chidx;
char drvid[25];
#ifdef CONFIG_ISDN_X25
ulong flags;
#endif
if (p) {
isdn_net_local *lp = &p->local; isdn_net_local *lp = &p->local;
int retval;
/* See if any registered driver supports the features we want */ if (lp->p_encap == cfg->p_encap){
features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) | /* no change */
((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT); retval = 0;
for (i = 0; i < ISDN_MAX_DRIVERS; i++) goto out;
if (dev->drv[i])
if ((dev->drv[i]->interface->features & features) == features)
break;
if (i == ISDN_MAX_DRIVERS) {
printk(KERN_WARNING "isdn_net: No driver with selected features\n");
return -ENODEV;
} }
if (lp->p_encap != cfg->p_encap){
#ifdef CONFIG_ISDN_X25
struct concap_proto * cprot = p -> cprot;
#endif
if (isdn_net_device_started(p)) { if (isdn_net_device_started(p)) {
printk(KERN_WARNING "%s: cannot change encap when if is up\n", retval = -EBUSY;
lp->name); goto out;
return -EBUSY;
}
#ifdef CONFIG_ISDN_X25
/* delete old encapsulation protocol if present ... */
save_flags(flags);
cli(); /* avoid races with incoming events trying to
call cprot->pops methods */
if( cprot && cprot -> pops )
cprot -> pops -> proto_del ( cprot );
p -> cprot = NULL;
lp -> dops = NULL;
restore_flags(flags);
/* ... , prepare for configuration of new one ... */
switch ( cfg -> p_encap ){
case ISDN_NET_ENCAP_X25IFACE:
lp -> dops = &isdn_concap_reliable_dl_dops;
}
/* ... and allocate new one ... */
p -> cprot = isdn_concap_new( cfg -> p_encap );
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
/* the protocol is not configured yet; this will
happen later when isdn_net_reset() is called */
#endif
} }
isdn_x25_encap_changed(p, cfg);
switch ( cfg->p_encap ) { switch ( cfg->p_encap ) {
case ISDN_NET_ENCAP_SYNCPPP: case ISDN_NET_ENCAP_SYNCPPP:
#ifndef CONFIG_ISDN_PPP retval = isdn_ppp_setup_dev(p);
printk(KERN_WARNING "%s: SyncPPP support not configured\n",
lp->name);
return -EINVAL;
#else
p->dev.type = ARPHRD_PPP; /* change ARP type */
p->dev.addr_len = 0;
p->dev.do_ioctl = isdn_ppp_dev_ioctl;
#endif
break; break;
case ISDN_NET_ENCAP_X25IFACE: case ISDN_NET_ENCAP_X25IFACE:
#ifndef CONFIG_ISDN_X25 retval = isdn_x25_setup_dev(p);
printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
p->local.name);
return -EINVAL;
#else
p->dev.type = ARPHRD_X25; /* change ARP type */
p->dev.addr_len = 0;
#endif
break; break;
case ISDN_NET_ENCAP_CISCOHDLCK: case ISDN_NET_ENCAP_CISCOHDLCK:
p->dev.do_ioctl = isdn_ciscohdlck_dev_ioctl; retval = isdn_ciscohdlck_setup_dev(p);
break; break;
default: default:
if( cfg->p_encap >= 0 && if (cfg->p_encap < 0 ||
cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP ) cfg->p_encap > ISDN_NET_ENCAP_MAX_ENCAP) {
retval = -EINVAL;
break; break;
printk(KERN_WARNING
"%s: encapsulation protocol %d not supported\n",
p->local.name, cfg->p_encap);
return -EINVAL;
} }
if (strlen(cfg->drvid)) { retval = 0;
/* A bind has been requested ... */ }
char *c, if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
*e; p->dev.hard_header = NULL;
p->dev.hard_header_cache = NULL;
p->dev.header_cache_update = NULL;
p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
} else {
p->dev.hard_header = isdn_net_header;
if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
p->dev.hard_header_cache = lp->org_hhc;
p->dev.header_cache_update = lp->org_hcu;
p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
} else {
p->dev.hard_header_cache = NULL;
p->dev.header_cache_update = NULL;
p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
}
}
drvidx = -1; lp->p_encap = cfg->p_encap;
chidx = -1;
strcpy(drvid, cfg->drvid); out:
if ((c = strchr(drvid, ','))) { return retval;
/* The channel-number is appended to the driver-Id with a comma */ }
chidx = (int) simple_strtoul(c + 1, &e, 10);
if (e == c) static int
chidx = -1; isdn_net_bind(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg)
*c = '\0'; {
isdn_net_local *lp = &p->local;
int i, retval;
int drvidx = -1;
int chidx = -1;
char drvid[25];
strncpy(drvid, cfg->drvid, 24);
drvid[24] = 0;
if (cfg->exclusive && !strlen(drvid)) {
/* If we want to bind exclusively, need to specify drv/chan */
retval = -ENODEV;
goto out;
} }
for (i = 0; i < ISDN_MAX_DRIVERS; i++) if (strlen(drvid)) {
/* A bind has been requested ... */
char *c = strchr(drvid, ',');
if (!c) {
retval = -ENODEV;
goto out;
}
/* The channel-number is appended to the driver-Id with a comma */
*c = 0;
chidx = simple_strtol(c + 1, NULL, 10);
for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
/* Lookup driver-Id in array */ /* Lookup driver-Id in array */
if (!(strcmp(dev->drvid[i], drvid))) { if (!strcmp(dev->drvid[i], drvid)) {
drvidx = i; drvidx = i;
break; break;
} }
if ((drvidx == -1) || (chidx == -1)) }
if (drvidx == -1 || chidx == -1) {
/* Either driver-Id or channel-number invalid */ /* Either driver-Id or channel-number invalid */
return -ENODEV; retval = -ENODEV;
} else { goto out;
/* Parameters are valid, so get them */
drvidx = lp->pre_device;
chidx = lp->pre_channel;
} }
if (cfg->exclusive > 0) { }
unsigned long flags; if (cfg->exclusive == lp->exclusive &&
drvidx == lp->pre_device && chidx == lp->pre_channel) {
/* no change */
retval = 0;
goto out;
}
if (lp->exclusive) {
isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
lp->exclusive = 0;
}
if (cfg->exclusive) {
/* If binding is exclusive, try to grab the channel */ /* If binding is exclusive, try to grab the channel */
save_flags(flags); i = isdn_get_free_slot(ISDN_USAGE_NET, lp->l2_proto,
if ((i = isdn_get_free_slot(ISDN_USAGE_NET, lp->l3_proto, drvidx, chidx, cfg->eaz);
lp->l2_proto, lp->l3_proto, drvidx, if (i < 0) {
chidx, lp->msn)) < 0) {
/* Grab failed, because desired channel is in use */ /* Grab failed, because desired channel is in use */
lp->exclusive = -1; retval = -EBUSY;
restore_flags(flags); goto out;
return -EBUSY;
} }
/* All went ok, so update isdninfo */ /* All went ok, so update isdninfo */
isdn_slot_set_usage(i, ISDN_USAGE_EXCLUSIVE); isdn_slot_set_usage(i, ISDN_USAGE_EXCLUSIVE);
restore_flags(flags); lp->exclusive = 1;
lp->exclusive = i;
} else {
/* Non-exclusive binding or unbind. */
lp->exclusive = -1;
if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
drvidx = -1;
chidx = -1;
} }
}
strcpy(lp->msn, cfg->eaz);
lp->pre_device = drvidx; lp->pre_device = drvidx;
lp->pre_channel = chidx; lp->pre_channel = chidx;
retval = 0;
out:
return retval;
}
/*
* Set interface-parameters.
* Always set all parameters, so the user-level application is responsible
* for not overwriting existing setups. It has to get the current
* setup first, if only selected parameters are to be changed.
*/
int
isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
{
isdn_net_dev *p = isdn_net_findif(cfg->name);
isdn_net_local *lp = &p->local;
ulong features;
int i, retval;
if (!p) {
retval = -ENODEV;
goto out;
}
/* See if any registered driver supports the features we want */
features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
if (dev->drv[i] &&
(dev->drv[i]->interface->features & features) == features)
break;
if (i == ISDN_MAX_DRIVERS) {
printk(KERN_WARNING "isdn_net: No driver with selected features\n");
retval = -ENODEV;
goto out;
}
retval = isdn_net_set_encap(p, cfg);
if (retval)
goto out;
retval = isdn_net_bind(p, cfg);
if (retval)
goto out;
strncpy(lp->msn, cfg->eaz, ISDN_MSNLEN-1);
lp->msn[ISDN_MSNLEN-1] = 0;
lp->onhtime = cfg->onhtime; lp->onhtime = cfg->onhtime;
lp->charge = cfg->charge; lp->charge = cfg->charge;
lp->l2_proto = cfg->l2_proto; lp->l2_proto = cfg->l2_proto;
...@@ -2829,50 +2849,31 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2829,50 +2849,31 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
} }
lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */ lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) { if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
/* old isdnctrl version, where only 0 or 1 is given */ retval = -EINVAL;
printk(KERN_WARNING goto out;
"Old isdnctrl version detected! Please update.\n");
lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
} }
else {
lp->flags |= cfg->dialmode; /* turn on selected bits */ lp->flags |= cfg->dialmode; /* turn on selected bits */
}
if (cfg->chargehup) if (cfg->chargehup)
lp->hupflags |= ISDN_CHARGEHUP; lp->hupflags |= ISDN_CHARGEHUP;
else else
lp->hupflags &= ~ISDN_CHARGEHUP; lp->hupflags &= ~ISDN_CHARGEHUP;
if (cfg->ihup) if (cfg->ihup)
lp->hupflags |= ISDN_INHUP; lp->hupflags |= ISDN_INHUP;
else else
lp->hupflags &= ~ISDN_INHUP; lp->hupflags &= ~ISDN_INHUP;
if (cfg->chargeint > 10) { if (cfg->chargeint > 10) {
lp->chargeint = cfg->chargeint * HZ; lp->chargeint = cfg->chargeint * HZ;
lp->charge_state = ST_CHARGE_HAVE_CINT; lp->charge_state = ST_CHARGE_HAVE_CINT;
lp->hupflags |= ISDN_MANCHARGE; lp->hupflags |= ISDN_MANCHARGE;
} }
if (cfg->p_encap != lp->p_encap) { retval = 0;
if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
p->dev.hard_header = NULL; out:
p->dev.hard_header_cache = NULL; return retval;
p->dev.header_cache_update = NULL;
p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
} else {
p->dev.hard_header = isdn_net_header;
if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
p->dev.hard_header_cache = lp->org_hhc;
p->dev.header_cache_update = lp->org_hcu;
p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
} else {
p->dev.hard_header_cache = NULL;
p->dev.header_cache_update = NULL;
p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
}
}
}
lp->p_encap = cfg->p_encap;
return 0;
}
return -ENODEV;
} }
/* /*
...@@ -2882,10 +2883,11 @@ int ...@@ -2882,10 +2883,11 @@ int
isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
{ {
isdn_net_dev *p = isdn_net_findif(cfg->name); isdn_net_dev *p = isdn_net_findif(cfg->name);
if (p) {
isdn_net_local *lp = &p->local; isdn_net_local *lp = &p->local;
if (!p)
return -ENODEV;
strcpy(cfg->eaz, lp->msn); strcpy(cfg->eaz, lp->msn);
cfg->exclusive = lp->exclusive; cfg->exclusive = lp->exclusive;
if (lp->pre_device >= 0) { if (lp->pre_device >= 0) {
...@@ -2925,9 +2927,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2925,9 +2927,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name); strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
else else
cfg->master[0] = '\0'; cfg->master[0] = '\0';
return 0; return 0;
}
return -ENODEV;
} }
/* /*
...@@ -3119,7 +3120,7 @@ isdn_net_realrm(isdn_net_dev *p) ...@@ -3119,7 +3120,7 @@ isdn_net_realrm(isdn_net_dev *p)
/* Free all phone-entries */ /* Free all phone-entries */
isdn_net_rmallphone(p); isdn_net_rmallphone(p);
/* If interface is bound exclusive, free channel-usage */ /* If interface is bound exclusive, free channel-usage */
if (p->local.exclusive != -1) if (p->local.exclusive)
isdn_unexclusive_channel(p->local.pre_device, p->local.pre_channel); isdn_unexclusive_channel(p->local.pre_device, p->local.pre_channel);
if (p->local.master) { if (p->local.master) {
/* It's a slave-device, so update master's slave-pointer if necessary */ /* It's a slave-device, so update master's slave-pointer if necessary */
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/ppp-comp.h> #include <linux/ppp-comp.h>
#include <linux/if_arp.h>
#include "isdn_common.h" #include "isdn_common.h"
#include "isdn_ppp.h" #include "isdn_ppp.h"
...@@ -2901,3 +2902,12 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_ ...@@ -2901,3 +2902,12 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_
} }
return -EINVAL; return -EINVAL;
} }
int isdn_ppp_setup_dev(isdn_net_dev *p)
{
p->dev.type = ARPHRD_PPP; /* change ARP type */
p->dev.addr_len = 0;
p->dev.do_ioctl = isdn_ppp_dev_ioctl;
return 0;
}
...@@ -20,13 +20,27 @@ extern int isdn_ppp_free(isdn_net_local *); ...@@ -20,13 +20,27 @@ extern int isdn_ppp_free(isdn_net_local *);
extern int isdn_ppp_bind(isdn_net_local *); extern int isdn_ppp_bind(isdn_net_local *);
extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *); extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *); extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
extern int isdn_ppp_dial_slave(char *); extern int isdn_ppp_dial_slave(char *);
extern void isdn_ppp_wakeup_daemon(isdn_net_local *); extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc); extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc); extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
#ifdef CONFIG_ISDN_PPP
int isdn_ppp_setup_dev(isdn_net_dev *p);
#else
static inline int
isdn_ppp_setup_dev(isdn_net_dev *p)
{
printk(KERN_WARNING "ISDN: SyncPPP support not configured\n");
return -EINVAL;
}
#endif
#define IPPP_OPEN 0x01 #define IPPP_OPEN 0x01
#define IPPP_CONNECT 0x02 #define IPPP_CONNECT 0x02
#define IPPP_CLOSEWAIT 0x04 #define IPPP_CLOSEWAIT 0x04
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment