fixed a few bugs

This commit is contained in:
Michael Hipp 1996-05-06 11:34:57 +00:00
parent 20450e4d39
commit 0096bd2e07
4 changed files with 274 additions and 120 deletions

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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 *);