patch-2.0.16 linux/drivers/isdn/isdn_ppp.c
Next file: linux/drivers/isdn/isdn_ppp.h
Previous file: linux/drivers/isdn/isdn_net.c
Back to the patch index
Back to the overall index
- Lines: 1066
- Date:
Sat Aug 31 19:13:03 1996
- Orig file:
v2.0.15/linux/drivers/isdn/isdn_ppp.c
- Orig date:
Wed Jul 17 11:55:48 1996
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.13 1996/07/01 19:47:24 hipp Exp $
+/* $Id: isdn_ppp.c,v 1.14 1996/08/12 16:26:47 hipp Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -19,6 +19,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.c,v $
+ * Revision 1.14 1996/08/12 16:26:47 hipp
+ * code cleanup
+ * changed connection management from minors to slots
+ *
* Revision 1.13 1996/07/01 19:47:24 hipp
* Fixed memory leak in VJ handling and more VJ changes
*
@@ -82,21 +86,21 @@
#endif
/* Prototypes */
-static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int minor);
-static int isdn_ppp_closewait(int);
+static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot);
+static int isdn_ppp_closewait(int slot);
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);
+static int isdn_ppp_if_get_unit(char *namebuf);
#ifdef CONFIG_ISDN_MPP
-static int isdn_ppp_bundle(int, int);
+static int isdn_ppp_bundle(struct ippp_struct *, int unit);
static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min);
static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
int BEbyte, int *sqno, int min_sqno);
#endif
-char *isdn_ppp_revision = "$Revision: 1.13 $";
+char *isdn_ppp_revision = "$Revision: 1.14 $";
struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
extern int isdn_net_force_dial_lp(isdn_net_local *);
@@ -109,10 +113,13 @@
{
isdn_net_local *master_lp=lp;
unsigned long flags;
+ struct ippp_struct *is;
- if (lp->ppp_minor < 0)
+ if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS)
return 0;
+ is = ippp_table[lp->ppp_slot];
+
save_flags(flags);
cli();
#ifdef CONFIG_ISDN_MPP
@@ -132,13 +139,13 @@
lp->next = lp->last = lp; /* (re)set own pointers */
#endif
- isdn_ppp_closewait(lp->ppp_minor); /* force wakeup on ippp device */
+ isdn_ppp_closewait(lp->ppp_slot); /* 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);
+ if(is->debug & 0x1)
+ printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp,(long) is->lp);
- ippp_table[lp->ppp_minor]->lp = NULL; /* link is down .. set lp to NULL */
- lp->ppp_minor = -1; /* is this OK ?? */
+ is->lp = NULL; /* link is down .. set lp to NULL */
+ lp->ppp_slot = -1; /* is this OK ?? */
restore_flags(flags);
return 0;
@@ -151,11 +158,11 @@
{
int i;
int unit = 0;
- char *name;
long flags;
+ struct ippp_struct *is;
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
- return 0;
+ return -1;
save_flags(flags);
cli();
@@ -172,19 +179,18 @@
net_dev = net_dev->next;
}
/*
- * search a free device
+ * search a free device / slot
*/
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (ippp_table[i]->state == IPPP_OPEN && !exclusive[i]) { /* OPEN, but not connected! */
+ if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) { /* OPEN, but not connected! */
break;
}
}
}
else {
- if (ippp_table[lp->pppbind]->state == IPPP_OPEN) /* OPEN, but not connected! */
- i = lp->pppbind;
- else
- i = ISDN_MAX_CHANNELS; /* trigger error */
+ for(i=0;i<ISDN_MAX_CHANNELS;i++)
+ if(ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == IPPP_OPEN)
+ break;
}
if (i >= ISDN_MAX_CHANNELS) {
@@ -192,24 +198,33 @@
printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
return -1;
}
- lp->ppp_minor = i;
- ippp_table[lp->ppp_minor]->lp = lp;
- name = lp->name;
- unit = isdn_ppp_if_get_unit(&name); /* get unit number from interface name .. ugly! */
- ippp_table[lp->ppp_minor]->unit = unit;
+ unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */
+ if(unit < 0) {
+ printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n",lp->name);
+ return -1;
+ }
- ippp_table[lp->ppp_minor]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+ lp->ppp_slot = i;
+ is = ippp_table[i];
+ is->lp = lp;
+ is->unit = unit;
+ is->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
restore_flags(flags);
- /*
- * kick the ipppd on the new device
- */
- if (ippp_table[lp->ppp_minor]->wq)
- wake_up_interruptible(&ippp_table[lp->ppp_minor]->wq);
+ return lp->ppp_slot;
+}
- return lp->ppp_minor;
+/*
+ * kick the ipppd on the device
+ * (wakes up daemon after B-channel connect)
+ */
+
+void isdn_ppp_wakeup_daemon(isdn_net_local *lp)
+{
+ if (ippp_table[lp->ppp_slot]->wq)
+ wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
}
/*
@@ -217,51 +232,76 @@
* force wakeup of the ippp device
* go into 'device waits for release' state
*/
-static int isdn_ppp_closewait(int minor)
+static int isdn_ppp_closewait(int slot)
{
- if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
+ struct ippp_struct *is;
+
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS)
return 0;
+ is = ippp_table[slot];
- if (ippp_table[minor]->state && ippp_table[minor]->wq)
- wake_up_interruptible(&ippp_table[minor]->wq);
+ if (is->state && is->wq)
+ wake_up_interruptible(&is->wq);
- ippp_table[minor]->state = IPPP_CLOSEWAIT;
+ is->state = IPPP_CLOSEWAIT;
return 1;
}
/*
+ * isdn_ppp_find_slot / isdn_ppp_free_slot
+ */
+
+static int isdn_ppp_get_slot(void)
+{
+ int i;
+ for(i=0;i<ISDN_MAX_CHANNELS;i++) {
+ if(!ippp_table[i]->state)
+ return i;
+ }
+ return -1;
+}
+
+/*
* isdn_ppp_open
*/
-int isdn_ppp_open(int minor, struct file *file)
+int isdn_ppp_open(int min, struct file *file)
{
- 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)
+ int slot;
+ struct ippp_struct *is;
+
+ slot = isdn_ppp_get_slot();
+ if(slot < 0) {
return -EBUSY;
+ }
+ is = file->private_data = ippp_table[slot];
- ippp_table[minor]->lp = 0;
- ippp_table[minor]->mp_seqno = 0; /* MP sequence number */
- ippp_table[minor]->pppcfg = 0; /* ppp configuration */
- ippp_table[minor]->mpppcfg = 0; /* mppp configuration */
- ippp_table[minor]->range = 0x1000000; /* MP: 24 bit range */
- ippp_table[minor]->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
- ippp_table[minor]->unit = -1; /* set, when we have our interface */
- ippp_table[minor]->mru = 1524; /* MRU, default 1524 */
- ippp_table[minor]->maxcid = 16; /* VJ: maxcid */
- ippp_table[minor]->tk = current;
- ippp_table[minor]->wq = NULL; /* read() wait queue */
- ippp_table[minor]->wq1 = NULL; /* select() wait queue */
- ippp_table[minor]->first = ippp_table[minor]->rq + NUM_RCV_BUFFS - 1; /* receive queue */
- ippp_table[minor]->last = ippp_table[minor]->rq;
+ if(is->debug & 0x1)
+ printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",slot, min,is->state);
+
+ is->lp = 0;
+ is->mp_seqno = 0; /* MP sequence number */
+ is->pppcfg = 0; /* ppp configuration */
+ is->mpppcfg = 0; /* mppp configuration */
+ is->range = 0x1000000; /* MP: 24 bit range */
+ is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
+ is->unit = -1; /* set, when we have our interface */
+ is->mru = 1524; /* MRU, default 1524 */
+ is->maxcid = 16; /* VJ: maxcid */
+ is->tk = current;
+ is->wq = NULL; /* read() wait queue */
+ is->wq1 = NULL; /* select() wait queue */
+ is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
+ is->last = is->rq;
+ is->minor = min;
#ifdef CONFIG_ISDN_PPP_VJ
/*
* VJ header compression init
*/
- ippp_table[minor]->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
+ is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
#endif
- ippp_table[minor]->state = IPPP_OPEN;
+ is->state = IPPP_OPEN;
return 0;
}
@@ -269,38 +309,40 @@
/*
* release ippp device
*/
-void isdn_ppp_release(int minor, struct file *file)
+void isdn_ppp_release(int min, struct file *file)
{
int i;
+ struct ippp_struct *is;
- if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
+ if (min < 0 || min >= ISDN_MAX_CHANNELS)
return;
+ is = file->private_data;
- if(ippp_table[minor]->debug & 0x1)
- printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) ippp_table[minor]->lp);
+ if(is->debug & 0x1)
+ printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
- if (ippp_table[minor]->lp) { /* a lp address says: this link is still up */
+ if (is->lp) { /* a lp address says: this link is still up */
isdn_net_dev *p = dev->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_closewait() */
- ippp_table[minor]->lp = NULL;
+ p = is->lp->netdev;
+ is->lp->ppp_slot = -1;
+ isdn_net_hangup(&p->dev); /* lp->ppp_slot==-1 => no calling of isdn_ppp_closewait() */
+ is->lp = NULL;
}
for (i = 0; i < NUM_RCV_BUFFS; i++) {
- if (ippp_table[minor]->rq[i].buf) {
- kfree(ippp_table[minor]->rq[i].buf);
- ippp_table[minor]->rq[i].buf = NULL;
+ if (is->rq[i].buf) {
+ kfree(is->rq[i].buf);
+ is->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;
+ is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
+ is->last = is->rq;
#ifdef CONFIG_ISDN_PPP_VJ
- slhc_free(ippp_table[minor]->slcomp);
- ippp_table[minor]->slcomp = NULL;
+ slhc_free(is->slcomp);
+ is->slcomp = NULL;
#endif
- ippp_table[minor]->state = 0;
+ is->state = 0;
}
/*
@@ -330,62 +372,59 @@
/*
* ippp device ioctl
*/
-int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long arg)
+int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long val;
int r;
+ struct ippp_struct *is;
+
+ is = file->private_data;
- 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(is->debug & 0x1)
+ printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n",min,cmd,is->state);
- if (!(ippp_table[minor]->state & IPPP_OPEN))
+ if (!(is->state & IPPP_OPEN))
return -EINVAL;
switch (cmd) {
-#if 0
- case PPPIOCSINPSIG: /* obsolete: set input ready signal */
- /* usual: sig = SIGIO *//* we always deliver a SIGIO */
- break;
-#endif
case PPPIOCBUNDLE:
#ifdef CONFIG_ISDN_MPP
if ((r = get_arg((void *) arg, &val)))
return r;
printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
- (int) minor, (int) ippp_table[minor]->unit, (int) val);
- return isdn_ppp_bundle(minor, val);
+ (int) min, (int) is->unit, (int) val);
+ return isdn_ppp_bundle(is, val);
#else
return -1;
#endif
break;
case PPPIOCGUNIT: /* get ppp/isdn unit number */
- if ((r = set_arg((void *) arg, ippp_table[minor]->unit)))
+ if ((r = set_arg((void *) arg, is->unit)))
return r;
break;
case PPPIOCGMPFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, ippp_table[minor]->mpppcfg)))
+ if ((r = set_arg((void *) arg, is->mpppcfg)))
return r;
break;
case PPPIOCSMPFLAGS: /* set configuration flags */
if ((r = get_arg((void *) arg, &val)))
return r;
- ippp_table[minor]->mpppcfg = val;
+ is->mpppcfg = val;
break;
case PPPIOCGFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, ippp_table[minor]->pppcfg)))
+ if ((r = set_arg((void *) arg, is->pppcfg)))
return r;
break;
case PPPIOCSFLAGS: /* set configuration flags */
if ((r = get_arg((void *) arg, &val))) {
return r;
}
- if (val & SC_ENABLE_IP && !(ippp_table[minor]->pppcfg & SC_ENABLE_IP)) {
- isdn_net_local *lp = ippp_table[minor]->lp;
+ if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) {
+ isdn_net_local *lp = is->lp;
lp->netdev->dev.tbusy = 0;
mark_bh(NET_BH); /* OK .. we are ready to send buffers */
}
- ippp_table[minor]->pppcfg = val;
+ is->pppcfg = val;
break;
#if 0
case PPPIOCGSTAT: /* read PPP statistic information */
@@ -396,7 +435,7 @@
case PPPIOCSMRU: /* set receive unit size for PPP */
if ((r = get_arg((void *) arg, &val)))
return r;
- ippp_table[minor]->mru = val;
+ is->mru = val;
break;
case PPPIOCSMPMRU:
break;
@@ -406,33 +445,33 @@
if ((r = get_arg((void *) arg, &val)))
return r;
val++;
- if(ippp_table[minor]->maxcid != val) {
+ if(is->maxcid != val) {
#ifdef CONFIG_ISDN_PPP_VJ
struct slcompress *sltmp;
#endif
- if(ippp_table[minor]->debug & 0x1)
+ if(is->debug & 0x1)
printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n",val);
- ippp_table[minor]->maxcid = val;
+ is->maxcid = val;
#ifdef CONFIG_ISDN_PPP_VJ
sltmp = slhc_init(16,val);
if(!sltmp) {
printk(KERN_ERR "ippp, can't realloc slhc struct\n");
return -ENOMEM;
}
- if(ippp_table[minor]->slcomp)
- slhc_free(ippp_table[minor]->slcomp);
- ippp_table[minor]->slcomp = sltmp;
+ if(is->slcomp)
+ slhc_free(is->slcomp);
+ is->slcomp = sltmp;
#endif
}
break;
case PPPIOCGDEBUG:
- if ((r = set_arg((void *) arg, ippp_table[minor]->debug)))
+ if ((r = set_arg((void *) arg, is->debug)))
return r;
break;
case PPPIOCSDEBUG:
if ((r = get_arg((void *) arg, &val)))
return r;
- ippp_table[minor]->debug = val;
+ is->debug = val;
break;
default:
break;
@@ -440,39 +479,42 @@
return 0;
}
-int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
+int isdn_ppp_select(int min, struct file *file, int type, select_table * st)
{
struct ippp_buf_queue *bf, *bl;
unsigned long flags;
+ struct ippp_struct *is;
- if(ippp_table[minor]->debug & 0x2)
- printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",minor,type);
+ is = file->private_data;
- if (!(ippp_table[minor]->state & IPPP_OPEN))
+ if(is->debug & 0x2)
+ printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",min,type);
+
+ if (!(is->state & IPPP_OPEN))
return -EINVAL;
switch (type) {
case SEL_IN:
save_flags(flags);
cli();
- bl = ippp_table[minor]->last;
- bf = ippp_table[minor]->first;
+ bl = is->last;
+ bf = is->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);
+ if (bf->next == bl && !(is->state & IPPP_NOBLOCK)) {
+ select_wait(&is->wq, st);
restore_flags(flags);
return 0;
}
- ippp_table[minor]->state &= ~IPPP_NOBLOCK;
+ is->state &= ~IPPP_NOBLOCK;
restore_flags(flags);
return 1;
case SEL_OUT:
/* we're always ready to send .. */
return 1;
case SEL_EX:
- select_wait(&ippp_table[minor]->wq1, st);
+ select_wait(&is->wq1, st);
return 0;
}
return 1;
@@ -482,17 +524,20 @@
* fill up isdn_ppp_read() queue ..
*/
-static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int minor)
+static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot)
{
struct ippp_buf_queue *bf, *bl;
unsigned long flags;
unsigned char *nbuf;
+ struct ippp_struct *is;
- if (minor < 0 || minor >= ISDN_MAX_CHANNELS) {
- printk(KERN_WARNING "ippp: illegal minor.\n");
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+ printk(KERN_WARNING "ippp: illegal slot.\n");
return 0;
}
- if (!(ippp_table[minor]->state & IPPP_CONNECT)) {
+ is = ippp_table[slot];
+
+ if (!(is->state & IPPP_CONNECT)) {
printk(KERN_DEBUG "ippp: device not activated.\n");
return 0;
}
@@ -511,23 +556,23 @@
save_flags(flags);
cli();
- bf = ippp_table[minor]->first;
- bl = ippp_table[minor]->last;
+ bf = is->first;
+ bl = is->last;
if (bf == bl) {
printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
bf = bf->next;
kfree(bf->buf);
- ippp_table[minor]->first = bf;
+ is->first = bf;
}
bl->buf = (char *) nbuf;
bl->len = len+4;
- ippp_table[minor]->last = bl->next;
+ is->last = bl->next;
restore_flags(flags);
- if (ippp_table[minor]->wq)
- wake_up_interruptible(&ippp_table[minor]->wq);
+ if (is->wq)
+ wake_up_interruptible(&is->wq);
return len;
}
@@ -537,14 +582,16 @@
* reports, that there is data
*/
-int isdn_ppp_read(int minor, struct file *file, char *buf, int count)
+int isdn_ppp_read(int min, struct file *file, char *buf, int count)
{
- struct ippp_struct *c = ippp_table[minor];
+ struct ippp_struct *is;
struct ippp_buf_queue *b;
int r;
unsigned long flags;
- if (!(ippp_table[minor]->state & IPPP_OPEN))
+ is = file->private_data;
+
+ if (!(is->state & IPPP_OPEN))
return 0;
if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
@@ -553,7 +600,7 @@
save_flags(flags);
cli();
- b = c->first->next;
+ b = is->first->next;
if (!b->buf) {
restore_flags(flags);
return -EAGAIN;
@@ -563,7 +610,7 @@
memcpy_tofs(buf, b->buf, count);
kfree(b->buf);
b->buf = NULL;
- c->first = b;
+ is->first = b;
restore_flags(flags);
return count;
@@ -573,14 +620,17 @@
* ipppd wanna write a packet to the card .. non-blocking
*/
-int isdn_ppp_write(int minor, struct file *file, const char *buf, int count)
+int isdn_ppp_write(int min, struct file *file, const char *buf, int count)
{
isdn_net_local *lp;
+ struct ippp_struct *is;
+
+ is = file->private_data;
- if (!(ippp_table[minor]->state & IPPP_CONNECT))
+ if (!(is->state & IPPP_CONNECT))
return 0;
- lp = ippp_table[minor]->lp;
+ lp = is->lp;
/* -> push it directly to the lowlevel interface */
@@ -659,7 +709,10 @@
void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
{
- if(ippp_table[lp->ppp_minor]->debug & 0x4)
+ struct ippp_struct *is;
+ is = ippp_table[lp->ppp_slot];
+
+ if(is->debug & 0x4)
printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len);
if(net_dev->local.master) {
@@ -669,14 +722,14 @@
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 (is->pppcfg & SC_REJ_COMP_AC) {
skb->free = 1;
dev_kfree_skb(skb,0 /* FREE_READ */ );
return; /* discard it silently */
}
#ifdef CONFIG_ISDN_MPP
- if (!(ippp_table[lp->ppp_minor]->mpppcfg & SC_REJ_MP_PROT)) {
+ if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
int proto;
int sqno_end;
if (skb->data[0] & 0x1) {
@@ -690,11 +743,11 @@
isdn_net_local *lpq;
int sqno, min_sqno, tseq;
u_char BEbyte = skb->data[0];
- 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 ,
+ if(is->debug & 0x8)
+ printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, 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)) {
+ if (!(is->mpppcfg & SC_IN_SHORT_SEQ)) {
sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3];
skb_pull(skb,4);
} else {
@@ -702,26 +755,26 @@
skb_pull(skb,2);
}
- if ((tseq = ippp_table[lp->ppp_minor]->last_link_seqno) >= sqno) {
- int range = ippp_table[lp->ppp_minor]->range;
+ if ((tseq = is->last_link_seqno) >= sqno) {
+ int range = is->range;
if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %d, last: %d !!!\n", sqno, tseq);
else {
sqno += range;
- ippp_table[lp->ppp_minor]->last_link_seqno = sqno;
+ is->last_link_seqno = sqno;
}
} else
- ippp_table[lp->ppp_minor]->last_link_seqno = sqno;
+ is->last_link_seqno = sqno;
for (min_sqno = 0, lpq = net_dev->queue;;) {
- if (ippp_table[lpq->ppp_minor]->last_link_seqno > min_sqno)
- min_sqno = ippp_table[lpq->ppp_minor]->last_link_seqno;
+ if (ippp_table[lpq->ppp_slot]->last_link_seqno > min_sqno)
+ min_sqno = ippp_table[lpq->ppp_slot]->last_link_seqno;
lpq = lpq->next;
if (lpq == net_dev->queue)
break;
}
- if (min_sqno >= ippp_table[lpq->ppp_minor]->range) { /* OK, every link overflowed */
- int mask = ippp_table[lpq->ppp_minor]->range - 1; /* range is a power of 2 */
+ if (min_sqno >= ippp_table[lpq->ppp_slot]->range) { /* OK, every link overflowed */
+ int mask = ippp_table[lpq->ppp_slot]->range - 1; /* range is a power of 2 */
isdn_ppp_cleanup_queue(net_dev, min_sqno);
isdn_ppp_mask_queue(net_dev, mask);
net_dev->ib.next_num &= mask;
@@ -734,14 +787,14 @@
}
min_sqno &= mask;
for (lpq = net_dev->queue;;) {
- ippp_table[lpq->ppp_minor]->last_link_seqno &= mask;
+ ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
lpq = lpq->next;
if (lpq == net_dev->queue)
break;
}
}
if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
- printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_minor);
+ printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot);
if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0)
return; /* no packet complete */
} else
@@ -820,9 +873,14 @@
}
+/*
+ * push frame to higher layers
+ * note: net_dev has to be master net_dev
+ */
static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb,int proto)
{
struct device *dev = &net_dev->dev;
+ struct ippp_struct *is = ippp_table[lp->ppp_slot];
if (proto < 0) { /* MP, oder normales Paket bei REJ_MP, MP Pakete gehen bei REJ zum pppd */
if (skb->data[0] & 0x01) { /* is it odd? */
@@ -834,12 +892,12 @@
}
}
- if(ippp_table[lp->ppp_minor]->debug & 0x10)
+ if(is->debug & 0x10)
printk(KERN_DEBUG "push, skb %ld %04x\n",skb->len,proto);
switch (proto) {
case PPP_IPX: /* untested */
- if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ if(is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: _IPX\n");
skb->dev = dev;
skb->mac.raw = skb->data;
@@ -847,9 +905,9 @@
break;
#ifdef CONFIG_ISDN_PPP_VJ
case PPP_VJC_UNCOMP:
- if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ if(is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
- if(slhc_remember(ippp_table[net_dev->local.ppp_minor]->slcomp, skb->data, skb->len) <= 0) {
+ if(slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
net_dev->local.stats.rx_dropped++;
skb->free = 1;
@@ -858,14 +916,14 @@
}
#endif
case PPP_IP:
- if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ if(is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: IP\n");
skb->dev = dev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IP);
break;
case PPP_VJC_COMP:
- if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ if(is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
#ifdef CONFIG_ISDN_PPP_VJ
{
@@ -885,7 +943,7 @@
skb_put(skb,skb_old->len + 40);
memcpy(skb->data, skb_old->data, skb_old->len);
skb->mac.raw = skb->data;
- pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_minor]->slcomp,
+ pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
skb->data, skb_old->len);
dev_kfree_skb(skb_old,0 /* FREE_READ */ );
if(pkt_len < 0) {
@@ -906,7 +964,7 @@
#endif
break;
default:
- isdn_ppp_fill_rq(skb->data, skb->len,proto, lp->ppp_minor); /* push data to pppd device */
+ isdn_ppp_fill_rq(skb->data, skb->len,proto, lp->ppp_slot); /* push data to pppd device */
skb->free = 1;
dev_kfree_skb(skb,0 /* FREE_READ */ );
return;
@@ -928,6 +986,19 @@
* skb isn't allowed!!
*/
+static void isdn_ppp_skb_destructor(struct sk_buff *skb)
+{
+ char outstr[80],*outpnt=outstr;
+ int i;
+
+ *outpnt = 0;
+ for(i=0;i<24 && i<skb->len;i++) {
+ sprintf(outpnt,"%02x ",skb->data[i]);
+ outpnt += 3;
+ }
+ printk(KERN_DEBUG "ippp_dstrct: %s\n",outstr);
+}
+
int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
{
struct device *mdev = ((isdn_net_local *) (dev->priv) )->master; /* get master (for redundancy) */
@@ -941,13 +1012,18 @@
else
mlp = (isdn_net_local *) (dev->priv);
nd = mlp->netdev; /* get master lp */
- ipts = ippp_table[mlp->ppp_minor];
+ ipts = ippp_table[mlp->ppp_slot];
if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
- printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
- return 1;
+ if(ipts->debug & 0x1) {
+ printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
+ skb->destructor = isdn_ppp_skb_destructor;
+ }
+ return 1;
}
+ skb->destructor = NULL;
+
lp = nd->queue; /* get lp on top of queue */
if(lp->sav_skb) { /* find a non-busy device */
isdn_net_local *nlp = lp->next;
@@ -958,35 +1034,21 @@
}
lp = nlp;
}
- ipt = ippp_table[lp->ppp_minor];
+ ipt = ippp_table[lp->ppp_slot];
lp->huptimer = 0;
-
- /* If packet is to be resent, it has already been processed and
- * therefore its first bytes are already initialized. In this case
- * send it immediately ...
- */
- if (*((u32 *)skb->data) != 0) {
- printk(KERN_ERR "%s: Whoops .. packet resend should no longer happen!\n",dev->name);
- return (isdn_net_send_skb(dev , lp , skb));
- }
- /* ... else packet needs processing. */
+ /*
+ * after this line .. requeueing in the device queue is no longer allowed!!!
+ */
- if(ippp_table[lp->ppp_minor]->debug & 0x4)
+ if(ipt->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %ld\n",skb->len);
#ifdef CONFIG_ISDN_PPP_VJ
- if (ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but check again */
+ if (ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but this check again */
struct sk_buff *new_skb;
- int len = 4;
-#ifdef CONFIG_ISDN_MPP
- if (ipt->mpppcfg & SC_MP_PROT) /* sigh */ /* ipt or ipts ?? */
- if (ipt->mpppcfg & SC_OUT_SHORT_SEQ)
- len += 3;
- else
- len += 5;
-#endif
+
new_skb = dev_alloc_skb(skb->len);
if(new_skb) {
u_char *buf;
@@ -995,8 +1057,6 @@
new_skb->dev = skb->dev;
new_skb->free = 1;
skb_put(new_skb,skb->len);
- skb_pull(skb,len); /* pull PPP header */
- skb_pull(new_skb,len); /* pull PPP header */
buf = skb->data;
pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
@@ -1021,12 +1081,11 @@
proto = PPP_VJC_UNCOMP;
skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
}
- skb_push(skb,len);
}
}
#endif
- if(ippp_table[lp->ppp_minor]->debug & 0x24)
+ if(ipt->debug & 0x24)
printk(KERN_DEBUG "xmit2 skb, len %ld, proto %04x\n",skb->len,proto);
#ifdef CONFIG_ISDN_MPP
@@ -1036,22 +1095,23 @@
ipts->mp_seqno++;
nd->queue = nd->queue->next;
if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
- /* skb_push(skb, 3); Done in isdn_net_header() */
+ skb_push(skb, 3);
mp_seqno &= 0xfff;
- skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8); /* (B)egin & (E)ndbit .. */
- skb->data[5] = mp_seqno & 0xff;
- skb->data[6] = proto; /* PID compression */
+ skb->data[0] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8); /* (B)egin & (E)ndbit .. */
+ skb->data[1] = mp_seqno & 0xff;
+ skb->data[2] = proto; /* PID compression */
} else {
- /* skb_push(skb, 5); Done in isdn_net_header () */
- skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */
- skb->data[5] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */
- skb->data[6] = (mp_seqno >> 8) & 0xff;
- skb->data[7] = (mp_seqno >> 0) & 0xff;
- skb->data[8] = proto; /* PID compression */
+ skb_push(skb, 5);
+ skb->data[0] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */
+ skb->data[1] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */
+ skb->data[2] = (mp_seqno >> 8) & 0xff;
+ skb->data[3] = (mp_seqno >> 0) & 0xff;
+ skb->data[4] = proto; /* PID compression */
}
proto = PPP_MP; /* MP Protocol, 0x003d */
}
#endif
+ skb_push(skb,4);
skb->data[0] = 0xff; /* All Stations */
skb->data[1] = 0x03; /* Unnumbered information */
skb->data[2] = proto >> 8;
@@ -1100,7 +1160,7 @@
#ifdef CONFIG_ISDN_MPP
-static int isdn_ppp_bundle(int minor, int unit)
+static int isdn_ppp_bundle(struct ippp_struct *is, int unit)
{
char ifn[IFNAMSIZ + 1];
long flags;
@@ -1117,7 +1177,7 @@
save_flags(flags);
cli();
- nlp = ippp_table[minor]->lp;
+ nlp = is->lp;
lp = p->queue;
p->ib.bundled = 1;
@@ -1127,17 +1187,17 @@
nlp->next = lp;
p->queue = nlp;
- ippp_table[nlp->ppp_minor]->unit = ippp_table[lp->ppp_minor]->unit;
+ ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
/* maybe also SC_CCP stuff */
- ippp_table[nlp->ppp_minor]->pppcfg |= ippp_table[lp->ppp_minor]->pppcfg &
+ ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
(SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
- ippp_table[nlp->ppp_minor]->mpppcfg |= ippp_table[lp->ppp_minor]->mpppcfg &
+ ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
(SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
#if 0
- if (ippp_table[nlp->ppp_minor]->mpppcfg != ippp_table[lp->ppp_minor]->mpppcfg) {
+ if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) {
printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n",
- ippp_table[nlp->ppp_minor]->mpppcfg, ippp_table[lp->ppp_minor]->mpppcfg);
+ ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg);
}
#endif
@@ -1325,7 +1385,7 @@
#ifdef CONFIG_ISDN_PPP_VJ
/* did we free a stale frame ? */
if(toss)
- slhc_toss(ippp_table[dev->local.ppp_minor]->slcomp);
+ slhc_toss(ippp_table[dev->local.ppp_slot]->slcomp);
#endif
}
@@ -1355,7 +1415,7 @@
#ifdef CONFIG_ISDN_PPP_VJ
/* did we step over a missing frame ? */
if(q->sqno_start != net_dev->ib.next_num)
- slhc_toss(ippp_table[lp->ppp_minor]->slcomp);
+ slhc_toss(ippp_table[lp->ppp_slot]->slcomp);
#endif
ql = net_dev->ib.sq;
@@ -1381,7 +1441,7 @@
* network device ioctl handlers
*/
-static int isdn_ppp_dev_ioctl_stats(int minor,struct ifreq *ifr,struct device *dev)
+static int isdn_ppp_dev_ioctl_stats(int slot,struct ifreq *ifr,struct device *dev)
{
struct ppp_stats *res, t;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -1402,8 +1462,8 @@
t.p.ppp_opackets = lp->stats.tx_packets;
t.p.ppp_oerrors = lp->stats.tx_errors;
#ifdef CONFIG_ISDN_PPP_VJ
- if(minor >= 0 && ippp_table[minor]->slcomp) {
- struct slcompress *slcomp = ippp_table[minor]->slcomp;
+ if(slot >= 0 && ippp_table[slot]->slcomp) {
+ struct slcompress *slcomp = ippp_table[slot]->slcomp;
t.vj.vjs_packets = slcomp->sls_o_compressed+slcomp->sls_o_uncompressed;
t.vj.vjs_compressed = slcomp->sls_o_compressed;
t.vj.vjs_searches = slcomp->sls_o_searches;
@@ -1428,7 +1488,7 @@
isdn_net_local *lp = (isdn_net_local *) dev->priv;
#if 0
- printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n",cmd,lp->ppp_minor);
+ printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n",cmd,lp->ppp_slot);
#endif
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
@@ -1443,7 +1503,7 @@
memcpy_tofs(r, PPP_VERSION, len);
break;
case SIOCGPPPSTATS:
- error = isdn_ppp_dev_ioctl_stats (lp->ppp_minor, ifr, dev);
+ error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
break;
default:
error = -EINVAL;
@@ -1452,24 +1512,26 @@
return error;
}
-static int isdn_ppp_if_get_unit(char **namebuf)
+static int isdn_ppp_if_get_unit(char *name)
{
- char *name = *namebuf;
int len, i, unit = 0, deci;
len = strlen(name);
+
+ if(strncmp("ippp",name,4) || len > 8)
+ return -1;
+
for (i = 0, deci = 1; i < len; i++, deci *= 10) {
- if (name[len - 1 - i] >= '0' && name[len - 1 - i] <= '9')
- unit += (name[len - 1 - i] - '0') * deci;
+ char a = name[len-i-1];
+ if (a >= '0' && a <= '9')
+ unit += (a - '0') * deci;
else
break;
}
- if (!i)
+ if (!i || len-i != 4)
unit = -1;
- *namebuf = name + len - 1 - i;
return unit;
-
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov