OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [isdn_ppp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* $Id: isdn_ppp.c,v 1.1.1.1 2001-09-10 07:44:18 simons Exp $
2
 *
3
 * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
4
 *
5
 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2, or (at your option)
10
 * any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 *
21
 * $Log: not supported by cvs2svn $
22
 * Revision 1.1.1.1  2001/07/02 17:58:31  simons
23
 * Initial revision
24
 *
25
 * Revision 1.28.2.3  1998/12/30 17:49:00  paul
26
 * fixed syncPPP callback out
27
 *
28
 * Revision 1.28.2.2  1998/11/03 14:31:23  fritz
29
 * Reduced stack usage in various functions.
30
 * Adapted statemachine to work with certified HiSax.
31
 * Some fixes in callback handling.
32
 *
33
 * Revision 1.28.2.1  1998/03/16 09:56:02  cal
34
 * Merged in TimRu-patches. Still needs validation in conjunction with ABC-patches.
35
 *
36
 * Revision 1.28  1997/06/17 13:05:57  hipp
37
 * Applied Eric's underflow-patches (slightly modified)
38
 * more compression changes (but disabled at the moment)
39
 * changed one copy_to_user() to run with enabled IRQs
40
 * a few MP changes
41
 * changed 'proto' handling in the isdn_ppp receive code
42
 *
43
 * Revision 1.27  1997/03/30 16:51:17  calle
44
 * changed calls to copy_from_user/copy_to_user and removed verify_area
45
 * were possible.
46
 *
47
 * Revision 1.26  1997/02/23 16:53:44  hipp
48
 * minor cleanup
49
 * some initial changes for future PPP compresion
50
 * added AC,PC compression for outgoing frames
51
 *
52
 * Revision 1.25  1997/02/12 20:37:35  hipp
53
 * New ioctl() PPPIOCGCALLINFO, minor cleanup
54
 *
55
 * Revision 1.24  1997/02/11 18:32:56  fritz
56
 * Bugfix in isdn_ppp_free_mpqueue().
57
 *
58
 * Revision 1.23  1997/02/10 11:12:19  fritz
59
 * More changes for Kernel 2.1.X compatibility.
60
 *
61
 * Revision 1.22  1997/02/06 15:03:51  hipp
62
 * changed GFP_KERNEL kmalloc to GFP_ATOMIC in isdn_ppp_fill_mpqueue()
63
 *
64
 * Revision 1.21  1997/02/03 23:29:38  fritz
65
 * Reformatted according CodingStyle
66
 * Bugfix: removed isdn_ppp_skb_destructor, used by upper layers.
67
 * Misc changes for Kernel 2.1.X compatibility.
68
 *
69
 * Revision 1.20  1996/10/30 12:21:58  fritz
70
 * Cosmetic fix: Compiler warning when compiling without MPP.
71
 *
72
 * Revision 1.19  1996/10/25 19:03:21  hipp
73
 * changed/added some defines to (re)allow compilation without MP/VJ
74
 *
75
 * Revision 1.18  1996/10/22 23:14:00  fritz
76
 * Changes for compatibility to 2.0.X and 2.1.X kernels.
77
 *
78
 * Revision 1.17  1996/10/22 09:39:49  hipp
79
 * a few MP changes and bugfixes
80
 *
81
 * Revision 1.16  1996/09/23 01:58:10  fritz
82
 * Fix: With syncPPP encapsulation, discard LCP packets
83
 *      when calculating hangup timeout.
84
 *
85
 * Revision 1.15  1996/09/07 12:50:12  hipp
86
 * bugfixes (unknown device after failed dial attempt, minor bugs)
87
 *
88
 * Revision 1.14  1996/08/12 16:26:47  hipp
89
 * code cleanup
90
 * changed connection management from minors to slots
91
 *
92
 * Revision 1.13  1996/07/01 19:47:24  hipp
93
 * Fixed memory leak in VJ handling and more VJ changes
94
 *
95
 * Revision 1.12  1996/06/24 17:42:03  fritz
96
 * Minor bugfixes.
97
 *
98
 * Revision 1.11  1996/06/16 17:46:05  tsbogend
99
 * changed unsigned long to u32 to make Alpha people happy
100
 *
101
 * Revision 1.10  1996/06/11 14:50:29  hipp
102
 * Lot of changes and bugfixes.
103
 * New scheme to resend packets to busy LL devices.
104
 *
105
 * Revision 1.9  1996/05/18 01:37:01  fritz
106
 * Added spelling corrections and some minor changes
107
 * to stay in sync with kernel.
108
 *
109
 * Revision 1.8  1996/05/06 11:34:55  hipp
110
 * fixed a few bugs
111
 *
112
 * Revision 1.7  1996/04/30 11:07:42  fritz
113
 * Added Michael's ippp-bind patch.
114
 *
115
 * Revision 1.6  1996/04/30 09:33:09  fritz
116
 * Removed compatibility-macros.
117
 *
118
 * Revision 1.5  1996/04/20 16:32:32  fritz
119
 * Changed ippp_table to an array of pointers, allocating each part
120
 * separately.
121
 *
122
 * Revision 1.4  1996/02/19 15:25:50  fritz
123
 * Bugfix: Sync-PPP packets got compressed twice, when resent due to
124
 * send-queue-full reject.
125
 *
126
 * Revision 1.3  1996/02/11 02:27:12  fritz
127
 * Lot of Bugfixes my Michael.
128
 * Moved calls to skb_push() into isdn_net_header()
129
 * Fixed a possible race-condition in isdn_ppp_timer_timeout().
130
 *
131
 * Revision 1.2  1996/01/22 05:08:06  fritz
132
 * Merged in Michael's patches for MP.
133
 * Minor changes in isdn_ppp_xmit.
134
 *
135
 * Revision 1.1  1996/01/09 04:11:29  fritz
136
 * Initial revision
137
 *
138
 */
139
 
140
/* TODO: right tbusy handling when using MP */
141
 
142
/*
143
 * experimental for dynamic addressing: readdress IP frames
144
 */
145
#undef ISDN_SYNCPPP_READDRESS
146
 
147
#include <linux/config.h>
148
#define __NO_VERSION__
149
#include <linux/module.h>
150
#include <linux/version.h>
151
#include <linux/isdn.h>
152
#if (LINUX_VERSION_CODE >= 0x020117)
153
#include <asm/poll.h>
154
#endif
155
#include "isdn_common.h"
156
#include "isdn_ppp.h"
157
#include "isdn_net.h"
158
 
159
#ifndef PPP_IPX
160
#define PPP_IPX 0x002b
161
#endif
162
 
163
/* set this if you use dynamic addressing */
164
 
165
/* Prototypes */
166
static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
167
static int isdn_ppp_closewait(int slot);
168
static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
169
                                 struct sk_buff *skb, int proto);
170
static int isdn_ppp_if_get_unit(char *namebuf);
171
static int isdn_ppp_set_compressor(struct ippp_struct *is,int num);
172
static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
173
                                struct ippp_struct *,struct ippp_struct *);
174
static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
175
                                struct sk_buff *skb);
176
static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
177
        struct ippp_struct *is,struct ippp_struct *master,int type);
178
 
179
#ifdef CONFIG_ISDN_MPP
180
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
181
static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
182
static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min);
183
static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev, isdn_net_local *, long min);
184
static void isdn_ppp_free_sqqueue(isdn_net_dev *);
185
static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
186
                                 int BEbyte, long *sqno, int min_sqno);
187
static void isdn_ppp_free_mpqueue(isdn_net_dev *);
188
#endif
189
 
190
char *isdn_ppp_revision = "$Revision: 1.1.1.1 $";
191
 
192
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
193
static struct isdn_ppp_compressor *ipc_head = NULL;
194
 
195
extern int isdn_net_force_dial_lp(isdn_net_local *);
196
 
197
/*
198
 * frame log (debug)
199
 */
200
static void
201
isdn_ppp_frame_log(char *info, char *data, int len, int maxlen)
202
{
203
        int cnt,
204
         j,
205
         i;
206
        char buf[80];
207
 
208
        if (len < maxlen)
209
                maxlen = len;
210
 
211
        for (i = 0, cnt = 0; cnt < maxlen; i++) {
212
                for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
213
                        sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
214
                printk(KERN_DEBUG "%s[%d]: %s\n", info, i, buf);
215
        }
216
}
217
 
218
/*
219
 * unbind isdn_net_local <=> ippp-device
220
 * note: it can happen, that we hangup/free the master before the slaves
221
 */
222
int
223
isdn_ppp_free(isdn_net_local * lp)
224
{
225
#ifdef CONFIG_ISDN_MPP
226
        isdn_net_local *master_lp = lp;
227
#endif
228
        unsigned long flags;
229
        struct ippp_struct *is;
230
 
231
        if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS)
232
                return 0;
233
 
234
        is = ippp_table[lp->ppp_slot];
235
 
236
        save_flags(flags);
237
        cli();
238
#ifdef CONFIG_ISDN_MPP
239
        if (lp->master)
240
                master_lp = (isdn_net_local *) lp->master->priv;
241
 
242
        lp->last->next = lp->next;
243
        lp->next->last = lp->last;
244
        if (master_lp->netdev->queue == lp) {
245
                master_lp->netdev->queue = lp->next;
246
                if (lp->next == lp) {   /* last link in queue? */
247
                        master_lp->netdev->ib.bundled = 0;
248
                        isdn_ppp_free_mpqueue(master_lp->netdev);
249
                        isdn_ppp_free_sqqueue(master_lp->netdev);
250
                }
251
        }
252
        lp->next = lp->last = lp;       /* (re)set own pointers */
253
#endif
254
 
255
        if ((is->state & IPPP_CONNECT))
256
                isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
257
        else if (is->state & IPPP_ASSIGNED)
258
                is->state = IPPP_OPEN;  /* fallback to 'OPEN but not ASSIGEND' staet */
259
 
260
 
261
        if (is->debug & 0x1)
262
                printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
263
 
264
        is->lp = NULL;          /* link is down .. set lp to NULL */
265
#ifdef ISDN_SYNCPPP_READDRESS
266
        is->old_pa_addr = 0x0;
267
        is->old_pa_dstaddr = 0x0;
268
#endif
269
        lp->ppp_slot = -1;      /* is this OK ?? */
270
        restore_flags(flags);
271
 
272
        return 0;
273
}
274
 
275
/*
276
 * bind isdn_net_local <=> ippp-device
277
 */
278
int
279
isdn_ppp_bind(isdn_net_local * lp)
280
{
281
        int i;
282
        int unit = 0;
283
        long flags;
284
        struct ippp_struct *is;
285
 
286
        if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
287
                return -1;
288
 
289
        save_flags(flags);
290
        cli();
291
 
292
        if (lp->pppbind < 0) {  /* device bounded to ippp device ? */
293
                isdn_net_dev *net_dev = dev->netdev;
294
                char exclusive[ISDN_MAX_CHANNELS];      /* exclusive flags */
295
                memset(exclusive, 0, ISDN_MAX_CHANNELS);
296
                while (net_dev) {       /* step through net devices to find exclusive minors */
297
                        isdn_net_local *lp = &net_dev->local;
298
                        if (lp->pppbind >= 0)
299
                                exclusive[lp->pppbind] = 1;
300
                        net_dev = net_dev->next;
301
                }
302
                /*
303
                 * search a free device / slot
304
                 */
305
                for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
306
                        if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) {    /* OPEN, but not connected! */
307
                                break;
308
                        }
309
                }
310
        } else {
311
                for (i = 0; i < ISDN_MAX_CHANNELS; i++)
312
                        if (ippp_table[i]->minor == lp->pppbind &&
313
                            (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
314
                                break;
315
        }
316
 
317
        if (i >= ISDN_MAX_CHANNELS) {
318
                restore_flags(flags);
319
                printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
320
                return -1;
321
        }
322
        unit = isdn_ppp_if_get_unit(lp->name);  /* get unit number from interface name .. ugly! */
323
        if (unit < 0) {
324
                printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
325
                return -1;
326
        }
327
        lp->ppp_slot = i;
328
        is = ippp_table[i];
329
        is->lp = lp;
330
        is->unit = unit;
331
        is->state = IPPP_OPEN | IPPP_ASSIGNED;  /* assigned to a netdevice but not connected */
332
 
333
        restore_flags(flags);
334
 
335
        return lp->ppp_slot;
336
}
337
 
338
/*
339
 * kick the ipppd on the device
340
 * (wakes up daemon after B-channel connect)
341
 */
342
 
343
void
344
isdn_ppp_wakeup_daemon(isdn_net_local * lp)
345
{
346
        if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS)
347
                return;
348
 
349
        ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
350
 
351
        if (ippp_table[lp->ppp_slot]->wq)
352
                wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
353
}
354
 
355
/*
356
 * there was a hangup on the netdevice
357
 * force wakeup of the ippp device
358
 * go into 'device waits for release' state
359
 */
360
static int
361
isdn_ppp_closewait(int slot)
362
{
363
        struct ippp_struct *is;
364
 
365
        if (slot < 0 || slot >= ISDN_MAX_CHANNELS)
366
                return 0;
367
        is = ippp_table[slot];
368
 
369
        if (is->state && is->wq)
370
                wake_up_interruptible(&is->wq);
371
 
372
        is->state = IPPP_CLOSEWAIT;
373
        return 1;
374
}
375
 
376
/*
377
 * isdn_ppp_find_slot / isdn_ppp_free_slot
378
 */
379
 
380
static int
381
isdn_ppp_get_slot(void)
382
{
383
        int i;
384
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
385
                if (!ippp_table[i]->state)
386
                        return i;
387
        }
388
        return -1;
389
}
390
 
391
/*
392
 * isdn_ppp_open
393
 */
394
 
395
int
396
isdn_ppp_open(int min, struct file *file)
397
{
398
        int slot;
399
        struct ippp_struct *is;
400
 
401
        if (min < 0 || min > ISDN_MAX_CHANNELS)
402
                return -ENODEV;
403
 
404
        slot = isdn_ppp_get_slot();
405
        if (slot < 0) {
406
                return -EBUSY;
407
        }
408
        is = file->private_data = ippp_table[slot];
409
 
410
        if (is->debug & 0x1)
411
                printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
412
 
413
        /* compression stuff */
414
        is->compressor = NULL;
415
        is->decomp_stat = is->comp_stat = NULL;
416
        is->link_compressor = NULL;
417
        is->link_decomp_stat = is->link_comp_stat = NULL;
418
 
419
        is->lp = NULL;
420
        is->mp_seqno = 0;       /* MP sequence number */
421
        is->pppcfg = 0;         /* ppp configuration */
422
        is->mpppcfg = 0;        /* mppp configuration */
423
        is->range = 0x1000000;  /* MP: 24 bit range */
424
        is->last_link_seqno = -1;       /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
425
        is->unit = -1;          /* set, when we have our interface */
426
        is->mru = 1524;         /* MRU, default 1524 */
427
        is->maxcid = 16;        /* VJ: maxcid */
428
        is->tk = current;
429
        is->wq = NULL;          /* read() wait queue */
430
        is->wq1 = NULL;         /* select() wait queue */
431
        is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
432
        is->last = is->rq;
433
        is->minor = min;
434
#ifdef CONFIG_ISDN_PPP_VJ
435
        /*
436
         * VJ header compression init
437
         */
438
        is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
439
#endif
440
 
441
        is->state = IPPP_OPEN;
442
 
443
        return 0;
444
}
445
 
446
/*
447
 * release ippp device
448
 */
449
void
450
isdn_ppp_release(int min, struct file *file)
451
{
452
        int i;
453
        struct ippp_struct *is;
454
 
455
        if (min < 0 || min >= ISDN_MAX_CHANNELS)
456
                return;
457
        is = file->private_data;
458
 
459
        if (is->debug & 0x1)
460
                printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
461
 
462
        if (is->lp) {           /* a lp address says: this link is still up */
463
                isdn_net_dev *p = is->lp->netdev;
464
 
465
                is->state &= ~IPPP_CONNECT;     /* -> effect: no call of wakeup */
466
                /*
467
                 * isdn_net_hangup() calls isdn_ppp_free()
468
                 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
469
                 * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
470
                 */
471
                isdn_net_hangup(&p->dev);
472
        }
473
        for (i = 0; i < NUM_RCV_BUFFS; i++) {
474
                if (is->rq[i].buf) {
475
                        kfree(is->rq[i].buf);
476
                        is->rq[i].buf = NULL;
477
                }
478
        }
479
        is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
480
        is->last = is->rq;
481
 
482
#ifdef CONFIG_ISDN_PPP_VJ
483
        slhc_free(is->slcomp);
484
        is->slcomp = NULL;
485
#endif
486
 
487
        is->state = 0;
488
}
489
 
490
/*
491
 * get_arg .. ioctl helper
492
 */
493
static int
494
get_arg(void *b, void *val, int len)
495
{
496
        int r;
497
        if (len <= 0)
498
                len = sizeof(unsigned long);
499
        if ((r = copy_from_user((void *) val, b, len)))
500
                return r;
501
        return 0;
502
}
503
 
504
/*
505
 * set arg .. ioctl helper
506
 */
507
static int
508
set_arg(void *b, unsigned long val, void *str)
509
{
510
        int r;
511
        if (!str) {
512
                if ((r = copy_to_user(b, (void *) &val, 4)))
513
                        return r;
514
        } else {
515
                if ((r = copy_to_user(b, str, val)))
516
                        return r;
517
        }
518
        return 0;
519
}
520
 
521
/*
522
 * ippp device ioctl
523
 */
524
int
525
isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
526
{
527
        unsigned long val;
528
        int num,r;
529
        struct ippp_struct *is;
530
        isdn_net_local *lp;
531
 
532
        is = (struct ippp_struct *) file->private_data;
533
        lp = is->lp;
534
 
535
        if (is->debug & 0x1)
536
                printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
537
 
538
        if (!(is->state & IPPP_OPEN))
539
                return -EINVAL;
540
 
541
        switch (cmd) {
542
                case PPPIOCBUNDLE:
543
#ifdef CONFIG_ISDN_MPP
544
                        if (!(is->state & IPPP_CONNECT))
545
                                return -EINVAL;
546
                        if ((r = get_arg((void *) arg, &val, 0)))
547
                                return r;
548
                        printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
549
                               (int) min, (int) is->unit, (int) val);
550
                        return isdn_ppp_bundle(is, val);
551
#else
552
                        return -1;
553
#endif
554
                        break;
555
                case PPPIOCGUNIT:       /* get ppp/isdn unit number */
556
                        if ((r = set_arg((void *) arg, is->unit, NULL)))
557
                                return r;
558
                        break;
559
                case PPPIOCGMPFLAGS:    /* get configuration flags */
560
                        if ((r = set_arg((void *) arg, is->mpppcfg, NULL)))
561
                                return r;
562
                        break;
563
                case PPPIOCSMPFLAGS:    /* set configuration flags */
564
                        if ((r = get_arg((void *) arg, &val, 0)))
565
                                return r;
566
                        is->mpppcfg = val;
567
                        break;
568
                case PPPIOCGFLAGS:      /* get configuration flags */
569
                        if ((r = set_arg((void *) arg, is->pppcfg, NULL)))
570
                                return r;
571
                        break;
572
                case PPPIOCSFLAGS:      /* set configuration flags */
573
                        if ((r = get_arg((void *) arg, &val, 0))) {
574
                                return r;
575
                        }
576
                        if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
577
                                if (lp) {
578
                                        lp->netdev->dev.tbusy = 0;
579
                                        mark_bh(NET_BH);        /* OK .. we are ready to send buffers */
580
                                }
581
                        }
582
                        is->pppcfg = val;
583
                        break;
584
#if 0
585
                case PPPIOCGSTAT:       /* read PPP statistic information */
586
                        break;
587
#endif
588
                case PPPIOCGIDLE:       /* get idle time information */
589
                        if (lp) {
590
                                struct ppp_idle pidle;
591
                                pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
592
                                if ((r = set_arg((void *) arg, sizeof(struct ppp_idle), &pidle)))
593
                                         return r;
594
                        }
595
                        break;
596
                case PPPIOCSMRU:        /* set receive unit size for PPP */
597
                        if ((r = get_arg((void *) arg, &val, 0)))
598
                                return r;
599
                        is->mru = val;
600
                        break;
601
                case PPPIOCSMPMRU:
602
                        break;
603
                case PPPIOCSMPMTU:
604
                        break;
605
                case PPPIOCSMAXCID:     /* set the maximum compression slot id */
606
                        if ((r = get_arg((void *) arg, &val, 0)))
607
                                return r;
608
                        val++;
609
                        if (is->maxcid != val) {
610
#ifdef CONFIG_ISDN_PPP_VJ
611
                                struct slcompress *sltmp;
612
#endif
613
                                if (is->debug & 0x1)
614
                                        printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
615
                                is->maxcid = val;
616
#ifdef CONFIG_ISDN_PPP_VJ
617
                                sltmp = slhc_init(16, val);
618
                                if (!sltmp) {
619
                                        printk(KERN_ERR "ippp, can't realloc slhc struct\n");
620
                                        return -ENOMEM;
621
                                }
622
                                if (is->slcomp)
623
                                        slhc_free(is->slcomp);
624
                                is->slcomp = sltmp;
625
#endif
626
                        }
627
                        break;
628
                case PPPIOCGDEBUG:
629
                        if ((r = set_arg((void *) arg, is->debug, 0)))
630
                                return r;
631
                        break;
632
                case PPPIOCSDEBUG:
633
                        if ((r = get_arg((void *) arg, &val, 0)))
634
                                return r;
635
                        is->debug = val;
636
                        break;
637
                case PPPIOCGCOMPRESSORS:
638
                        {
639
                                unsigned long protos = 0;
640
                                struct isdn_ppp_compressor *ipc = ipc_head;
641
                                while(ipc) {
642
                                        protos |= (0x1<<ipc->num);
643
                                        ipc = ipc->next;
644
                                }
645
                                if ((r = set_arg((void *) arg, protos, 0)))
646
                                        return r;
647
                        }
648
                        break;
649
                case PPPIOCSCOMPRESSOR:
650
                        if ((r = get_arg((void *) arg, &num, sizeof(int))))
651
                                return r;
652
                        return isdn_ppp_set_compressor(is, num);
653
                        break;
654
                case PPPIOCGCALLINFO:
655
                        {
656
                                struct pppcallinfo *pci;
657
 
658
                                if ((pci = (struct pppcallinfo *)kmalloc(sizeof(struct pppcallinfo), GFP_KERNEL)) == NULL)
659
                                        return -ENOMEM;
660
                                memset((char *) pci,0,sizeof(struct pppcallinfo));
661
                                if(lp)
662
                                {
663
                                        strncpy(pci->local_num,lp->msn,63);
664
                                        if(lp->dial) {
665
                                                strncpy(pci->remote_num,lp->dial->num,63);
666
                                        }
667
                                        pci->charge_units = lp->charge;
668
                                        if(lp->outgoing)
669
                                                pci->calltype = CALLTYPE_OUTGOING;
670
                                        else
671
                                                pci->calltype = CALLTYPE_INCOMING;
672
                                        if(lp->flags & ISDN_NET_CALLBACK)
673
                                                pci->calltype |= CALLTYPE_CALLBACK;
674
                                }
675
                                r = set_arg((void *)arg,sizeof(struct pppcallinfo),pci);
676
                                kfree(pci);
677
                                return r;
678
                        }
679
                default:
680
                        break;
681
        }
682
        return 0;
683
}
684
 
685
#if (LINUX_VERSION_CODE < 0x020117)
686
int
687
isdn_ppp_select(int min, struct file *file, int type, select_table * st)
688
{
689
        struct ippp_buf_queue *bf,
690
        *bl;
691
        unsigned long flags;
692
        struct ippp_struct *is;
693
 
694
        is = file->private_data;
695
 
696
        if (is->debug & 0x2)
697
                printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n", min, type);
698
 
699
        if (!(is->state & IPPP_OPEN))
700
                return -EINVAL;
701
 
702
        switch (type) {
703
                case SEL_IN:
704
                        save_flags(flags);
705
                        cli();
706
                        bl = is->last;
707
                        bf = is->first;
708
                        /*
709
                         * if IPPP_NOBLOCK is set we return even if we have nothing to read
710
                         */
711
                        if (bf->next == bl && !(is->state & IPPP_NOBLOCK)) {
712
                                select_wait(&is->wq, st);
713
                                restore_flags(flags);
714
                                return 0;
715
                        }
716
                        is->state &= ~IPPP_NOBLOCK;
717
                        restore_flags(flags);
718
                        return 1;
719
                case SEL_OUT:
720
                        /* we're always ready to send .. */
721
                        return 1;
722
                case SEL_EX:
723
                        select_wait(&is->wq1, st);
724
                        return 0;
725
        }
726
        return 1;
727
}
728
#else
729
unsigned int
730
isdn_ppp_poll(struct file *file, poll_table * wait)
731
{
732
        unsigned int mask;
733
        struct ippp_buf_queue *bf;
734
        struct ippp_buf_queue *bl;
735
        unsigned long flags;
736
        struct ippp_struct *is;
737
 
738
        is = file->private_data;
739
 
740
        if (is->debug & 0x2)
741
                printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", MINOR(file->f_inode->i_rdev));
742
 
743
        poll_wait(&is->wq, wait);
744
 
745
        if (!(is->state & IPPP_OPEN)) {
746
                printk(KERN_DEBUG "isdn_ppp: device not open\n");
747
                return POLLERR;
748
        }
749
        /* we're always ready to send .. */
750
        mask = POLLOUT | POLLWRNORM;
751
 
752
        save_flags(flags);
753
        cli();
754
        bl = is->last;
755
        bf = is->first;
756
        /*
757
         * if IPPP_NOBLOCK is set we return even if we have nothing to read
758
         */
759
        if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
760
                is->state &= ~IPPP_NOBLOCK;
761
                mask |= POLLIN | POLLRDNORM;
762
        }
763
        restore_flags(flags);
764
        return mask;
765
}
766
#endif
767
 
768
 
769
/*
770
 *  fill up isdn_ppp_read() queue ..
771
 */
772
 
773
static int
774
isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
775
{
776
        struct ippp_buf_queue *bf,
777
        *bl;
778
        unsigned long flags;
779
        unsigned char *nbuf;
780
        struct ippp_struct *is;
781
 
782
        if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
783
                printk(KERN_WARNING "ippp: illegal slot.\n");
784
                return 0;
785
        }
786
        is = ippp_table[slot];
787
 
788
        if (!(is->state & IPPP_CONNECT)) {
789
                printk(KERN_DEBUG "ippp: device not activated.\n");
790
                return 0;
791
        }
792
        nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
793
        if (!nbuf) {
794
                printk(KERN_WARNING "ippp: Can't alloc buf\n");
795
                return 0;
796
        }
797
        nbuf[0] = PPP_ALLSTATIONS;
798
        nbuf[1] = PPP_UI;
799
        nbuf[2] = proto >> 8;
800
        nbuf[3] = proto & 0xff;
801
        memcpy(nbuf + 4, buf, len);
802
 
803
        save_flags(flags);
804
        cli();
805
 
806
        bf = is->first;
807
        bl = is->last;
808
 
809
        if (bf == bl) {
810
                printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
811
                bf = bf->next;
812
                kfree(bf->buf);
813
                is->first = bf;
814
        }
815
        bl->buf = (char *) nbuf;
816
        bl->len = len + 4;
817
 
818
        is->last = bl->next;
819
        restore_flags(flags);
820
 
821
        if (is->wq)
822
                wake_up_interruptible(&is->wq);
823
 
824
        return len;
825
}
826
 
827
/*
828
 * read() .. non-blocking: ipppd calls it only after select()
829
 *           reports, that there is data
830
 */
831
 
832
int
833
isdn_ppp_read(int min, struct file *file, char *buf, int count)
834
{
835
        struct ippp_struct *is;
836
        struct ippp_buf_queue *b;
837
        int r;
838
        unsigned long flags;
839
        unsigned char *save_buf;
840
 
841
        is = file->private_data;
842
 
843
        if (!(is->state & IPPP_OPEN))
844
                return 0;
845
 
846
        if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
847
                return r;
848
 
849
        save_flags(flags);
850
        cli();
851
 
852
        b = is->first->next;
853
        save_buf = b->buf;
854
        if (!save_buf) {
855
                restore_flags(flags);
856
                return -EAGAIN;
857
        }
858
        if (b->len < count)
859
                count = b->len;
860
        b->buf = NULL;
861
        is->first = b;
862
 
863
        restore_flags(flags);
864
 
865
        copy_to_user(buf, save_buf, count);
866
        kfree(save_buf);
867
 
868
        return count;
869
}
870
 
871
/*
872
 * ipppd wanna write a packet to the card .. non-blocking
873
 */
874
 
875
int
876
isdn_ppp_write(int min, struct file *file, const char *buf, int count)
877
{
878
        isdn_net_local *lp;
879
        struct ippp_struct *is;
880
        int proto;
881
        unsigned char protobuf[4];
882
 
883
        is = file->private_data;
884
 
885
        if (!(is->state & IPPP_CONNECT))
886
                return 0;
887
 
888
        lp = is->lp;
889
 
890
        /* -> push it directly to the lowlevel interface */
891
 
892
        if (!lp)
893
                printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
894
        else {
895
                /*
896
                 * Don't reset huptimer for
897
                 * LCP packets. (Echo requests).
898
                 */
899
                if (copy_from_user(protobuf, buf, 4))
900
                        return -EFAULT;
901
                proto = PPP_PROTOCOL(protobuf);
902
                if (proto != PPP_LCP)
903
                        lp->huptimer = 0;
904
 
905
                if (lp->isdn_device < 0 || lp->isdn_channel < 0)
906
                        return 0;
907
 
908
                if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
909
                        lp->dialstate == 0 &&
910
                    (lp->flags & ISDN_NET_CONNECTED)) {
911
                        int cnt;
912
                        struct sk_buff *skb;
913
                        skb = dev_alloc_skb(count);
914
                        if (!skb) {
915
                                printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
916
                                return count;
917
                        }
918
                        SET_SKB_FREE(skb);
919
                        if (copy_from_user(skb_put(skb, count), buf, count))
920
                                return -EFAULT;
921
                        if (is->debug & 0x40) {
922
                                printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
923
                                isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
924
                        }
925
 
926
                        if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb)) != count) {
927
                                if (lp->sav_skb) {
928
                                        dev_kfree_skb(lp->sav_skb, FREE_WRITE);
929
                                        printk(KERN_INFO "isdn_ppp_write: freeing sav_skb (%d,%d)!\n", cnt, count);
930
                                } else
931
                                        printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", cnt, count);
932
                                lp->sav_skb = skb;
933
                        }
934
                }
935
        }
936
        return count;
937
}
938
 
939
/*
940
 * init memory, structures etc.
941
 */
942
 
943
int
944
isdn_ppp_init(void)
945
{
946
        int i,
947
         j;
948
 
949
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
950
                if (!(ippp_table[i] = (struct ippp_struct *)
951
                      kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
952
                        printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
953
                        for (j = 0; j < i; j++)
954
                                kfree(ippp_table[i]);
955
                        return -1;
956
                }
957
                memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
958
                ippp_table[i]->state = 0;
959
                ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
960
                ippp_table[i]->last = ippp_table[i]->rq;
961
 
962
                for (j = 0; j < NUM_RCV_BUFFS; j++) {
963
                        ippp_table[i]->rq[j].buf = NULL;
964
                        ippp_table[i]->rq[j].last = ippp_table[i]->rq +
965
                            (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
966
                        ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
967
                }
968
        }
969
        return 0;
970
}
971
 
972
void
973
isdn_ppp_cleanup(void)
974
{
975
        int i;
976
 
977
        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
978
                kfree(ippp_table[i]);
979
}
980
 
981
/*
982
 * get the PPP protocol header and pull skb
983
 */
984
static int isdn_ppp_strip_proto(struct sk_buff *skb)
985
{
986
        int proto;
987
        if (skb->data[0] & 0x1) {
988
                proto = skb->data[0];
989
                skb_pull(skb, 1);   /* protocol ID is only 8 bit */
990
        } else {
991
                proto = ((int) skb->data[0] << 8) + skb->data[1];
992
                skb_pull(skb, 2);
993
        }
994
        return proto;
995
}
996
 
997
 
998
/*
999
 * handler for incoming packets on a syncPPP interface
1000
 */
1001
void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
1002
{
1003
        struct ippp_struct *is;
1004
        int proto;
1005
 
1006
        is = ippp_table[lp->ppp_slot];
1007
 
1008
        if (is->debug & 0x4) {
1009
                printk(KERN_DEBUG "ippp_receive: len: %d\n", (int) skb->len);
1010
                isdn_ppp_frame_log("receive", skb->data, skb->len, 32);
1011
        }
1012
        if (net_dev->local.master) {
1013
                printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
1014
                net_dev = ((isdn_net_local *) net_dev->local.master->priv)->netdev;
1015
        }
1016
        if (skb->data[0] == 0xff && skb->data[1] == 0x03)
1017
                skb_pull(skb, 2);
1018
        else if (is->pppcfg & SC_REJ_COMP_AC) {
1019
                SET_SKB_FREE(skb);
1020
                dev_kfree_skb(skb, 0 /* FREE_READ */ );
1021
                return;         /* discard it silently */
1022
        }
1023
 
1024
        proto = isdn_ppp_strip_proto(skb);
1025
 
1026
#ifdef CONFIG_ISDN_MPP
1027
        if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
1028
                int sqno_end;
1029
 
1030
                if(proto == PPP_LINK_COMP) {
1031
                        printk(KERN_DEBUG "received single link compressed frame\n");
1032
                        skb = isdn_ppp_decompress(skb,is,NULL);
1033
                        if(!skb)
1034
                                return;
1035
                        proto = isdn_ppp_strip_proto(skb);
1036
                }
1037
 
1038
                if (proto == PPP_MP) {
1039
                        isdn_net_local *lpq;
1040
                        long sqno, min_sqno, tseq;
1041
 
1042
                        u_char BEbyte = skb->data[0];
1043
                        if (is->debug & 0x8)
1044
                                printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto,
1045
                                       (int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
1046
                                       (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
1047
                        if (!(is->mpppcfg & SC_IN_SHORT_SEQ)) {
1048
                                sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3];
1049
                                skb_pull(skb, 4);
1050
                        } else {
1051
                                sqno = (((int) skb->data[0] & 0xf) << 8) + (int) skb->data[1];
1052
                                skb_pull(skb, 2);
1053
                        }
1054
 
1055
                        /*
1056
                         * new sequence number lower than last number? (this is only allowed
1057
                         * for overflow case)
1058
                         */
1059
                        if ((tseq = is->last_link_seqno) >= sqno) {
1060
                                int range = is->range;
1061
                                if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
1062
                                        printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq);
1063
                                else {
1064
                                        sqno += range;
1065
                                        is->last_link_seqno = sqno;
1066
                                }
1067
                        } else {
1068
                                /* here, we should also add an redundancy check */
1069
                                is->last_link_seqno = sqno;
1070
                        }
1071
 
1072
                        /*
1073
                         * step over all links to find lowest link number
1074
                         */
1075
                        for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) {
1076
                                long lls = ippp_table[lpq->ppp_slot]->last_link_seqno;
1077
                                if (lls >= 0 && lls < min_sqno)
1078
                                        min_sqno = lls;
1079
                                lpq = lpq->next;
1080
                                if (lpq == net_dev->queue)
1081
                                        break;
1082
                        }
1083
 
1084
                        /*
1085
                         * for the case, that the last frame numbers of all
1086
                         * links are overflowed: mask/reduce the sequenece number to
1087
                         * 'normal' numbering.
1088
                         */
1089
                        if (min_sqno >= ippp_table[lpq->ppp_slot]->range) {
1090
                                int mask = ippp_table[lpq->ppp_slot]->range-1;  /* range is power of two, so a mask will do the job */
1091
                                isdn_ppp_mask_queue(net_dev, mask);
1092
                                net_dev->ib.next_num &= mask;
1093
                                {
1094
                                        struct sqqueue *q = net_dev->ib.sq;
1095
                                        while (q) {
1096
                                                q->sqno_start &= mask;
1097
                                                q->sqno_end &= mask;
1098
                                        }
1099
                                }
1100
                                min_sqno &= mask;
1101
                                for (lpq = net_dev->queue;;) {
1102
                                        ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
1103
                                        lpq = lpq->next;
1104
                                        if (lpq == net_dev->queue)
1105
                                                break;
1106
                                }
1107
                        }
1108
                        if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
1109
                                static int dmes = 0;
1110
                                if( !dmes ) {
1111
                                        printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot);
1112
                                        dmes = 1;
1113
                                }
1114
                                if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb, BEbyte, &sqno, min_sqno)) < 0) {
1115
                                        net_dev->ib.modify = 1; /* block timeout-timer */
1116
                                        isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno);
1117
                                        net_dev->ib.modify = 0;
1118
                                        return; /* no packet complete */
1119
                                }
1120
                        } else
1121
                                sqno_end = sqno;
1122
 
1123
                        if (is->debug & 0x40)
1124
                                printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n", min_sqno, sqno_end, net_dev->ib.next_num);
1125
 
1126
                        /*
1127
                         * MP buffer management .. reorders incoming packets ..
1128
                         * lotsa mem-copies and not heavily tested.
1129
                         *
1130
                         * first check whether there is more than one link in the bundle
1131
                         * then check whether the number is in order
1132
                         */
1133
                        net_dev->ib.modify = 1; /* block timeout-timer */
1134
                        if (net_dev->ib.bundled && net_dev->ib.next_num != sqno) {
1135
                                /*
1136
                                 * packet is not 'in order'
1137
                                 */
1138
                                struct sqqueue *q;
1139
 
1140
                                q = (struct sqqueue *) kmalloc(sizeof(struct sqqueue), GFP_ATOMIC);
1141
                                if (!q) {
1142
                                        net_dev->ib.modify = 0;
1143
                                        printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n");
1144
                                        SET_SKB_FREE(skb);
1145
                                        dev_kfree_skb(skb, 0 /* FREE_READ */ );
1146
                                        return; /* discard */
1147
                                }
1148
                                q->skb = skb;
1149
                                q->sqno_end = sqno_end;
1150
                                q->sqno_start = sqno;
1151
                                q->timer = jiffies + (ISDN_TIMER_1SEC) * 5;     /* timeout after 5 seconds */
1152
 
1153
                                if (!net_dev->ib.sq) {
1154
                                        net_dev->ib.sq = q;
1155
                                        q->next = NULL;
1156
                                } else {
1157
                                        struct sqqueue *ql = net_dev->ib.sq;
1158
                                        if (ql->sqno_start > q->sqno_start) {
1159
                                                q->next = ql;
1160
                                                net_dev->ib.sq = q;
1161
                                        } else {
1162
                                                while (ql->next && ql->next->sqno_start < q->sqno_start)
1163
                                                        ql = ql->next;
1164
                                                q->next = ql->next;
1165
                                                ql->next = q;
1166
                                        }
1167
                                }
1168
                        } else {
1169
                                /*
1170
                                 * packet was 'in order' .. push it higher
1171
                                 */
1172
                                net_dev->ib.next_num = sqno_end + 1;
1173
                                proto = isdn_ppp_strip_proto(skb);
1174
                                isdn_ppp_push_higher(net_dev, lp, skb, proto);
1175
                        }
1176
                        isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno);
1177
                        net_dev->ib.modify = 0;
1178
 
1179
                } else
1180
                        isdn_ppp_push_higher(net_dev, lp, skb, proto);
1181
        } else
1182
#endif
1183
                isdn_ppp_push_higher(net_dev, lp, skb, proto);
1184
}
1185
 
1186
/*
1187
 * push frame to higher layers
1188
 * note: net_dev has to be master net_dev
1189
 */
1190
static void
1191
isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
1192
{
1193
        struct device *dev = &net_dev->dev;
1194
        struct ippp_struct *is = ippp_table[lp->ppp_slot];
1195
 
1196
        if (is->debug & 0x10) {
1197
                printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
1198
                isdn_ppp_frame_log("rpush", skb->data, skb->len, 32);
1199
        }
1200
 
1201
        if(proto == PPP_COMP) {
1202
                if(!lp->master)
1203
                        skb = isdn_ppp_decompress(skb,is,is);
1204
                else
1205
                        skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]);
1206
                if(!skb)
1207
                        return;
1208
                proto = isdn_ppp_strip_proto(skb);
1209
        }
1210
 
1211
        switch (proto) {
1212
                case PPP_IPX:  /* untested */
1213
                        if (is->debug & 0x20)
1214
                                printk(KERN_DEBUG "isdn_ppp: IPX\n");
1215
                        skb->dev = dev;
1216
                        skb->mac.raw = skb->data;
1217
                        skb->protocol = htons(ETH_P_IPX);
1218
                        break;
1219
#ifdef CONFIG_ISDN_PPP_VJ
1220
                case PPP_VJC_UNCOMP:
1221
                        if (is->debug & 0x20)
1222
                                printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
1223
                        if (slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
1224
                                printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
1225
                                net_dev->local.stats.rx_dropped++;
1226
                                SET_SKB_FREE(skb);
1227
                                dev_kfree_skb(skb, 0 /* FREE_READ */ );
1228
                                return;
1229
                        }
1230
#endif
1231
                case PPP_IP:
1232
                        if (is->debug & 0x20)
1233
                                printk(KERN_DEBUG "isdn_ppp: IP\n");
1234
                        skb->dev = dev;
1235
                        skb->mac.raw = skb->data;
1236
                        skb->protocol = htons(ETH_P_IP);
1237
                        break;
1238
                case PPP_VJC_COMP:
1239
                        if (is->debug & 0x20)
1240
                                printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
1241
#ifdef CONFIG_ISDN_PPP_VJ
1242
                        {
1243
                                struct sk_buff *skb_old = skb;
1244
                                int pkt_len;
1245
                                skb = dev_alloc_skb(skb_old->len + 40);
1246
 
1247
                                SET_SKB_FREE(skb_old);
1248
 
1249
                                if (!skb) {
1250
                                        printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
1251
                                        net_dev->local.stats.rx_dropped++;
1252
                                        dev_kfree_skb(skb_old, 0 /* FREE_READ */ );
1253
                                        return;
1254
                                }
1255
                                skb->dev = dev;
1256
                                skb_put(skb, skb_old->len + 40);
1257
                                memcpy(skb->data, skb_old->data, skb_old->len);
1258
                                skb->mac.raw = skb->data;
1259
                                pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
1260
                                                skb->data, skb_old->len);
1261
                                dev_kfree_skb(skb_old, 0 /* FREE_READ */ );
1262
                                if (pkt_len < 0) {
1263
                                        SET_SKB_FREE(skb);
1264
                                        dev_kfree_skb(skb, 0 /* FREE_READ */ );
1265
                                        lp->stats.rx_dropped++;
1266
                                        return;
1267
                                }
1268
                                skb_trim(skb, pkt_len);
1269
                                skb->protocol = htons(ETH_P_IP);
1270
                        }
1271
#else
1272
                        printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n");
1273
                        lp->stats.rx_dropped++;
1274
                        SET_SKB_FREE(skb);
1275
                        dev_kfree_skb(skb, 0 /* FREE_READ */ );
1276
                        return;
1277
#endif
1278
                        break;
1279
                case PPP_CCP:
1280
                        isdn_ppp_receive_ccp(net_dev,lp,skb);
1281
                        /* fall through */
1282
                default:
1283
                        isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);     /* push data to pppd device */
1284
                        SET_SKB_FREE(skb);
1285
                        dev_kfree_skb(skb, 0 /* FREE_READ */ );
1286
                        return;
1287
        }
1288
 
1289
        /* Reset hangup-timer */
1290
        lp->huptimer = 0;
1291
        netif_rx(skb);
1292
        /* net_dev->local.stats.rx_packets++; *//* done in isdn_net.c */
1293
 
1294
        return;
1295
}
1296
 
1297
/*
1298
 * isdn_ppp_skb_push ..
1299
 * checks whether we have enough space at the beginning of the SKB
1300
 * and allocs a new SKB if necessary
1301
 */
1302
static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
1303
{
1304
        struct sk_buff *skb = *skb_p;
1305
 
1306
        if(skb_headroom(skb) < len) {
1307
                printk(KERN_ERR "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
1308
                dev_kfree_skb(skb,FREE_WRITE);
1309
                return NULL;
1310
        }
1311
        return skb_push(skb,len);
1312
}
1313
 
1314
 
1315
/*
1316
 * send ppp frame .. we expect a PIDCOMPressable proto --
1317
 *  (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
1318
 *
1319
 * VJ compression may change skb pointer!!! .. requeue with old
1320
 * skb isn't allowed!!
1321
 */
1322
 
1323
int
1324
isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
1325
{
1326
        struct device *mdev = ((isdn_net_local *) (dev->priv))->master; /* get master (for redundancy) */
1327
        isdn_net_local *lp,*mlp;
1328
        isdn_net_dev *nd;
1329
        unsigned int proto = PPP_IP;     /* 0x21 */
1330
        struct ippp_struct *ipt,*ipts;
1331
 
1332
        if (mdev)
1333
                mlp = (isdn_net_local *) (mdev->priv);
1334
        else {
1335
                mdev = dev;
1336
                mlp = (isdn_net_local *) (dev->priv);
1337
        }
1338
        nd = mlp->netdev;       /* get master lp */
1339
        ipts = ippp_table[mlp->ppp_slot];
1340
 
1341
        if (!(ipts->pppcfg & SC_ENABLE_IP)) {   /* PPP connected ? */
1342
#ifdef ISDN_SYNCPPP_READDRESS
1343
                if (!ipts->old_pa_addr)
1344
                        ipts->old_pa_addr = mdev->pa_addr;
1345
                if (!ipts->old_pa_dstaddr)
1346
                        ipts->old_pa_dstaddr = mdev->pa_dstaddr;
1347
#endif
1348
                if (ipts->debug & 0x1)
1349
                        printk(KERN_INFO "%s: IP frame delayed.\n", dev->name);
1350
                return 1;
1351
        }
1352
 
1353
        switch (ntohs(skb->protocol)) {
1354
                case ETH_P_IP:
1355
                        proto = PPP_IP;
1356
#ifdef ISDN_SYNCPPP_READDRESS
1357
                        if (ipts->old_pa_addr != mdev->pa_addr) {
1358
                                struct iphdr *ipfr;
1359
                                ipfr = (struct iphdr *) skb->data;
1360
                                if(ipts->debug & 0x4)
1361
                                        printk(KERN_DEBUG "IF-address changed from %lx to %lx\n", ipts->old_pa_addr, mdev->pa_addr);
1362
                                if (ipfr->version == 4) {
1363
                                        if (ipfr->saddr == ipts->old_pa_addr) {
1364
                                                printk(KERN_DEBUG "readdressing %lx to %lx\n", ipfr->saddr, mdev->pa_addr);
1365
                                                ipfr->saddr = mdev->pa_addr;
1366
                                        }
1367
                                }
1368
                        }
1369
                        /* dstaddr change not so important */
1370
#endif
1371
                        break;
1372
                case ETH_P_IPX:
1373
                        proto = PPP_IPX;        /* untested */
1374
                        break;
1375
                default:
1376
                        dev_kfree_skb(skb, FREE_WRITE);
1377
                        printk(KERN_ERR "isdn_ppp: skipped frame with unsupported protocoll: %#x.\n", skb->protocol);
1378
                        return 0;
1379
        }
1380
 
1381
        lp = nd->queue;         /* get lp on top of queue */
1382
 
1383
        if (lp->sav_skb) {      /* find a non-busy device */
1384
                isdn_net_local *nlp = lp->next;
1385
                while (lp->sav_skb) {
1386
                        if (lp == nlp)
1387
                                return 1;
1388
                        nlp = nd->queue = nd->queue->next;
1389
                }
1390
                lp = nlp;
1391
        }
1392
        ipt = ippp_table[lp->ppp_slot];
1393
 
1394
        lp->huptimer = 0;
1395
 
1396
        /*
1397
         * after this line .. requeueing in the device queue is no longer allowed!!!
1398
         */
1399
 
1400
        /* Pull off the fake header we stuck on earlier to keep
1401
         * the fragemntation code happy.
1402
         * this will break the ISDN_SYNCPPP_READDRESS hack a few lines
1403
         * above. So, enabling this is no longer allowed
1404
         */
1405
        skb_pull(skb,IPPP_MAX_HEADER);
1406
 
1407
        if (ipt->debug & 0x4)
1408
                printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
1409
 
1410
#ifdef CONFIG_ISDN_PPP_VJ
1411
        if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {    /* ipts here? probably yes, but check this again */
1412
                struct sk_buff *new_skb;
1413
 
1414
                new_skb = dev_alloc_skb(skb->len);
1415
                if (new_skb) {
1416
                        u_char *buf;
1417
                        int pktlen;
1418
 
1419
                        new_skb->dev = skb->dev;
1420
                        SET_SKB_FREE(new_skb);
1421
                        skb_put(new_skb, skb->len);
1422
                        buf = skb->data;
1423
 
1424
                        pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
1425
                                 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
1426
 
1427
                        if (buf != skb->data) {
1428
                                if (new_skb->data != buf)
1429
                                        printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
1430
                                dev_kfree_skb(skb, FREE_WRITE);
1431
                                skb = new_skb;
1432
                        } else {
1433
                                dev_kfree_skb(new_skb, 0 /* FREE_WRITE */ );
1434
                        }
1435
 
1436
                        skb_trim(skb, pktlen);
1437
                        if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) {     /* cslip? style -> PPP */
1438
                                proto = PPP_VJC_COMP;
1439
                                skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
1440
                        } else {
1441
                                if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
1442
                                        proto = PPP_VJC_UNCOMP;
1443
                                skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
1444
                        }
1445
                }
1446
        }
1447
#endif
1448
 
1449
        /*
1450
         * normal or bundle compression
1451
         */
1452
        skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
1453
 
1454
        if (ipt->debug & 0x24)
1455
                printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
1456
 
1457
#ifdef CONFIG_ISDN_MPP
1458
        if (ipt->mpppcfg & SC_MP_PROT) {
1459
                /* we get mp_seqno from static isdn_net_local */
1460
                long mp_seqno = ipts->mp_seqno;
1461
                ipts->mp_seqno++;
1462
                nd->queue = nd->queue->next;
1463
                if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
1464
                        unsigned char *data = isdn_ppp_skb_push(&skb, 3);
1465
                        if(!data)
1466
                                return 0;
1467
                        mp_seqno &= 0xfff;
1468
                        data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */
1469
                        data[1] = mp_seqno & 0xff;
1470
                        data[2] = proto;        /* PID compression */
1471
                } else {
1472
                        unsigned char *data = isdn_ppp_skb_push(&skb, 5);
1473
                        if(!data)
1474
                                return 0;
1475
                        data[0] = MP_BEGIN_FRAG | MP_END_FRAG;   /* (B)egin & (E)ndbit .. */
1476
                        data[1] = (mp_seqno >> 16) & 0xff;      /* sequence number: 24bit */
1477
                        data[2] = (mp_seqno >> 8) & 0xff;
1478
                        data[3] = (mp_seqno >> 0) & 0xff;
1479
                        data[4] = proto;        /* PID compression */
1480
                }
1481
                proto = PPP_MP; /* MP Protocol, 0x003d */
1482
        }
1483
#endif
1484
 
1485
        /*
1486
         * 'link' compression
1487
         */
1488
        skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
1489
 
1490
        if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
1491
                unsigned char *data = isdn_ppp_skb_push(&skb,1);
1492
                if(!data)
1493
                        return 0;
1494
                data[0] = proto & 0xff;
1495
        }
1496
        else {
1497
                unsigned char *data = isdn_ppp_skb_push(&skb,2);
1498
                if(!data)
1499
                        return 0;
1500
                data[0] = (proto >> 8) & 0xff;
1501
                data[1] = proto & 0xff;
1502
        }
1503
        if(!(ipt->pppcfg & SC_COMP_AC)) {
1504
                unsigned char *data = isdn_ppp_skb_push(&skb,2);
1505
                if(!data)
1506
                        return 0;
1507
                data[0] = 0xff;    /* All Stations */
1508
                data[1] = 0x03;    /* Unnumbered information */
1509
        }
1510
 
1511
        /* tx-stats are now updated via BSENT-callback */
1512
 
1513
        if (ipts->debug & 0x40) {
1514
                printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
1515
                isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
1516
        }
1517
        if (isdn_net_send_skb(dev, lp, skb)) {
1518
                if (lp->sav_skb) {      /* whole sav_skb processing with disabled IRQs ?? */
1519
                        printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", dev->name);
1520
                        dev_kfree_skb(skb, FREE_WRITE);
1521
                } else
1522
                        lp->sav_skb = skb;
1523
        }
1524
        return 0;
1525
}
1526
 
1527
#ifdef CONFIG_ISDN_MPP
1528
 
1529
static void
1530
isdn_ppp_free_sqqueue(isdn_net_dev * p)
1531
{
1532
        struct sqqueue *q = p->ib.sq;
1533
 
1534
        p->ib.sq = NULL;
1535
        while (q) {
1536
                struct sqqueue *qn = q->next;
1537
                if (q->skb) {
1538
                        SET_SKB_FREE(q->skb);
1539
                        dev_kfree_skb(q->skb, 0 /* FREE_READ */ );
1540
                }
1541
                kfree(q);
1542
                q = qn;
1543
        }
1544
 
1545
}
1546
 
1547
static void
1548
isdn_ppp_free_mpqueue(isdn_net_dev * p)
1549
{
1550
        struct mpqueue *q = p->mp_last;
1551
        p->mp_last = NULL;
1552
 
1553
        while (q) {
1554
                struct mpqueue *ql = q->next;
1555
                SET_SKB_FREE(q->skb);
1556
                dev_kfree_skb(q->skb, 0 /* FREE_READ */ );
1557
                kfree(q);
1558
                q = ql;
1559
        }
1560
}
1561
 
1562
static int
1563
isdn_ppp_bundle(struct ippp_struct *is, int unit)
1564
{
1565
        char ifn[IFNAMSIZ + 1];
1566
        long flags;
1567
        isdn_net_dev *p;
1568
        isdn_net_local *lp,
1569
        *nlp;
1570
 
1571
        sprintf(ifn, "ippp%d", unit);
1572
        p = isdn_net_findif(ifn);
1573
        if (!p)
1574
                return -1;
1575
 
1576
        isdn_timer_ctrl(ISDN_TIMER_IPPP, 1);    /* enable timer for ippp/MP */
1577
 
1578
        save_flags(flags);
1579
        cli();
1580
 
1581
        nlp = is->lp;
1582
 
1583
        lp = p->queue;
1584
        p->ib.bundled = 1;
1585
        nlp->last = lp->last;
1586
        lp->last->next = nlp;
1587
        lp->last = nlp;
1588
        nlp->next = lp;
1589
        p->queue = nlp;
1590
 
1591
        ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
1592
/* maybe also SC_CCP stuff */
1593
        ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
1594
            (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
1595
 
1596
        ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
1597
            (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
1598
#if 0
1599
        if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) {
1600
                printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n",
1601
                       ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg);
1602
        }
1603
#endif
1604
 
1605
        restore_flags(flags);
1606
        return 0;
1607
}
1608
 
1609
 
1610
static void
1611
isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
1612
{
1613
        struct mpqueue *q = dev->mp_last;
1614
        while (q) {
1615
                q->sqno &= mask;
1616
                q = q->next;
1617
        }
1618
}
1619
 
1620
static int
1621
isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno)
1622
{
1623
        struct mpqueue *qe,
1624
        *q1,
1625
        *q;
1626
        long cnt,
1627
         flags;
1628
        int pktlen,
1629
         sqno_end;
1630
        int sqno = *sqnop;
1631
 
1632
        q1 = (struct mpqueue *) kmalloc(sizeof(struct mpqueue), GFP_ATOMIC);
1633
        if (!q1) {
1634
                printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n");
1635
                save_flags(flags);
1636
                cli();
1637
                isdn_ppp_cleanup_mpqueue(dev, min_sqno);
1638
                restore_flags(flags);
1639
                return -1;
1640
        }
1641
        q1->skb = *skb;
1642
        q1->sqno = sqno;
1643
        q1->BEbyte = BEbyte;
1644
        q1->time = jiffies;
1645
 
1646
        save_flags(flags);
1647
        cli();
1648
 
1649
        if (!(q = dev->mp_last)) {
1650
                dev->mp_last = q1;
1651
                q1->next = NULL;
1652
                q1->last = NULL;
1653
                isdn_ppp_cleanup_mpqueue(dev, min_sqno);        /* not necessary */
1654
                restore_flags(flags);
1655
                return -1;      /* -1 is not an error. Just says, that this fragment hasn't complete a full frame */
1656
        }
1657
        for (;;) {              /* the faster way would be to step from the queue-end to the start */
1658
                if (sqno > q->sqno) {
1659
                        if (q->next) {
1660
                                q = q->next;
1661
                                continue;
1662
                        }
1663
                        q->next = q1;
1664
                        q1->next = NULL;
1665
                        q1->last = q;
1666
                        break;
1667
                }
1668
                if (sqno == q->sqno)
1669
                        printk(KERN_WARNING "isdn_fill_mpqueue: illegal sqno received!!\n");
1670
                q1->last = q->last;
1671
                q1->next = q;
1672
                if (q->last) {
1673
                        q->last->next = q1;
1674
                } else
1675
                        dev->mp_last = q1;
1676
                q->last = q1;
1677
                break;
1678
        }
1679
 
1680
/* now we check whether we completed a packet with this fragment */
1681
        pktlen = -q1->skb->len;
1682
        q = q1;
1683
        cnt = q1->sqno;
1684
        while (!(q->BEbyte & MP_END_FRAG)) {
1685
                cnt++;
1686
                if (!(q->next) || q->next->sqno != cnt) {
1687
                        isdn_ppp_cleanup_mpqueue(dev, min_sqno);
1688
                        restore_flags(flags);
1689
                        return -1;
1690
                }
1691
                pktlen += q->skb->len;
1692
                q = q->next;
1693
        }
1694
        pktlen += q->skb->len;
1695
        qe = q;
1696
 
1697
        q = q1;
1698
        cnt = q1->sqno;
1699
        while (!(q->BEbyte & MP_BEGIN_FRAG)) {
1700
                cnt--;
1701
                if (!(q->last) || q->last->sqno != cnt) {
1702
                        isdn_ppp_cleanup_mpqueue(dev, min_sqno);
1703
                        restore_flags(flags);
1704
                        return -1;
1705
                }
1706
                pktlen += q->skb->len;
1707
                q = q->last;
1708
        }
1709
        pktlen += q->skb->len;
1710
 
1711
        if (q->last)
1712
                q->last->next = qe->next;
1713
        else
1714
                dev->mp_last = qe->next;
1715
 
1716
        if (qe->next)
1717
                qe->next->last = q->last;
1718
        qe->next = NULL;
1719
        sqno_end = qe->sqno;
1720
        *sqnop = q->sqno;
1721
 
1722
        isdn_ppp_cleanup_mpqueue(dev, min_sqno);
1723
        restore_flags(flags);
1724
 
1725
        *skb = dev_alloc_skb(pktlen + 40);      /* not needed: +40 for VJ compression .. */
1726
 
1727
        if (!(*skb)) {
1728
                while (q) {
1729
                        struct mpqueue *ql = q->next;
1730
                        SET_SKB_FREE(q->skb);
1731
                        dev_kfree_skb(q->skb, 0 /* FREE_READ */ );
1732
                        kfree(q);
1733
                        q = ql;
1734
                }
1735
                return -2;
1736
        }
1737
        cnt = 0;
1738
        skb_put(*skb, pktlen);
1739
        while (q) {
1740
                struct mpqueue *ql = q->next;
1741
                memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
1742
                cnt += q->skb->len;
1743
                SET_SKB_FREE(q->skb);
1744
                dev_kfree_skb(q->skb, 0 /* FREE_READ */ );
1745
                kfree(q);
1746
                q = ql;
1747
        }
1748
 
1749
        return sqno_end;
1750
}
1751
 
1752
/*
1753
 * check sq-queue, whether we have still buffered the next packet(s)
1754
 * or packets with a sqno less or equal to min_sqno
1755
 * net_dev: master netdevice , lp: 'real' local connection
1756
 */
1757
static void
1758
isdn_ppp_cleanup_sqqueue(isdn_net_dev * net_dev, isdn_net_local * lp, long min_sqno)
1759
{
1760
        struct sqqueue *q;
1761
 
1762
        while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno)) {
1763
                int proto;
1764
                if (q->sqno_start != net_dev->ib.next_num) {
1765
                        printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n", net_dev->ib.next_num);
1766
#ifdef CONFIG_ISDN_PPP_VJ
1767
                        slhc_toss(ippp_table[net_dev->local.ppp_slot]->slcomp);
1768
#endif
1769
                }
1770
                proto = isdn_ppp_strip_proto(q->skb);
1771
                isdn_ppp_push_higher(net_dev, lp, q->skb, proto);
1772
                net_dev->ib.sq = q->next;
1773
                net_dev->ib.next_num = q->sqno_end + 1;
1774
                kfree(q);
1775
        }
1776
}
1777
 
1778
/*
1779
 * remove stale packets from list
1780
 */
1781
static void
1782
isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno)
1783
{
1784
#ifdef CONFIG_ISDN_PPP_VJ
1785
        int toss = 0;
1786
#endif
1787
/* z.z einfaches aussortieren gammeliger pakete. Fuer die Zukunft:
1788
   eventuell, solange vorne kein B-paket ist und sqno<=min_sqno: auch rauswerfen
1789
   wenn sqno<min_sqno und Luecken vorhanden sind: auch weg (die koennen nicht mehr gefuellt werden)
1790
   bei paketen groesser min_sqno: ueber mp_mrru: wenn summe ueber pktlen der rumhaengenden Pakete
1791
   groesser als mrru ist: raus damit , Pakete muessen allerdings zusammenhaengen sonst koennte
1792
   ja ein Paket mit B und eins mit E dazwischenpassen */
1793
 
1794
        struct mpqueue *ql,
1795
        *q = dev->mp_last;
1796
        while(q && (q->sqno < min_sqno) ) {
1797
                if ( (q->BEbyte & MP_END_FRAG) ||
1798
                         (q->next && (q->next->sqno <= min_sqno) && (q->next->BEbyte & MP_BEGIN_FRAG)) ) {
1799
                        printk(KERN_DEBUG "ippp: freeing stale packet(s), min_sq: %ld!\n",min_sqno);
1800
                        if ((dev->mp_last = q->next))
1801
                                q->next->last = NULL;
1802
                        while (q) {
1803
                                ql = q->last;
1804
                                SET_SKB_FREE(q->skb);
1805
                                printk(KERN_DEBUG "ippp, freeing packet with sqno: %ld\n",q->sqno);
1806
                                dev_kfree_skb(q->skb, 0 /* FREE_READ */ );
1807
                                kfree(q);
1808
#ifdef CONFIG_ISDN_PPP_VJ
1809
                                toss = 1;
1810
#endif
1811
                                q = ql;
1812
                        }
1813
                        q = dev->mp_last;
1814
                } else
1815
                        q = q->next;
1816
        }
1817
#ifdef CONFIG_ISDN_PPP_VJ
1818
        /* did we free a stale frame ? */
1819
        if (toss)
1820
                slhc_toss(ippp_table[dev->local.ppp_slot]->slcomp);
1821
#endif
1822
}
1823
 
1824
/*
1825
 * a buffered packet timed-out?
1826
 */
1827
 
1828
#endif
1829
 
1830
void
1831
isdn_ppp_timer_timeout(void)
1832
{
1833
#ifdef CONFIG_ISDN_MPP
1834
        isdn_net_dev *net_dev = dev->netdev;
1835
        struct sqqueue *q,
1836
        *ql = NULL,
1837
        *qn;
1838
 
1839
        while (net_dev) {
1840
                isdn_net_local *lp = &net_dev->local;
1841
                if (net_dev->ib.modify || lp->master) { /* interface locked or slave? */
1842
                        net_dev = net_dev->next;
1843
                        continue;
1844
                }
1845
                q = net_dev->ib.sq;
1846
                while (q) {
1847
                        if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) {
1848
 
1849
#ifdef CONFIG_ISDN_PPP_VJ
1850
                                /* did we step over a missing frame ? */
1851
                                if (q->sqno_start != net_dev->ib.next_num)
1852
                                        slhc_toss(ippp_table[lp->ppp_slot]->slcomp);
1853
#endif
1854
 
1855
                                ql = net_dev->ib.sq;
1856
                                net_dev->ib.sq = q->next;
1857
                                net_dev->ib.next_num = q->sqno_end + 1;
1858
                                q->next = NULL;
1859
                                for (; ql;) {
1860
                                        int proto = isdn_ppp_strip_proto(ql->skb);
1861
                                        isdn_ppp_push_higher(net_dev, lp, ql->skb, proto);
1862
                                        qn = ql->next;
1863
                                        kfree(ql);
1864
                                        ql = qn;
1865
                                }
1866
                                q = net_dev->ib.sq;
1867
                        } else
1868
                                q = q->next;
1869
                }
1870
                net_dev = net_dev->next;
1871
        }
1872
#endif
1873
}
1874
 
1875
/*
1876
 * network device ioctl handlers
1877
 */
1878
 
1879
static int
1880
isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct device *dev)
1881
{
1882
        struct ppp_stats *res,
1883
         t;
1884
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
1885
        int err;
1886
 
1887
        res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
1888
        err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats));
1889
 
1890
        if (err)
1891
                return err;
1892
 
1893
        /* build a temporary stat struct and copy it to user space */
1894
 
1895
        memset(&t, 0, sizeof(struct ppp_stats));
1896
        if (dev->flags & IFF_UP) {
1897
                t.p.ppp_ipackets = lp->stats.rx_packets;
1898
                t.p.ppp_ierrors = lp->stats.rx_errors;
1899
                t.p.ppp_opackets = lp->stats.tx_packets;
1900
                t.p.ppp_oerrors = lp->stats.tx_errors;
1901
#ifdef CONFIG_ISDN_PPP_VJ
1902
                if (slot >= 0 && ippp_table[slot]->slcomp) {
1903
                        struct slcompress *slcomp = ippp_table[slot]->slcomp;
1904
                        t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
1905
                        t.vj.vjs_compressed = slcomp->sls_o_compressed;
1906
                        t.vj.vjs_searches = slcomp->sls_o_searches;
1907
                        t.vj.vjs_misses = slcomp->sls_o_misses;
1908
                        t.vj.vjs_errorin = slcomp->sls_i_error;
1909
                        t.vj.vjs_tossed = slcomp->sls_i_tossed;
1910
                        t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
1911
                        t.vj.vjs_compressedin = slcomp->sls_i_compressed;
1912
                }
1913
#endif
1914
        }
1915
        return copy_to_user(res, &t, sizeof(struct ppp_stats));
1916
}
1917
 
1918
int
1919
isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
1920
{
1921
        int error;
1922
        char *r;
1923
        int len;
1924
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
1925
 
1926
#if 0
1927
        printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n", cmd, lp->ppp_slot);
1928
#endif
1929
 
1930
        if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
1931
                return -EINVAL;
1932
 
1933
        switch (cmd) {
1934
                case SIOCGPPPVER:
1935
                        r = (char *) ifr->ifr_ifru.ifru_data;
1936
                        len = strlen(PPP_VERSION) + 1;
1937
                        error = copy_to_user(r, PPP_VERSION, len);
1938
                        break;
1939
                case SIOCGPPPSTATS:
1940
                        error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
1941
                        break;
1942
                default:
1943
                        error = -EINVAL;
1944
                        break;
1945
        }
1946
        return error;
1947
}
1948
 
1949
static int
1950
isdn_ppp_if_get_unit(char *name)
1951
{
1952
        int len,
1953
         i,
1954
         unit = 0,
1955
         deci;
1956
 
1957
        len = strlen(name);
1958
 
1959
        if (strncmp("ippp", name, 4) || len > 8)
1960
                return -1;
1961
 
1962
        for (i = 0, deci = 1; i < len; i++, deci *= 10) {
1963
                char a = name[len - i - 1];
1964
                if (a >= '0' && a <= '9')
1965
                        unit += (a - '0') * deci;
1966
                else
1967
                        break;
1968
        }
1969
        if (!i || len - i != 4)
1970
                unit = -1;
1971
 
1972
        return unit;
1973
}
1974
 
1975
 
1976
int
1977
isdn_ppp_dial_slave(char *name)
1978
{
1979
#ifdef CONFIG_ISDN_MPP
1980
        isdn_net_dev *ndev;
1981
        isdn_net_local *lp;
1982
        struct device *sdev;
1983
 
1984
        if (!(ndev = isdn_net_findif(name)))
1985
                return 1;
1986
        lp = &ndev->local;
1987
        if (!(lp->flags & ISDN_NET_CONNECTED))
1988
                return 5;
1989
 
1990
        sdev = lp->slave;
1991
        while (sdev) {
1992
                isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
1993
                if (!(mlp->flags & ISDN_NET_CONNECTED))
1994
                        break;
1995
                sdev = mlp->slave;
1996
        }
1997
        if (!sdev)
1998
                return 2;
1999
 
2000
        isdn_net_force_dial_lp((isdn_net_local *) sdev->priv);
2001
        return 0;
2002
#else
2003
        return -1;
2004
#endif
2005
}
2006
 
2007
int
2008
isdn_ppp_hangup_slave(char *name)
2009
{
2010
#ifdef CONFIG_ISDN_MPP
2011
        isdn_net_dev *ndev;
2012
        isdn_net_local *lp;
2013
        struct device *sdev;
2014
 
2015
        if (!(ndev = isdn_net_findif(name)))
2016
                return 1;
2017
        lp = &ndev->local;
2018
        if (!(lp->flags & ISDN_NET_CONNECTED))
2019
                return 5;
2020
 
2021
        sdev = lp->slave;
2022
        while (sdev) {
2023
                isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
2024
                if ((mlp->flags & ISDN_NET_CONNECTED))
2025
                        break;
2026
                sdev = mlp->slave;
2027
        }
2028
        if (!sdev)
2029
                return 2;
2030
 
2031
        isdn_net_hangup(sdev);
2032
        return 0;
2033
#else
2034
        return -1;
2035
#endif
2036
}
2037
 
2038
/*
2039
 * PPP compression stuff
2040
 */
2041
static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master)
2042
{
2043
#if 1
2044
        printk(KERN_ERR "compression not included!\n");
2045
        SET_SKB_FREE(skb);
2046
        dev_kfree_skb(skb,FREE_WRITE);
2047
        return NULL;
2048
#else
2049
        if(!master) {
2050
                /*
2051
                 * single link compression
2052
                 */
2053
                if(!is->link_compressor) {
2054
                        printk(KERN_ERR "ippp: no (link) compressor defined!\n");
2055
                        SET_SKB_FREE(skb);
2056
                        dev_kfree_skb(skb,FREE_WRITE);
2057
                        return NULL;
2058
                }
2059
                if(!is->link_decomp_stat) {
2060
                        printk(KERN_DEBUG "ippp: initialize link compressor\n");
2061
                }
2062
/*
2063
                -> decompress link
2064
*/
2065
    }
2066
        else {
2067
                /*
2068
                 * 'normal' or bundle-compression
2069
                 */
2070
                if(!master->compressor) {
2071
                        printk(KERN_ERR "ippp: no (link) compressor defined!\n");
2072
                        SET_SKB_FREE(skb);
2073
                        dev_kfree_skb(skb,FREE_WRITE);
2074
                        return NULL;
2075
                }
2076
                if(!master->decomp_stat) {
2077
#if 0
2078
                        master->decomp_stat = (master->compressor->decomp_alloc)( .. );
2079
#endif
2080
                        printk(KERN_DEBUG "ippp: initialize compressor\n");
2081
                }
2082
        }
2083
 
2084
        return skb;
2085
#endif
2086
}
2087
 
2088
/*
2089
 * compress a frame
2090
 *   type=0: normal/bundle compression
2091
 *       =1: link compression
2092
 * returns original skb if we haven't compressed the frame
2093
 * and a new skb pointer if we've done it
2094
 */
2095
static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
2096
        struct ippp_struct *is,struct ippp_struct *master,int type)
2097
{
2098
#if 1   
2099
        return skb_in;
2100
#else
2101
    int ret;
2102
    int new_proto;
2103
    struct isdn_ppp_compressor *compressor;
2104
    void *stat;
2105
    struct sk_buff *skb_out;
2106
 
2107
        if(type) { /* type=1 => Link compression */
2108
                compressor = is->link_compressor;
2109
                stat = is->link_comp_stat;
2110
                new_proto = PPP_LINK_COMP;
2111
        }
2112
        else {
2113
                if(!master) {
2114
                        compressor = is->compressor;
2115
                        stat = is->comp_stat;
2116
                }
2117
                else {
2118
                        compressor = master->compressor;
2119
                        stat = master->comp_stat;
2120
                }
2121
                new_proto = PPP_COMP;
2122
        }
2123
 
2124
        if(!compressor) {
2125
                printk(KERN_ERR "No compressor set!\n");
2126
                return skb_in;
2127
        }
2128
        if(!stat) {
2129
                /* init here ? */
2130
                return skb_in;
2131
        }
2132
 
2133
        skb_out = dev_alloc_skb(skb_in->len);
2134
        if(!skb_out)
2135
                return skb_in;
2136
 
2137
        ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
2138
        if(!ret) {
2139
                SET_SKB_FREE(skb_out);
2140
                dev_kfree_skb(skb_out,0);
2141
                return skb_in;
2142
        }
2143
 
2144
        dev_kfree_skb(skb_in,FREE_WRITE);
2145
        *proto = new_proto;
2146
        return skb_out;
2147
#endif
2148
 
2149
}
2150
 
2151
/*
2152
 * we received a CCP frame ..
2153
 * not a clean solution, but we SHOULD handle a few cased in the kernel
2154
 */
2155
static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
2156
         struct sk_buff *skb)
2157
{
2158
#if 0
2159
        printk(KERN_DEBUG "isdn_ppp_receive_cpp: %02x %02x %02x %02x %02x %02x %02x %02x\n",
2160
                skb->data[0],skb->data[1],skb->data[2],skb->data[3],
2161
                skb->data[4],skb->data[5],skb->data[6],skb->data[7] );
2162
#endif
2163
}
2164
 
2165
int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
2166
{
2167
        ipc->next = ipc_head;
2168
        ipc->prev = NULL;
2169
        if(ipc_head) {
2170
                ipc_head->prev = ipc;
2171
        }
2172
        ipc_head = ipc;
2173
        return 0;
2174
}
2175
 
2176
int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
2177
{
2178
        if(ipc->prev)
2179
                ipc->prev->next = ipc->next;
2180
        else
2181
                ipc_head = ipc->next;
2182
        if(ipc->next)
2183
                ipc->next->prev = ipc->prev;
2184
        ipc->prev = ipc->next = NULL;
2185
        return 0;
2186
}
2187
 
2188
static int isdn_ppp_set_compressor(struct ippp_struct *is,int num)
2189
{
2190
        struct isdn_ppp_compressor *ipc = ipc_head;
2191
 
2192
        while(ipc) {
2193
                if(ipc->num == num) {
2194
                        return 0;
2195
                        is->compressor = ipc;
2196
                        is->link_compressor = ipc;
2197
                }
2198
                ipc = ipc->next;
2199
        }
2200
        return -EINVAL;
2201
}
2202
 
2203
 
2204
#if 0
2205
static struct symbol_table isdn_ppp_syms =
2206
{
2207
#include <linux/symtab_begin.h>
2208
        X(isdn_ppp_register_compressor),
2209
        X(isdn_ppp_unregister_compressor),
2210
#include <linux/symtab_end.h>
2211
};
2212
#endif
2213
 
2214
 
2215
 
2216
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.