Commit 67f46677 authored by Kai Germaschewski's avatar Kai Germaschewski

Hand merged.

parents c2dd03a9 36743e75
......@@ -106,3 +106,39 @@ struct concap_proto * isdn_concap_new( int encap )
}
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 @@
extern struct concap_device_ops isdn_concap_reliable_dl_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 @@
#include <linux/inetdevice.h>
#include "isdn_common.h"
#include "isdn_net.h"
#ifdef CONFIG_ISDN_PPP
#include "isdn_ppp.h"
#endif
#ifdef CONFIG_ISDN_X25
#include <linux/concap.h>
#include "isdn_concap.h"
#endif
enum {
ST_NULL,
......@@ -1711,6 +1707,13 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *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.
*/
......@@ -2533,7 +2536,7 @@ isdn_net_new(char *name, struct net_device *master)
netdev->local.isdn_slot = -1;
netdev->local.pre_device = -1;
netdev->local.pre_channel = -1;
netdev->local.exclusive = -1;
netdev->local.exclusive = 0;
netdev->local.ppp_slot = -1;
netdev->local.pppbind = -1;
skb_queue_head_init(&netdev->local.super_tx_queue);
......@@ -2591,163 +2594,180 @@ isdn_net_newslave(char *parm)
return isdn_net_new(p+1, &m->dev);
}
/*
* 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)
static int
isdn_net_set_encap(isdn_net_dev *p, 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;
int retval;
/* 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])
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){
/* no change */
retval = 0;
goto out;
}
if (lp->p_encap != cfg->p_encap){
#ifdef CONFIG_ISDN_X25
struct concap_proto * cprot = p -> cprot;
#endif
if (isdn_net_device_started(p)) {
printk(KERN_WARNING "%s: cannot change encap when if is up\n",
lp->name);
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
retval = -EBUSY;
goto out;
}
isdn_x25_encap_changed(p, cfg);
switch ( cfg->p_encap ) {
case ISDN_NET_ENCAP_SYNCPPP:
#ifndef CONFIG_ISDN_PPP
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
retval = isdn_ppp_setup_dev(p);
break;
case ISDN_NET_ENCAP_X25IFACE:
#ifndef CONFIG_ISDN_X25
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
retval = isdn_x25_setup_dev(p);
break;
case ISDN_NET_ENCAP_CISCOHDLCK:
p->dev.do_ioctl = isdn_ciscohdlck_dev_ioctl;
retval = isdn_ciscohdlck_setup_dev(p);
break;
default:
if( cfg->p_encap >= 0 &&
cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
if (cfg->p_encap < 0 ||
cfg->p_encap > ISDN_NET_ENCAP_MAX_ENCAP) {
retval = -EINVAL;
break;
printk(KERN_WARNING
"%s: encapsulation protocol %d not supported\n",
p->local.name, cfg->p_encap);
return -EINVAL;
}
if (strlen(cfg->drvid)) {
/* A bind has been requested ... */
char *c,
*e;
retval = 0;
}
if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
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;
chidx = -1;
strcpy(drvid, cfg->drvid);
if ((c = strchr(drvid, ','))) {
/* The channel-number is appended to the driver-Id with a comma */
chidx = (int) simple_strtoul(c + 1, &e, 10);
if (e == c)
chidx = -1;
*c = '\0';
lp->p_encap = cfg->p_encap;
out:
return retval;
}
static int
isdn_net_bind(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg)
{
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 */
if (!(strcmp(dev->drvid[i], drvid))) {
if (!strcmp(dev->drvid[i], drvid)) {
drvidx = i;
break;
}
if ((drvidx == -1) || (chidx == -1))
}
if (drvidx == -1 || chidx == -1) {
/* Either driver-Id or channel-number invalid */
return -ENODEV;
} else {
/* Parameters are valid, so get them */
drvidx = lp->pre_device;
chidx = lp->pre_channel;
retval = -ENODEV;
goto out;
}
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 */
save_flags(flags);
if ((i = isdn_get_free_slot(ISDN_USAGE_NET,
lp->l2_proto, lp->l3_proto, drvidx,
chidx, lp->msn)) < 0) {
i = isdn_get_free_slot(ISDN_USAGE_NET, lp->l2_proto,
lp->l3_proto, drvidx, chidx, cfg->eaz);
if (i < 0) {
/* Grab failed, because desired channel is in use */
lp->exclusive = -1;
restore_flags(flags);
return -EBUSY;
retval = -EBUSY;
goto out;
}
/* All went ok, so update isdninfo */
isdn_slot_set_usage(i, ISDN_USAGE_EXCLUSIVE);
restore_flags(flags);
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;
lp->exclusive = 1;
}
}
strcpy(lp->msn, cfg->eaz);
lp->pre_device = drvidx;
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->charge = cfg->charge;
lp->l2_proto = cfg->l2_proto;
......@@ -2782,14 +2802,11 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
}
lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
/* old isdnctrl version, where only 0 or 1 is given */
printk(KERN_WARNING
"Old isdnctrl version detected! Please update.\n");
lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
retval = -EINVAL;
goto out;
}
else {
lp->flags |= cfg->dialmode; /* turn on selected bits */
}
if (lp->flags & ISDN_NET_DM_OFF)
isdn_net_hangup(lp);
......@@ -2797,38 +2814,21 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
lp->hupflags |= ISDN_CHARGEHUP;
else
lp->hupflags &= ~ISDN_CHARGEHUP;
if (cfg->ihup)
lp->hupflags |= ISDN_INHUP;
else
lp->hupflags &= ~ISDN_INHUP;
if (cfg->chargeint > 10) {
lp->chargeint = cfg->chargeint * HZ;
lp->charge_state = ST_CHARGE_HAVE_CINT;
lp->hupflags |= ISDN_MANCHARGE;
}
if (cfg->p_encap != lp->p_encap) {
if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
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;
}
}
}
lp->p_encap = cfg->p_encap;
return 0;
}
return -ENODEV;
retval = 0;
out:
return retval;
}
/*
......@@ -2838,10 +2838,11 @@ int
isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
{
isdn_net_dev *p = isdn_net_findif(cfg->name);
if (p) {
isdn_net_local *lp = &p->local;
if (!p)
return -ENODEV;
strcpy(cfg->eaz, lp->msn);
cfg->exclusive = lp->exclusive;
if (lp->pre_device >= 0) {
......@@ -2881,9 +2882,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
else
cfg->master[0] = '\0';
return 0;
}
return -ENODEV;
}
/*
......@@ -3074,7 +3074,7 @@ isdn_net_realrm(isdn_net_dev *p)
/* Free all phone-entries */
isdn_net_rmallphone(p);
/* 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);
if (p->local.master) {
/* It's a slave-device, so update master's slave-pointer if necessary */
......
......@@ -14,6 +14,7 @@
#include <linux/smp_lock.h>
#include <linux/poll.h>
#include <linux/ppp-comp.h>
#include <linux/if_arp.h>
#include "isdn_common.h"
#include "isdn_ppp.h"
......@@ -2893,3 +2894,12 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_
}
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 *);
extern int isdn_ppp_bind(isdn_net_local *);
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 int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
extern int isdn_ppp_dial_slave(char *);
extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
extern int isdn_ppp_register_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_CONNECT 0x02
#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