fixed a few bugs
This commit is contained in:
parent
20450e4d39
commit
0096bd2e07
|
@ -21,6 +21,12 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.7 1996/05/02 03:55:17 fritz
|
||||
* Bugfixes:
|
||||
* - B-channel connect message for modem devices
|
||||
* sometimes did not result in a CONNECT-message.
|
||||
* - register_isdn did not check for driverId-conflicts.
|
||||
*
|
||||
* Revision 1.6 1996/04/30 20:57:21 fritz
|
||||
* Commit test
|
||||
*
|
||||
|
@ -907,7 +913,7 @@ static int isdn_select(struct inode *inode, struct file *file, int type, select_
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
if (minor <= ISDN_MINOR_CTRLMAX)
|
||||
if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
|
||||
if (drvidx < 0)
|
||||
return -ENODEV;
|
||||
if (dev->drv[drvidx]->stavail)
|
||||
|
@ -918,6 +924,7 @@ static int isdn_select(struct inode *inode, struct file *file, int type, select_
|
|||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
if (minor <= ISDN_MINOR_PPPMAX)
|
||||
return (isdn_ppp_select(minor - ISDN_MINOR_PPP, file, type, st));
|
||||
|
@ -1228,8 +1235,15 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
|
|||
memcpy_fromfs(name,(char*)arg,sizeof(name));
|
||||
return isdn_ppp_dial_slave(name);
|
||||
case IIOCNETDLN:
|
||||
/* remove one link from bundle; removed for i4l 0.7.1 */
|
||||
return 2;
|
||||
if(arg) {
|
||||
if ((ret = verify_area(VERIFY_READ,
|
||||
(void*)arg,
|
||||
sizeof(name))))
|
||||
return ret;
|
||||
} else
|
||||
return -EINVAL;
|
||||
memcpy_fromfs(name,(char*)arg,sizeof(name));
|
||||
return isdn_ppp_hangup_slave(name);
|
||||
#endif
|
||||
case IIOCNETHUP:
|
||||
/* Force hangup of a network-interface */
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.8 1996/04/30 21:04:40 fritz
|
||||
* Test commit
|
||||
*
|
||||
* Revision 1.7 1996/04/30 11:10:42 fritz
|
||||
* Added Michael's ippp-bind patch.
|
||||
*
|
||||
|
@ -83,6 +86,8 @@ static int isdn_net_wildmat(char *s, char *p);
|
|||
static int isdn_net_start_xmit(struct sk_buff *, struct device *);
|
||||
static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
|
||||
|
||||
extern void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */
|
||||
|
||||
char *isdn_net_revision = "$Revision$";
|
||||
|
||||
/*
|
||||
|
@ -146,6 +151,32 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx)
|
|||
restore_flags(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* unbind a net-interface (resets interface after an error)
|
||||
*/
|
||||
static void
|
||||
isdn_net_unbind_channel(isdn_net_local * lp)
|
||||
{
|
||||
ulong flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if (lp->first_skb) {
|
||||
dev_kfree_skb(lp->first_skb,FREE_WRITE);
|
||||
lp->first_skb = NULL;
|
||||
}
|
||||
dev_purge_queues(&lp->netdev->dev);
|
||||
lp->dialstate = 0;
|
||||
dev->rx_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
|
||||
dev->st_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
|
||||
isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
|
||||
lp->flags &= ~ISDN_NET_CONNECTED;
|
||||
lp->isdn_device = -1;
|
||||
lp->isdn_channel = -1;
|
||||
|
||||
restore_flags(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform auto-hangup and cps-calculation for net-interfaces.
|
||||
*
|
||||
|
@ -236,6 +267,8 @@ isdn_net_stat_callback(int idx, int cmd)
|
|||
/* Either D-Channel-hangup or error during dialout */
|
||||
if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
|
||||
lp->flags &= ~ISDN_NET_CONNECTED;
|
||||
if(lp->first_skb)
|
||||
dev_kfree_skb(lp->first_skb,FREE_WRITE);
|
||||
isdn_free_channel(lp->isdn_device, lp->isdn_channel,
|
||||
ISDN_USAGE_NET);
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
|
@ -545,6 +578,7 @@ isdn_net_hangup(struct device *d)
|
|||
dev_kfree_skb(lp->first_skb,FREE_WRITE);
|
||||
lp->first_skb = NULL;
|
||||
}
|
||||
dev_purge_queues(d);
|
||||
if (lp->flags & ISDN_NET_CONNECTED) {
|
||||
printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
|
||||
lp->dialstate = 0;
|
||||
|
@ -699,8 +733,10 @@ isdn_net_xmit(struct device *ndev, isdn_net_local *lp, struct sk_buff *skb)
|
|||
|
||||
/* 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));
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
|
||||
ndev->tbusy = ret = isdn_ppp_xmit(skb, ndev);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
/* Reset hangup-timeout */
|
||||
lp->huptimer = 0;
|
||||
|
@ -759,7 +795,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
|
|||
{
|
||||
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
|
||||
|
||||
|
||||
if (ndev->tbusy) {
|
||||
if (jiffies - ndev->trans_start < 20)
|
||||
return 1;
|
||||
|
@ -799,6 +834,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
|
|||
"isdn_net_start_xmit: No channel for %s\n",
|
||||
ndev->name);
|
||||
restore_flags(flags);
|
||||
/* we probably should drop the skb here and return 0 to omit
|
||||
'socket destroy delayed' messages */
|
||||
return 1;
|
||||
}
|
||||
/* Log packet, which triggered dialing */
|
||||
|
@ -809,15 +846,18 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
|
|||
/* Connect interface with channel */
|
||||
isdn_net_bind_channel(lp, chi);
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
|
||||
/* no 'first_skb' handling for syncPPP */
|
||||
if (isdn_ppp_bind(lp) < 0) {
|
||||
lp->dialstate = 0;
|
||||
isdn_free_channel(lp->isdn_device,
|
||||
lp->isdn_channel,
|
||||
ISDN_USAGE_NET);
|
||||
lp->first_skb = skb; /* net_unbind will free skb */
|
||||
isdn_net_unbind_channel(lp);
|
||||
restore_flags(flags);
|
||||
return 1;
|
||||
return 0; /* STN (skb to nirvana) ;) */
|
||||
}
|
||||
isdn_net_dial(); /* Initiate dialing */
|
||||
restore_flags(flags);
|
||||
return 1; /* let upper layer requeue skb packet */
|
||||
}
|
||||
#endif
|
||||
/* remember first skb to speed up arp
|
||||
* when using encap ETHER
|
||||
|
@ -1634,9 +1674,7 @@ isdn_net_find_icall(int di, int ch, int idx, char *num)
|
|||
#ifdef CONFIG_ISDN_PPP
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
||||
if (isdn_ppp_bind(lp) < 0) {
|
||||
isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
|
||||
ISDN_USAGE_NET);
|
||||
lp->dialstate = 0;
|
||||
isdn_net_unbind_channel(lp);
|
||||
restore_flags(flags);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1684,9 +1722,7 @@ isdn_net_find_icall(int di, int ch, int idx, char *num)
|
|||
#ifdef CONFIG_ISDN_PPP
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
||||
if (isdn_ppp_bind(lp) < 0) {
|
||||
isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
|
||||
ISDN_USAGE_NET);
|
||||
lp->dialstate = 0;
|
||||
isdn_net_unbind_channel(lp);
|
||||
restore_flags(flags);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1750,9 +1786,9 @@ int isdn_net_force_dial_lp(isdn_net_local * lp)
|
|||
#ifdef CONFIG_ISDN_PPP
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
|
||||
if (isdn_ppp_bind(lp) < 0) {
|
||||
lp->dialstate = 0;
|
||||
isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
|
||||
return 1;
|
||||
isdn_net_unbind_channel(lp);
|
||||
restore_flags(flags);
|
||||
return -EAGAIN;
|
||||
}
|
||||
#endif
|
||||
/* Initiate dialing */
|
||||
|
@ -2296,7 +2332,7 @@ static int isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
|
|||
restore_flags(flags);
|
||||
|
||||
#ifdef CONFIG_ISDN_PPP
|
||||
isdn_ppp_free_mpqueue(p);
|
||||
isdn_ppp_free_mpqueue(p); /* still necessary? */
|
||||
#endif
|
||||
kfree(p);
|
||||
|
||||
|
@ -2351,6 +2387,26 @@ int isdn_net_rmall(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to flush device queues
|
||||
* the better place would be net/core/dev.c
|
||||
*/
|
||||
void dev_purge_queues(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<DEV_NUMBUFFS;i++) {
|
||||
struct sk_buff *skb;
|
||||
while((skb=skb_dequeue(&dev->buffs[i])))
|
||||
if(skb->free)
|
||||
kfree_skb(skb,FREE_WRITE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.7 1996/04/30 11:07:42 fritz
|
||||
* Added Michael's ippp-bind patch.
|
||||
*
|
||||
* Revision 1.6 1996/04/30 09:33:09 fritz
|
||||
* Removed compatibility-macros.
|
||||
*
|
||||
|
@ -59,8 +62,8 @@
|
|||
#endif
|
||||
|
||||
/* Prototypes */
|
||||
static int isdn_ppp_fill_rq(char *buf, int len, int minor);
|
||||
static int isdn_ppp_hangup(int);
|
||||
static int isdn_ppp_fill_rq(char *buf, int len,int proto, int minor);
|
||||
static int isdn_ppp_closewait(int);
|
||||
static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
|
||||
struct sk_buff *skb, int proto);
|
||||
static int isdn_ppp_if_get_unit(char **namebuf);
|
||||
|
@ -78,42 +81,48 @@ struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
|
|||
|
||||
extern int isdn_net_force_dial_lp(isdn_net_local *);
|
||||
|
||||
int isdn_ppp_free(isdn_net_local * lp)
|
||||
/*
|
||||
* unbind isdn_net_local <=> ippp-device
|
||||
* note: it can happen, that we hangup/free the master before the slaves
|
||||
*/
|
||||
int isdn_ppp_free(isdn_net_local *lp)
|
||||
{
|
||||
isdn_net_local *master_lp=lp;
|
||||
|
||||
if (lp->ppp_minor < 0)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_ISDN_MPP
|
||||
if(lp->master)
|
||||
{
|
||||
isdn_net_dev *p = dev->netdev;
|
||||
lp->last->next = lp->next;
|
||||
lp->next->last = lp->last;
|
||||
if(lp->netdev->queue == lp)
|
||||
lp->netdev->queue = lp->next;
|
||||
lp->next = lp->last = lp;
|
||||
while(p) {
|
||||
if(lp == &p->local) {
|
||||
lp->netdev = p;
|
||||
break;
|
||||
}
|
||||
p=p->next;
|
||||
master_lp = (isdn_net_local *) lp->master->priv;
|
||||
|
||||
lp->last->next = lp->next;
|
||||
lp->next->last = lp->last;
|
||||
if(master_lp->netdev->queue == lp) {
|
||||
master_lp->netdev->queue = lp->next;
|
||||
if(lp->next == lp) { /* last link in queue? */
|
||||
master_lp->netdev->ib.bundled = 0;
|
||||
isdn_ppp_free_mpqueue(master_lp->netdev);
|
||||
isdn_ppp_free_sqqueue(master_lp->netdev);
|
||||
}
|
||||
} else {
|
||||
lp->netdev->ib.bundled = 0;
|
||||
/* last link: free mpqueue, free sqqueue ? */
|
||||
}
|
||||
|
||||
lp->next = lp->last = lp; /* (re)set own pointers */
|
||||
#endif
|
||||
|
||||
isdn_ppp_hangup(lp->ppp_minor);
|
||||
#if 0
|
||||
printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_minor, (long) lp,(long) ippp_table[lp->ppp_minor]->lp);
|
||||
#endif
|
||||
ippp_table[lp->ppp_minor]->lp = NULL;
|
||||
isdn_ppp_closewait(lp->ppp_minor); /* force wakeup on ippp device */
|
||||
|
||||
if(ippp_table[lp->ppp_minor]->debug & 0x1)
|
||||
printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_minor, (long) lp,(long) ippp_table[lp->ppp_minor]->lp);
|
||||
|
||||
ippp_table[lp->ppp_minor]->lp = NULL; /* link is down .. set lp to NULL */
|
||||
lp->ppp_minor = -1; /* is this OK ?? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* bind isdn_net_local <=> ippp-device
|
||||
*/
|
||||
int isdn_ppp_bind(isdn_net_local * lp)
|
||||
{
|
||||
int i;
|
||||
|
@ -179,7 +188,12 @@ int isdn_ppp_bind(isdn_net_local * lp)
|
|||
return lp->ppp_minor;
|
||||
}
|
||||
|
||||
static int isdn_ppp_hangup(int minor)
|
||||
/*
|
||||
* there was a hangup on the netdevice
|
||||
* force wakeup of the ippp device
|
||||
* go into 'device waits for release' state
|
||||
*/
|
||||
static int isdn_ppp_closewait(int minor)
|
||||
{
|
||||
if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
|
||||
return 0;
|
||||
|
@ -197,9 +211,8 @@ static int isdn_ppp_hangup(int minor)
|
|||
|
||||
int isdn_ppp_open(int minor, struct file *file)
|
||||
{
|
||||
#if 0
|
||||
printk(KERN_DEBUG "ippp, open, minor: %d state: %04x\n", minor,ippp_table[minor]->state);
|
||||
#endif
|
||||
if(ippp_table[minor]->debug & 0x1)
|
||||
printk(KERN_DEBUG "ippp, open, minor: %d state: %04x\n", minor,ippp_table[minor]->state);
|
||||
if (ippp_table[minor]->state)
|
||||
return -EBUSY;
|
||||
|
||||
|
@ -235,6 +248,9 @@ int isdn_ppp_open(int minor, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* release ippp device
|
||||
*/
|
||||
void isdn_ppp_release(int minor, struct file *file)
|
||||
{
|
||||
int i;
|
||||
|
@ -242,29 +258,24 @@ void isdn_ppp_release(int minor, struct file *file)
|
|||
if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) ippp_table[minor]->lp);
|
||||
#endif
|
||||
if(ippp_table[minor]->debug & 0x1)
|
||||
printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) ippp_table[minor]->lp);
|
||||
|
||||
if (ippp_table[minor]->lp) { /* a lp address says: this link is still up */
|
||||
isdn_net_dev *p = dev->netdev;
|
||||
while(p) { /* find interface for our lp; */
|
||||
if(&p->local == ippp_table[minor]->lp)
|
||||
break;
|
||||
p = p->next;
|
||||
}
|
||||
if(!p) {
|
||||
printk(KERN_ERR "isdn_ppp_release: Can't find device for net_local\n");
|
||||
p = ippp_table[minor]->lp->netdev;
|
||||
}
|
||||
p = ippp_table[minor]->lp->netdev;
|
||||
ippp_table[minor]->lp->ppp_minor = -1;
|
||||
isdn_net_hangup(&p->dev); /* lp->ppp_minor==-1 => no calling of isdn_ppp_hangup() */
|
||||
isdn_net_hangup(&p->dev); /* lp->ppp_minor==-1 => no calling of isdn_ppp_closewait() */
|
||||
ippp_table[minor]->lp = NULL;
|
||||
}
|
||||
for (i = 0; i < NUM_RCV_BUFFS; i++) {
|
||||
if (ippp_table[minor]->rq[i].buf)
|
||||
if (ippp_table[minor]->rq[i].buf) {
|
||||
kfree(ippp_table[minor]->rq[i].buf);
|
||||
ippp_table[minor]->rq[i].buf = NULL;
|
||||
}
|
||||
}
|
||||
ippp_table[minor]->first = ippp_table[minor]->rq + NUM_RCV_BUFFS - 1; /* receive queue */
|
||||
ippp_table[minor]->last = ippp_table[minor]->rq;
|
||||
|
||||
#ifdef CONFIG_ISDN_PPP_VJ
|
||||
slhc_free(ippp_table[minor]->slcomp);
|
||||
|
@ -274,6 +285,9 @@ void isdn_ppp_release(int minor, struct file *file)
|
|||
ippp_table[minor]->state = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_arg .. ioctl helper
|
||||
*/
|
||||
static int get_arg(void *b, unsigned long *val)
|
||||
{
|
||||
int r;
|
||||
|
@ -283,6 +297,9 @@ static int get_arg(void *b, unsigned long *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set arg .. ioctl helper
|
||||
*/
|
||||
static int set_arg(void *b, unsigned long val)
|
||||
{
|
||||
int r;
|
||||
|
@ -292,15 +309,17 @@ static int set_arg(void *b, unsigned long val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ippp device ioctl
|
||||
*/
|
||||
int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long val;
|
||||
int r;
|
||||
|
||||
#if 0
|
||||
printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x",minor,cmd);
|
||||
printk(KERN_DEBUG " state: %x\n",ippp_table[minor]->state);
|
||||
#endif
|
||||
if(ippp_table[minor]->debug & 0x1)
|
||||
printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n",
|
||||
minor,cmd,ippp_table[minor]->state);
|
||||
|
||||
if (!(ippp_table[minor]->state & IPPP_OPEN))
|
||||
return -EINVAL;
|
||||
|
@ -344,8 +363,9 @@ int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long
|
|||
return r;
|
||||
}
|
||||
if (val & SC_ENABLE_IP && !(ippp_table[minor]->pppcfg & SC_ENABLE_IP)) {
|
||||
ippp_table[minor]->lp->netdev->dev.tbusy = 0;
|
||||
mark_bh(NET_BH); /* OK .. we are ready to send the first buffer */
|
||||
isdn_net_local *lp = ippp_table[minor]->lp;
|
||||
lp->netdev->dev.tbusy = 0;
|
||||
mark_bh(NET_BH); /* OK .. we are ready to send buffers */
|
||||
}
|
||||
ippp_table[minor]->pppcfg = val;
|
||||
break;
|
||||
|
@ -370,8 +390,13 @@ int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long
|
|||
ippp_table[minor]->maxcid = val;
|
||||
break;
|
||||
case PPPIOCGDEBUG:
|
||||
if ((r = set_arg((void *) arg, ippp_table[minor]->debug)))
|
||||
return r;
|
||||
break;
|
||||
case PPPIOCSDEBUG:
|
||||
if ((r = get_arg((void *) arg, &val)))
|
||||
return r;
|
||||
ippp_table[minor]->debug = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -384,9 +409,8 @@ int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
|
|||
struct ippp_buf_queue *bf, *bl;
|
||||
unsigned long flags;
|
||||
|
||||
#if 0
|
||||
printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",minor,type);
|
||||
#endif
|
||||
if(ippp_table[minor]->debug & 0x2)
|
||||
printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",minor,type);
|
||||
|
||||
if (!(ippp_table[minor]->state & IPPP_OPEN))
|
||||
return -EINVAL;
|
||||
|
@ -397,6 +421,9 @@ int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
|
|||
cli();
|
||||
bl = ippp_table[minor]->last;
|
||||
bf = ippp_table[minor]->first;
|
||||
/*
|
||||
* if IPPP_NOBLOCK is set we return even if we have nothing to read
|
||||
*/
|
||||
if (bf->next == bl && !(ippp_table[minor]->state & IPPP_NOBLOCK)) {
|
||||
select_wait(&ippp_table[minor]->wq, st);
|
||||
restore_flags(flags);
|
||||
|
@ -419,7 +446,7 @@ int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
|
|||
* fill up isdn_ppp_read() queue ..
|
||||
*/
|
||||
|
||||
static int isdn_ppp_fill_rq(char *buf, int len, int minor)
|
||||
static int isdn_ppp_fill_rq(char *buf, int len,int proto, int minor)
|
||||
{
|
||||
struct ippp_buf_queue *bf, *bl;
|
||||
unsigned long flags;
|
||||
|
@ -444,15 +471,19 @@ static int isdn_ppp_fill_rq(char *buf, int len, int minor)
|
|||
kfree(bf->buf);
|
||||
ippp_table[minor]->first = bf;
|
||||
}
|
||||
bl->buf = (char *) kmalloc(len, GFP_ATOMIC);
|
||||
bl->buf = (char *) kmalloc(len+4, GFP_ATOMIC);
|
||||
if (!bl->buf) {
|
||||
printk(KERN_WARNING "ippp: Can't alloc buf\n");
|
||||
restore_flags(flags);
|
||||
return 0;
|
||||
}
|
||||
bl->len = len;
|
||||
bl->len = len+4;
|
||||
|
||||
memcpy(bl->buf, buf, len);
|
||||
bl->buf[0] = PPP_ALLSTATIONS;
|
||||
bl->buf[1] = PPP_UI;
|
||||
bl->buf[2] = proto >> 8;
|
||||
bl->buf[3] = proto & 0xff;
|
||||
memcpy(bl->buf+4, buf, len);
|
||||
|
||||
ippp_table[minor]->last = bl->next;
|
||||
restore_flags(flags);
|
||||
|
@ -518,6 +549,7 @@ int isdn_ppp_write(int minor, struct file *file, const char *buf, int count)
|
|||
if (!lp)
|
||||
printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
|
||||
else {
|
||||
lp->huptimer = 0;
|
||||
if (lp->isdn_device < 0 || lp->isdn_channel < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -542,11 +574,11 @@ int isdn_ppp_init(void)
|
|||
if (!(ippp_table[i] = (struct ippp_struct *)
|
||||
kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
|
||||
printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
|
||||
for (j = 0; j < i; j++)
|
||||
kfree(ippp_table[i]);
|
||||
for (j = 0; j < i; j++)
|
||||
kfree(ippp_table[i]);
|
||||
return -1;
|
||||
}
|
||||
memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
|
||||
memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
|
||||
ippp_table[i]->state = 0;
|
||||
ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
|
||||
ippp_table[i]->last = ippp_table[i]->rq;
|
||||
|
@ -575,14 +607,15 @@ void isdn_ppp_cleanup(void)
|
|||
|
||||
void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
|
||||
{
|
||||
#if 0
|
||||
printk(KERN_DEBUG "recv, skb %d\n",skb->len);
|
||||
#endif
|
||||
if(ippp_table[lp->ppp_minor]->debug & 0x4)
|
||||
printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len);
|
||||
|
||||
if(skb->data[0] == 0xff && skb->data[1] == 0x03)
|
||||
skb_pull(skb,2);
|
||||
else if (ippp_table[lp->ppp_minor]->pppcfg & SC_REJ_COMP_AC)
|
||||
else if (ippp_table[lp->ppp_minor]->pppcfg & SC_REJ_COMP_AC) {
|
||||
dev_kfree_skb(skb,FREE_WRITE);
|
||||
return; /* discard it silently */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_MPP
|
||||
if (!(ippp_table[lp->ppp_minor]->mpppcfg & SC_REJ_MP_PROT)) {
|
||||
|
@ -599,11 +632,10 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
|
|||
isdn_net_local *lpq;
|
||||
int sqno, min_sqno, tseq;
|
||||
u_char BEbyte = skb->data[0];
|
||||
#if 0
|
||||
printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_minor, proto ,
|
||||
(int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
|
||||
(int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
|
||||
#endif
|
||||
if(ippp_table[lp->ppp_minor]->debug & 0x8)
|
||||
printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_minor, proto ,
|
||||
(int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
|
||||
(int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
|
||||
if (!(ippp_table[lp->ppp_minor]->mpppcfg & SC_IN_SHORT_SEQ)) {
|
||||
sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3];
|
||||
skb_pull(skb,4);
|
||||
|
@ -673,8 +705,9 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
|
|||
|
||||
q = (struct sqqueue *) kmalloc(sizeof(struct sqqueue), GFP_ATOMIC);
|
||||
if (!q) {
|
||||
printk(KERN_WARNING "ippp: err, no memory !!\n");
|
||||
net_dev->ib.modify = 0;
|
||||
printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n");
|
||||
dev_kfree_skb(skb,FREE_WRITE);
|
||||
return; /* discard */
|
||||
}
|
||||
q->skb = skb;
|
||||
|
@ -742,9 +775,8 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
printk(KERN_DEBUG "push, skb %d %04x\n",skb->len,proto);
|
||||
#endif
|
||||
if(ippp_table[lp->ppp_minor]->debug & 0x10)
|
||||
printk(KERN_DEBUG "push, skb %ld %04x\n",skb->len,proto);
|
||||
|
||||
switch (proto) {
|
||||
case PPP_IPX: /* untested */
|
||||
|
@ -771,6 +803,7 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
|
|||
if (!skb) {
|
||||
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
|
||||
net_dev->local.stats.rx_dropped++;
|
||||
dev_kfree_skb(skb_old,FREE_WRITE);
|
||||
return;
|
||||
}
|
||||
skb->dev = dev;
|
||||
|
@ -786,16 +819,12 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
|
|||
#else
|
||||
printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n");
|
||||
lp->stats.rx_dropped++;
|
||||
dev_kfree_skb(skb,FREE_WRITE);
|
||||
return;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
skb_push(skb,4);
|
||||
skb->data[0] = 0xff;
|
||||
skb->data[1] = 0x03;
|
||||
skb->data[2] = (proto>>8);
|
||||
skb->data[3] = proto & 0xff;
|
||||
isdn_ppp_fill_rq(skb->data, skb->len, lp->ppp_minor); /* push data to pppd device */
|
||||
isdn_ppp_fill_rq(skb->data, skb->len,proto, lp->ppp_minor); /* push data to pppd device */
|
||||
dev_kfree_skb(skb,FREE_WRITE);
|
||||
return;
|
||||
}
|
||||
|
@ -809,17 +838,32 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
|
|||
}
|
||||
|
||||
/*
|
||||
* send ppp frame .. we expect a PIDCOMPable proto --
|
||||
* send ppp frame .. we expect a PIDCOMPressable proto --
|
||||
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
|
||||
*/
|
||||
int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
|
||||
{
|
||||
isdn_net_dev *nd = ((isdn_net_local *) dev->priv)->netdev;
|
||||
isdn_net_local *lp = nd->queue;
|
||||
struct device *mdev = ((isdn_net_local *) (dev->priv) )->master; /* get master (for redundancy) */
|
||||
isdn_net_local *lp,*mlp;
|
||||
isdn_net_dev *nd;
|
||||
int proto = PPP_IP; /* 0x21 */
|
||||
struct ippp_struct *ipt = ippp_table[lp->ppp_minor];
|
||||
struct ippp_struct *ipts = ippp_table[lp->netdev->local.ppp_minor];
|
||||
struct ippp_struct *ipt,*ipts;
|
||||
|
||||
if(mdev)
|
||||
mlp = (isdn_net_local *) (mdev->priv);
|
||||
else
|
||||
mlp = (isdn_net_local *) (dev->priv);
|
||||
nd = mlp->netdev; /* get master lp */
|
||||
lp = nd->queue; /* get lp on top of queue */
|
||||
ipt = ippp_table[lp->ppp_minor];
|
||||
ipts = ippp_table[mlp->ppp_minor];
|
||||
|
||||
if (!(ipt->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
|
||||
printk(KERN_INFO "isdn, xmit: Packet blocked: %d %d\n", lp->isdn_device, lp->isdn_channel);
|
||||
return 1;
|
||||
}
|
||||
lp->huptimer = 0;
|
||||
|
||||
/* If packet is to be resent, it has already been processed and
|
||||
* therefore it's first bytes are already initialized. In this case
|
||||
* send it immediately ...
|
||||
|
@ -831,17 +875,16 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
|
|||
|
||||
/* future: step to next 'lp' when this lp is 'tbusy' */
|
||||
|
||||
#if 0
|
||||
printk(KERN_DEBUG "xmit, skb %d\n",skb->len);
|
||||
#endif
|
||||
if(ippp_table[lp->ppp_minor]->debug & 0x4)
|
||||
printk(KERN_DEBUG "xmit skb, len %ld\n",skb->len);
|
||||
|
||||
#ifdef CONFIG_ISDN_PPP_VJ
|
||||
if (ipt->pppcfg & SC_COMP_TCP) {
|
||||
if (ipt->pppcfg & SC_COMP_TCP) { /* ipt or ipts ? -> check this again! */
|
||||
u_char *buf = skb->data;
|
||||
int pktlen;
|
||||
int len = 4;
|
||||
#ifdef CONFIG_ISDN_MPP
|
||||
if (ipt->mpppcfg & SC_MP_PROT) /* sigh */
|
||||
if (ipt->mpppcfg & SC_MP_PROT) /* sigh */ /* ipt or ipts ?? */
|
||||
if (ipt->mpppcfg & SC_OUT_SHORT_SEQ)
|
||||
len += 3;
|
||||
else
|
||||
|
@ -865,9 +908,8 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printk(KERN_DEBUG "xmit, skb %d %04x\n",skb->len,proto);
|
||||
#endif
|
||||
if(ippp_table[lp->ppp_minor]->debug & 0x24)
|
||||
printk(KERN_DEBUG "xmit2 skb, len %ld, proto %04x\n",skb->len,proto);
|
||||
|
||||
#ifdef CONFIG_ISDN_MPP
|
||||
if (ipt->mpppcfg & SC_MP_PROT) {
|
||||
|
@ -897,15 +939,25 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
|
|||
skb->data[2] = proto >> 8;
|
||||
skb->data[3] = proto & 0xff;
|
||||
|
||||
lp->huptimer = 0;
|
||||
if (!(ipt->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
|
||||
printk(KERN_INFO "isdn, xmit: Packet blocked: %d %d\n", lp->isdn_device, lp->isdn_channel);
|
||||
return 1;
|
||||
}
|
||||
/* tx-stats are now updated via BSENT-callback */
|
||||
return (isdn_net_send_skb(dev , lp , skb));
|
||||
}
|
||||
|
||||
void isdn_ppp_free_sqqueue(isdn_net_dev * p)
|
||||
{
|
||||
struct sqqueue *q = p->ib.sq;
|
||||
|
||||
p->ib.sq = NULL;
|
||||
while(q) {
|
||||
struct sqqueue *qn = q->next;
|
||||
if(q->skb)
|
||||
dev_kfree_skb(q->skb,FREE_WRITE);
|
||||
kfree(q);
|
||||
q = qn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void isdn_ppp_free_mpqueue(isdn_net_dev * p)
|
||||
{
|
||||
struct mpqueue *ql, *q = p->mp_last;
|
||||
|
@ -946,8 +998,6 @@ static int isdn_ppp_bundle(int minor, int unit)
|
|||
nlp->next = lp;
|
||||
p->queue = nlp;
|
||||
|
||||
nlp->netdev = lp->netdev;
|
||||
|
||||
ippp_table[nlp->ppp_minor]->unit = ippp_table[lp->ppp_minor]->unit;
|
||||
/* maybe also SC_CCP stuff */
|
||||
ippp_table[nlp->ppp_minor]->pppcfg |= ippp_table[lp->ppp_minor]->pppcfg &
|
||||
|
@ -1253,4 +1303,34 @@ int isdn_ppp_dial_slave(char *name)
|
|||
#endif
|
||||
}
|
||||
|
||||
int isdn_ppp_hangup_slave(char *name)
|
||||
{
|
||||
#ifdef CONFIG_ISDN_MPP
|
||||
isdn_net_dev *ndev;
|
||||
isdn_net_local *lp;
|
||||
struct device *sdev;
|
||||
|
||||
if(!(ndev = isdn_net_findif(name)))
|
||||
return 1;
|
||||
lp = &ndev->local;
|
||||
if(!(lp->flags & ISDN_NET_CONNECTED))
|
||||
return 5;
|
||||
|
||||
sdev = lp->slave;
|
||||
while(sdev)
|
||||
{
|
||||
isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
|
||||
if((mlp->flags & ISDN_NET_CONNECTED))
|
||||
break;
|
||||
sdev = mlp->slave;
|
||||
}
|
||||
if(!sdev)
|
||||
return 2;
|
||||
|
||||
isdn_net_hangup(sdev);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1996/04/30 09:33:10 fritz
|
||||
* Removed compatibility-macros.
|
||||
*
|
||||
* Revision 1.2 1996/04/20 16:35:11 fritz
|
||||
* Changed isdn_ppp_receive to use sk_buff as parameter.
|
||||
* Added definition of isdn_ppp_dial_slave and ippp_table.
|
||||
|
@ -40,6 +43,7 @@ extern int isdn_ppp_xmit(struct sk_buff *, struct device *);
|
|||
extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
|
||||
extern int isdn_ppp_dev_ioctl(struct device *, struct ifreq *, int);
|
||||
extern void isdn_ppp_free_mpqueue(isdn_net_dev *);
|
||||
extern void isdn_ppp_free_sqqueue(isdn_net_dev *);
|
||||
extern int isdn_ppp_select(int, struct file *, int, select_table *);
|
||||
extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
|
||||
extern void isdn_ppp_release(int, struct file *);
|
||||
|
|
Loading…
Reference in New Issue