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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [isdn_ppp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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