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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [isdn/] [isdn_ppp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: isdn_ppp.c,v 1.1.1.1 2004-04-15 02:03:40 phoenix 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 software may be used and distributed according to the terms
8
 * of the GNU General Public License, incorporated herein by reference.
9
 *
10
 */
11
 
12
#include <linux/config.h>
13
#include <linux/isdn.h>
14
#include <linux/poll.h>
15
#include <linux/ppp-comp.h>
16
#ifdef CONFIG_IPPP_FILTER
17
#include <linux/filter.h>
18
#endif
19
 
20
#include "isdn_common.h"
21
#include "isdn_ppp.h"
22
#include "isdn_net.h"
23
 
24
#ifndef PPP_IPX
25
#define PPP_IPX 0x002b
26
#endif
27
 
28
/* Prototypes */
29
static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
30
static int isdn_ppp_closewait(int slot);
31
static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
32
                                 struct sk_buff *skb, int proto);
33
static int isdn_ppp_if_get_unit(char *namebuf);
34
static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
35
static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
36
                                struct ippp_struct *,struct ippp_struct *,int *proto);
37
static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
38
                                struct sk_buff *skb,int proto);
39
static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
40
        struct ippp_struct *is,struct ippp_struct *master,int type);
41
static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
42
         struct sk_buff *skb);
43
 
44
/* New CCP stuff */
45
static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
46
static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
47
                                    unsigned char code, unsigned char id,
48
                                    unsigned char *data, int len);
49
static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
50
static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
51
static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
52
                                          unsigned char id);
53
static void isdn_ppp_ccp_timer_callback(unsigned long closure);
54
static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
55
                                                      unsigned char id);
56
static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
57
                                     struct isdn_ppp_resetparams *rp);
58
static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
59
                                        unsigned char id);
60
 
61
 
62
 
63
#ifdef CONFIG_ISDN_MPP
64
static ippp_bundle * isdn_ppp_bundle_arr = NULL;
65
 
66
static int isdn_ppp_mp_bundle_array_init(void);
67
static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to );
68
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
69
                                                        struct sk_buff *skb);
70
static void isdn_ppp_mp_cleanup( isdn_net_local * lp );
71
 
72
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
73
#endif  /* CONFIG_ISDN_MPP */
74
 
75
char *isdn_ppp_revision = "$Revision: 1.1.1.1 $";
76
 
77
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
78
 
79
static struct isdn_ppp_compressor *ipc_head = NULL;
80
 
81
/*
82
 * frame log (debug)
83
 */
84
static void
85
isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
86
{
87
        int cnt,
88
         j,
89
         i;
90
        char buf[80];
91
 
92
        if (len < maxlen)
93
                maxlen = len;
94
 
95
        for (i = 0, cnt = 0; cnt < maxlen; i++) {
96
                for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
97
                        sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
98
                printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
99
        }
100
}
101
 
102
/*
103
 * unbind isdn_net_local <=> ippp-device
104
 * note: it can happen, that we hangup/free the master before the slaves
105
 *       in this case we bind another lp to the master device
106
 */
107
int
108
isdn_ppp_free(isdn_net_local * lp)
109
{
110
        unsigned long flags;
111
        struct ippp_struct *is;
112
 
113
        if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
114
                printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
115
                        __FUNCTION__, lp->ppp_slot);
116
                return 0;
117
        }
118
 
119
        save_flags(flags);
120
        cli();
121
 
122
#ifdef CONFIG_ISDN_MPP
123
        spin_lock(&lp->netdev->pb->lock);
124
#endif
125
        isdn_net_rm_from_bundle(lp);
126
#ifdef CONFIG_ISDN_MPP
127
        if (lp->netdev->pb->ref_ct == 1)        /* last link in queue? */
128
                isdn_ppp_mp_cleanup(lp);
129
 
130
        lp->netdev->pb->ref_ct--;
131
        spin_unlock(&lp->netdev->pb->lock);
132
#endif /* CONFIG_ISDN_MPP */
133
        if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
134
                printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
135
                        __FUNCTION__, lp->ppp_slot);
136
                restore_flags(flags);
137
                return 0;
138
        }
139
        is = ippp_table[lp->ppp_slot];
140
        if ((is->state & IPPP_CONNECT))
141
                isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
142
        else if (is->state & IPPP_ASSIGNED)
143
                is->state = IPPP_OPEN;  /* fallback to 'OPEN but not ASSIGNED' state */
144
 
145
        if (is->debug & 0x1)
146
                printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
147
 
148
        is->lp = NULL;          /* link is down .. set lp to NULL */
149
        lp->ppp_slot = -1;      /* is this OK ?? */
150
 
151
        restore_flags(flags);
152
        return 0;
153
}
154
 
155
/*
156
 * bind isdn_net_local <=> ippp-device
157
 */
158
int
159
isdn_ppp_bind(isdn_net_local * lp)
160
{
161
        int i;
162
        int unit = 0;
163
        long flags;
164
        struct ippp_struct *is;
165
        int retval;
166
 
167
        save_flags(flags);
168
        cli();
169
        if (lp->pppbind < 0) {  /* device bounded to ippp device ? */
170
                isdn_net_dev *net_dev = dev->netdev;
171
                char exclusive[ISDN_MAX_CHANNELS];      /* exclusive flags */
172
                memset(exclusive, 0, ISDN_MAX_CHANNELS);
173
                while (net_dev) {       /* step through net devices to find exclusive minors */
174
                        isdn_net_local *lp = net_dev->local;
175
                        if (lp->pppbind >= 0)
176
                                exclusive[lp->pppbind] = 1;
177
                        net_dev = net_dev->next;
178
                }
179
                /*
180
                 * search a free device / slot
181
                 */
182
                for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
183
                        if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) {    /* OPEN, but not connected! */
184
                                break;
185
                        }
186
                }
187
        } else {
188
                for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
189
                        if (ippp_table[i]->minor == lp->pppbind &&
190
                            (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
191
                                break;
192
                }
193
        }
194
 
195
        if (i >= ISDN_MAX_CHANNELS) {
196
                restore_flags(flags);
197
                printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
198
                retval = -1;
199
                goto out;
200
        }
201
        unit = isdn_ppp_if_get_unit(lp->name);  /* get unit number from interface name .. ugly! */
202
        if (unit < 0) {
203
                printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
204
                retval = -1;
205
                goto out;
206
        }
207
 
208
        lp->ppp_slot = i;
209
        is = ippp_table[i];
210
        is->lp = lp;
211
        is->unit = unit;
212
        is->state = IPPP_OPEN | IPPP_ASSIGNED;  /* assigned to a netdevice but not connected */
213
#ifdef CONFIG_ISDN_MPP
214
        retval = isdn_ppp_mp_init(lp, NULL);
215
        if (retval < 0)
216
                goto out;
217
#endif /* CONFIG_ISDN_MPP */
218
 
219
        retval = lp->ppp_slot;
220
 
221
 out:
222
        restore_flags(flags);
223
        return retval;
224
}
225
 
226
/*
227
 * kick the ipppd on the device
228
 * (wakes up daemon after B-channel connect)
229
 */
230
 
231
void
232
isdn_ppp_wakeup_daemon(isdn_net_local * lp)
233
{
234
        if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
235
                printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
236
                        __FUNCTION__, lp->ppp_slot);
237
                return;
238
        }
239
        ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
240
        wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
241
}
242
 
243
/*
244
 * there was a hangup on the netdevice
245
 * force wakeup of the ippp device
246
 * go into 'device waits for release' state
247
 */
248
static int
249
isdn_ppp_closewait(int slot)
250
{
251
        struct ippp_struct *is;
252
 
253
        if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
254
                printk(KERN_ERR "%s: slot(%d) out of range\n",
255
                        __FUNCTION__, slot);
256
                return 0;
257
        }
258
        is = ippp_table[slot];
259
        if (is->state)
260
                wake_up_interruptible(&is->wq);
261
        is->state = IPPP_CLOSEWAIT;
262
        return 1;
263
}
264
 
265
/*
266
 * isdn_ppp_find_slot / isdn_ppp_free_slot
267
 */
268
 
269
static int
270
isdn_ppp_get_slot(void)
271
{
272
        int i;
273
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
274
                if (!ippp_table[i]->state)
275
                        return i;
276
        }
277
        return -1;
278
}
279
 
280
/*
281
 * isdn_ppp_open
282
 */
283
 
284
int
285
isdn_ppp_open(int min, struct file *file)
286
{
287
        int slot;
288
        struct ippp_struct *is;
289
 
290
        if (min < 0 || min > ISDN_MAX_CHANNELS)
291
                return -ENODEV;
292
 
293
        slot = isdn_ppp_get_slot();
294
        if (slot < 0) {
295
                return -EBUSY;
296
        }
297
        is = file->private_data = ippp_table[slot];
298
 
299
        printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
300
               slot, min, is->state);
301
 
302
        /* compression stuff */
303
        is->link_compressor   = is->compressor = NULL;
304
        is->link_decompressor = is->decompressor = NULL;
305
        is->link_comp_stat    = is->comp_stat = NULL;
306
        is->link_decomp_stat  = is->decomp_stat = NULL;
307
        is->compflags = 0;
308
 
309
        is->reset = isdn_ppp_ccp_reset_alloc(is);
310
 
311
        is->lp = NULL;
312
        is->mp_seqno = 0;       /* MP sequence number */
313
        is->pppcfg = 0;         /* ppp configuration */
314
        is->mpppcfg = 0;        /* mppp configuration */
315
        is->last_link_seqno = -1;       /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
316
        is->unit = -1;          /* set, when we have our interface */
317
        is->mru = 1524;         /* MRU, default 1524 */
318
        is->maxcid = 16;        /* VJ: maxcid */
319
        is->tk = current;
320
        init_waitqueue_head(&is->wq);
321
        is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
322
        is->last = is->rq;
323
        is->minor = min;
324
#ifdef CONFIG_ISDN_PPP_VJ
325
        /*
326
         * VJ header compression init
327
         */
328
        is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
329
#endif
330
#ifdef CONFIG_IPPP_FILTER
331
        is->pass_filter.filter = NULL;
332
        is->active_filter.filter = NULL;
333
#endif
334
        is->state = IPPP_OPEN;
335
 
336
        return 0;
337
}
338
 
339
/*
340
 * release ippp device
341
 */
342
void
343
isdn_ppp_release(int min, struct file *file)
344
{
345
        int i;
346
        struct ippp_struct *is;
347
 
348
        if (min < 0 || min >= ISDN_MAX_CHANNELS)
349
                return;
350
        is = file->private_data;
351
 
352
        if (!is) {
353
                printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
354
                return;
355
        }
356
        if (is->debug & 0x1)
357
                printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
358
 
359
        if (is->lp) {           /* a lp address says: this link is still up */
360
                isdn_net_dev *p = is->lp->netdev;
361
 
362
                if (!p) {
363
                        printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
364
                        return;
365
                }
366
                is->state &= ~IPPP_CONNECT;     /* -> effect: no call of wakeup */
367
                /*
368
                 * isdn_net_hangup() calls isdn_ppp_free()
369
                 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
370
                 * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
371
                 */
372
                isdn_net_hangup(&p->dev);
373
        }
374
        for (i = 0; i < NUM_RCV_BUFFS; i++) {
375
                if (is->rq[i].buf) {
376
                        kfree(is->rq[i].buf);
377
                        is->rq[i].buf = NULL;
378
                }
379
        }
380
        is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
381
        is->last = is->rq;
382
 
383
#ifdef CONFIG_ISDN_PPP_VJ
384
/* TODO: if this was the previous master: link the slcomp to the new master */
385
        slhc_free(is->slcomp);
386
        is->slcomp = NULL;
387
#endif
388
#ifdef CONFIG_IPPP_FILTER
389
        if (is->pass_filter.filter) {
390
                kfree(is->pass_filter.filter);
391
                is->pass_filter.filter = NULL;
392
        }
393
        if (is->active_filter.filter) {
394
                kfree(is->active_filter.filter);
395
                is->active_filter.filter = NULL;
396
        }
397
#endif
398
 
399
/* TODO: if this was the previous master: link the stuff to the new master */
400
        if(is->comp_stat)
401
                is->compressor->free(is->comp_stat);
402
        if(is->link_comp_stat)
403
                is->link_compressor->free(is->link_comp_stat);
404
        if(is->link_decomp_stat)
405
                is->link_decompressor->free(is->link_decomp_stat);
406
        if(is->decomp_stat)
407
                is->decompressor->free(is->decomp_stat);
408
        is->compressor   = is->link_compressor   = NULL;
409
        is->decompressor = is->link_decompressor = NULL;
410
        is->comp_stat    = is->link_comp_stat    = NULL;
411
        is->decomp_stat  = is->link_decomp_stat  = NULL;
412
 
413
        /* Clean up if necessary */
414
        if(is->reset)
415
                isdn_ppp_ccp_reset_free(is);
416
 
417
        /* this slot is ready for new connections */
418
        is->state = 0;
419
}
420
 
421
/*
422
 * get_arg .. ioctl helper
423
 */
424
static int
425
get_arg(void *b, void *val, int len)
426
{
427
        if (len <= 0)
428
                len = sizeof(void *);
429
        if (copy_from_user((void *) val, b, len))
430
                return -EFAULT;
431
        return 0;
432
}
433
 
434
/*
435
 * set arg .. ioctl helper
436
 */
437
static int
438
set_arg(void *b, void *val,int len)
439
{
440
        if(len <= 0)
441
                len = sizeof(void *);
442
        if (copy_to_user(b, (void *) val, len))
443
                return -EFAULT;
444
        return 0;
445
}
446
 
447
/*
448
 * ippp device ioctl
449
 */
450
int
451
isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
452
{
453
        unsigned long val;
454
        int r,i,j;
455
        struct ippp_struct *is;
456
        isdn_net_local *lp;
457
        struct isdn_ppp_comp_data data;
458
 
459
        is = (struct ippp_struct *) file->private_data;
460
        lp = is->lp;
461
 
462
        if (is->debug & 0x1)
463
                printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
464
 
465
        if (!(is->state & IPPP_OPEN))
466
                return -EINVAL;
467
 
468
        switch (cmd) {
469
                case PPPIOCBUNDLE:
470
#ifdef CONFIG_ISDN_MPP
471
                        if (!(is->state & IPPP_CONNECT))
472
                                return -EINVAL;
473
                        if ((r = get_arg((void *) arg, &val, sizeof(val) )))
474
                                return r;
475
                        printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
476
                               (int) min, (int) is->unit, (int) val);
477
                        return isdn_ppp_bundle(is, val);
478
#else
479
                        return -1;
480
#endif
481
                        break;
482
                case PPPIOCGUNIT:       /* get ppp/isdn unit number */
483
                        if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
484
                                return r;
485
                        break;
486
                case PPPIOCGIFNAME:
487
                        if(!lp)
488
                                return -EINVAL;
489
                        if ((r = set_arg((void *) arg, lp->name, strlen(lp->name))))
490
                                return r;
491
                        break;
492
                case PPPIOCGMPFLAGS:    /* get configuration flags */
493
                        if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
494
                                return r;
495
                        break;
496
                case PPPIOCSMPFLAGS:    /* set configuration flags */
497
                        if ((r = get_arg((void *) arg, &val, sizeof(val) )))
498
                                return r;
499
                        is->mpppcfg = val;
500
                        break;
501
                case PPPIOCGFLAGS:      /* get configuration flags */
502
                        if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
503
                                return r;
504
                        break;
505
                case PPPIOCSFLAGS:      /* set configuration flags */
506
                        if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
507
                                return r;
508
                        }
509
                        if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
510
                                if (lp) {
511
                                        /* OK .. we are ready to send buffers */
512
                                        is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
513
                                        netif_wake_queue(&lp->netdev->dev);
514
                                        break;
515
                                }
516
                        }
517
                        is->pppcfg = val;
518
                        break;
519
                case PPPIOCGIDLE:       /* get idle time information */
520
                        if (lp) {
521
                                struct ppp_idle pidle;
522
                                pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
523
                                if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
524
                                         return r;
525
                        }
526
                        break;
527
                case PPPIOCSMRU:        /* set receive unit size for PPP */
528
                        if ((r = get_arg((void *) arg, &val, sizeof(val) )))
529
                                return r;
530
                        is->mru = val;
531
                        break;
532
                case PPPIOCSMPMRU:
533
                        break;
534
                case PPPIOCSMPMTU:
535
                        break;
536
                case PPPIOCSMAXCID:     /* set the maximum compression slot id */
537
                        if ((r = get_arg((void *) arg, &val, sizeof(val) )))
538
                                return r;
539
                        val++;
540
                        if (is->maxcid != val) {
541
#ifdef CONFIG_ISDN_PPP_VJ
542
                                struct slcompress *sltmp;
543
#endif
544
                                if (is->debug & 0x1)
545
                                        printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
546
                                is->maxcid = val;
547
#ifdef CONFIG_ISDN_PPP_VJ
548
                                sltmp = slhc_init(16, val);
549
                                if (!sltmp) {
550
                                        printk(KERN_ERR "ippp, can't realloc slhc struct\n");
551
                                        return -ENOMEM;
552
                                }
553
                                if (is->slcomp)
554
                                        slhc_free(is->slcomp);
555
                                is->slcomp = sltmp;
556
#endif
557
                        }
558
                        break;
559
                case PPPIOCGDEBUG:
560
                        if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
561
                                return r;
562
                        break;
563
                case PPPIOCSDEBUG:
564
                        if ((r = get_arg((void *) arg, &val, sizeof(val) )))
565
                                return r;
566
                        is->debug = val;
567
                        break;
568
                case PPPIOCGCOMPRESSORS:
569
                        {
570
                                unsigned long protos[8] = {0,};
571
                                struct isdn_ppp_compressor *ipc = ipc_head;
572
                                while(ipc) {
573
                                        j = ipc->num / (sizeof(long)*8);
574
                                        i = ipc->num % (sizeof(long)*8);
575
                                        if(j < 8)
576
                                                protos[j] |= (0x1<<i);
577
                                        ipc = ipc->next;
578
                                }
579
                                if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
580
                                        return r;
581
                        }
582
                        break;
583
                case PPPIOCSCOMPRESSOR:
584
                        if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
585
                                return r;
586
                        return isdn_ppp_set_compressor(is, &data);
587
                case PPPIOCGCALLINFO:
588
                        {
589
                                struct pppcallinfo pci;
590
                                memset((char *) &pci,0,sizeof(struct pppcallinfo));
591
                                if(lp)
592
                                {
593
                                        strncpy(pci.local_num,lp->msn,63);
594
                                        if(lp->dial) {
595
                                                strncpy(pci.remote_num,lp->dial->num,63);
596
                                        }
597
                                        pci.charge_units = lp->charge;
598
                                        if(lp->outgoing)
599
                                                pci.calltype = CALLTYPE_OUTGOING;
600
                                        else
601
                                                pci.calltype = CALLTYPE_INCOMING;
602
                                        if(lp->flags & ISDN_NET_CALLBACK)
603
                                                pci.calltype |= CALLTYPE_CALLBACK;
604
                                }
605
                                return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
606
                        }
607
#ifdef CONFIG_IPPP_FILTER
608
                case PPPIOCSPASS:
609
                case PPPIOCSACTIVE:
610
                        {
611
                                struct sock_fprog uprog, *filtp;
612
                                struct sock_filter *code = NULL;
613
                                int len, err;
614
 
615
                                if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
616
                                        return -EFAULT;
617
                                if (uprog.len > 0 && uprog.len < 65536) {
618
                                        len = uprog.len * sizeof(struct sock_filter);
619
                                        code = kmalloc(len, GFP_KERNEL);
620
                                        if (code == NULL)
621
                                                return -ENOMEM;
622
                                        if (copy_from_user(code, uprog.filter, len)) {
623
                                                kfree(code);
624
                                                return -EFAULT;
625
                                        }
626
                                        err = sk_chk_filter(code, uprog.len);
627
                                        if (err) {
628
                                                kfree(code);
629
                                                return err;
630
                                        }
631
                                }
632
                                filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
633
                                if (filtp->filter)
634
                                        kfree(filtp->filter);
635
                                filtp->filter = code;
636
                                filtp->len = uprog.len;
637
                                break;
638
                        }
639
#endif /* CONFIG_IPPP_FILTER */
640
                default:
641
                        break;
642
        }
643
        return 0;
644
}
645
 
646
unsigned int
647
isdn_ppp_poll(struct file *file, poll_table * wait)
648
{
649
        unsigned int mask;
650
        struct ippp_buf_queue *bf;
651
        struct ippp_buf_queue *bl;
652
        unsigned long flags;
653
        struct ippp_struct *is;
654
 
655
        is = file->private_data;
656
 
657
        if (is->debug & 0x2)
658
                printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
659
                                MINOR(file->f_dentry->d_inode->i_rdev));
660
 
661
        /* just registers wait_queue hook. This doesn't really wait. */
662
        poll_wait(file, &is->wq, wait);
663
 
664
        if (!(is->state & IPPP_OPEN)) {
665
                if(is->state == IPPP_CLOSEWAIT)
666
                        return POLLHUP;
667
                printk(KERN_DEBUG "isdn_ppp: device not open\n");
668
                return POLLERR;
669
        }
670
        /* we're always ready to send .. */
671
        mask = POLLOUT | POLLWRNORM;
672
 
673
        save_flags(flags);
674
        cli();
675
        bl = is->last;
676
        bf = is->first;
677
        /*
678
         * if IPPP_NOBLOCK is set we return even if we have nothing to read
679
         */
680
        if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
681
                is->state &= ~IPPP_NOBLOCK;
682
                mask |= POLLIN | POLLRDNORM;
683
        }
684
        restore_flags(flags);
685
        return mask;
686
}
687
 
688
/*
689
 *  fill up isdn_ppp_read() queue ..
690
 */
691
 
692
static int
693
isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
694
{
695
        struct ippp_buf_queue *bf,
696
        *bl;
697
        unsigned long flags;
698
        unsigned char *nbuf;
699
        struct ippp_struct *is;
700
 
701
        if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
702
                printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
703
                return 0;
704
        }
705
        is = ippp_table[slot];
706
 
707
        if (!(is->state & IPPP_CONNECT)) {
708
                printk(KERN_DEBUG "ippp: device not activated.\n");
709
                return 0;
710
        }
711
        nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
712
        if (!nbuf) {
713
                printk(KERN_WARNING "ippp: Can't alloc buf\n");
714
                return 0;
715
        }
716
        nbuf[0] = PPP_ALLSTATIONS;
717
        nbuf[1] = PPP_UI;
718
        nbuf[2] = proto >> 8;
719
        nbuf[3] = proto & 0xff;
720
        memcpy(nbuf + 4, buf, len);
721
 
722
        save_flags(flags);
723
        cli();
724
 
725
        bf = is->first;
726
        bl = is->last;
727
 
728
        if (bf == bl) {
729
                printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
730
                bf = bf->next;
731
                kfree(bf->buf);
732
                is->first = bf;
733
        }
734
        bl->buf = (char *) nbuf;
735
        bl->len = len + 4;
736
 
737
        is->last = bl->next;
738
        restore_flags(flags);
739
 
740
                wake_up_interruptible(&is->wq);
741
 
742
        return len;
743
}
744
 
745
/*
746
 * read() .. non-blocking: ipppd calls it only after select()
747
 *           reports, that there is data
748
 */
749
 
750
int
751
isdn_ppp_read(int min, struct file *file, char *buf, int count)
752
{
753
        struct ippp_struct *is;
754
        struct ippp_buf_queue *b;
755
        int r;
756
        unsigned long flags;
757
        unsigned char *save_buf;
758
 
759
        is = file->private_data;
760
 
761
        if (!(is->state & IPPP_OPEN))
762
                return 0;
763
 
764
        if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
765
                return r;
766
 
767
        save_flags(flags);
768
        cli();
769
 
770
        b = is->first->next;
771
        save_buf = b->buf;
772
        if (!save_buf) {
773
                restore_flags(flags);
774
                return -EAGAIN;
775
        }
776
        if (b->len < count)
777
                count = b->len;
778
        b->buf = NULL;
779
        is->first = b;
780
 
781
        restore_flags(flags);
782
 
783
        copy_to_user(buf, save_buf, count);
784
        kfree(save_buf);
785
 
786
        return count;
787
}
788
 
789
/*
790
 * ipppd wanna write a packet to the card .. non-blocking
791
 */
792
 
793
int
794
isdn_ppp_write(int min, struct file *file, const char *buf, int count)
795
{
796
        isdn_net_local *lp;
797
        struct ippp_struct *is;
798
        int proto;
799
        unsigned char protobuf[4];
800
 
801
        is = file->private_data;
802
 
803
        if (!(is->state & IPPP_CONNECT))
804
                return 0;
805
 
806
        lp = is->lp;
807
 
808
        /* -> push it directly to the lowlevel interface */
809
 
810
        if (!lp)
811
                printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
812
        else {
813
                /*
814
                 * Don't reset huptimer for
815
                 * LCP packets. (Echo requests).
816
                 */
817
                if (copy_from_user(protobuf, buf, 4))
818
                        return -EFAULT;
819
                proto = PPP_PROTOCOL(protobuf);
820
                if (proto != PPP_LCP)
821
                        lp->huptimer = 0;
822
 
823
                if (lp->isdn_device < 0 || lp->isdn_channel < 0)
824
                        return 0;
825
 
826
                if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
827
                        lp->dialstate == 0 &&
828
                    (lp->flags & ISDN_NET_CONNECTED)) {
829
                        unsigned short hl;
830
                        struct sk_buff *skb;
831
                        /*
832
                         * we need to reserve enought space in front of
833
                         * sk_buff. old call to dev_alloc_skb only reserved
834
                         * 16 bytes, now we are looking what the driver want
835
                         */
836
                        hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
837
                        skb = alloc_skb(hl+count, GFP_ATOMIC);
838
                        if (!skb) {
839
                                printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
840
                                return count;
841
                        }
842
                        skb_reserve(skb, hl);
843
                        if (copy_from_user(skb_put(skb, count), buf, count))
844
                        {
845
                                kfree_skb(skb);
846
                                return -EFAULT;
847
                        }
848
                        if (is->debug & 0x40) {
849
                                printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
850
                                isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
851
                        }
852
 
853
                        isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
854
 
855
                        isdn_net_write_super(lp, skb);
856
                }
857
        }
858
        return count;
859
}
860
 
861
/*
862
 * init memory, structures etc.
863
 */
864
 
865
int
866
isdn_ppp_init(void)
867
{
868
        int i,
869
         j;
870
 
871
#ifdef CONFIG_ISDN_MPP
872
        if( isdn_ppp_mp_bundle_array_init() < 0 )
873
                return -ENOMEM;
874
#endif /* CONFIG_ISDN_MPP */
875
 
876
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
877
                if (!(ippp_table[i] = (struct ippp_struct *)
878
                      kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
879
                        printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
880
                        for (j = 0; j < i; j++)
881
                                kfree(ippp_table[j]);
882
                        return -1;
883
                }
884
                memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
885
                ippp_table[i]->state = 0;
886
                ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
887
                ippp_table[i]->last = ippp_table[i]->rq;
888
 
889
                for (j = 0; j < NUM_RCV_BUFFS; j++) {
890
                        ippp_table[i]->rq[j].buf = NULL;
891
                        ippp_table[i]->rq[j].last = ippp_table[i]->rq +
892
                            (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
893
                        ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
894
                }
895
        }
896
        return 0;
897
}
898
 
899
void
900
isdn_ppp_cleanup(void)
901
{
902
        int i;
903
 
904
        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
905
                kfree(ippp_table[i]);
906
 
907
#ifdef CONFIG_ISDN_MPP
908
        if (isdn_ppp_bundle_arr)
909
                kfree(isdn_ppp_bundle_arr);
910
#endif /* CONFIG_ISDN_MPP */
911
 
912
}
913
 
914
/*
915
 * check for address/control field and skip if allowed
916
 * retval != 0 -> discard packet silently
917
 */
918
static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb)
919
{
920
        if (skb->len < 1)
921
                return -1;
922
 
923
        if (skb->data[0] == 0xff) {
924
                if (skb->len < 2)
925
                        return -1;
926
 
927
                if (skb->data[1] != 0x03)
928
                        return -1;
929
 
930
                // skip address/control (AC) field
931
                skb_pull(skb, 2);
932
        } else {
933
                if (is->pppcfg & SC_REJ_COMP_AC)
934
                        // if AC compression was not negotiated, but used, discard packet
935
                        return -1;
936
        }
937
        return 0;
938
}
939
 
940
/*
941
 * get the PPP protocol header and pull skb
942
 * retval < 0 -> discard packet silently
943
 */
944
static int isdn_ppp_strip_proto(struct sk_buff *skb)
945
{
946
        int proto;
947
 
948
        if (skb->len < 1)
949
                return -1;
950
 
951
        if (skb->data[0] & 0x1) {
952
                // protocol field is compressed
953
                proto = skb->data[0];
954
                skb_pull(skb, 1);
955
        } else {
956
                if (skb->len < 2)
957
                        return -1;
958
                proto = ((int) skb->data[0] << 8) + skb->data[1];
959
                skb_pull(skb, 2);
960
        }
961
        return proto;
962
}
963
 
964
 
965
/*
966
 * handler for incoming packets on a syncPPP interface
967
 */
968
void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
969
{
970
        struct ippp_struct *is;
971
        int slot;
972
        int proto;
973
 
974
        if (net_dev->local->master)
975
                BUG(); // we're called with the master device always
976
 
977
        slot = lp->ppp_slot;
978
        if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
979
                printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
980
                        lp->ppp_slot);
981
                kfree_skb(skb);
982
                return;
983
        }
984
        is = ippp_table[slot];
985
 
986
        if (is->debug & 0x4) {
987
                printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
988
                       (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);
989
                isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
990
        }
991
 
992
        if (isdn_ppp_skip_ac(is, skb) < 0) {
993
                kfree_skb(skb);
994
                return;
995
        }
996
        proto = isdn_ppp_strip_proto(skb);
997
        if (proto < 0) {
998
                kfree_skb(skb);
999
                return;
1000
        }
1001
 
1002
#ifdef CONFIG_ISDN_MPP
1003
        if (is->compflags & SC_LINK_DECOMP_ON) {
1004
                skb = isdn_ppp_decompress(skb, is, NULL, &proto);
1005
                if (!skb) // decompression error
1006
                        return;
1007
        }
1008
 
1009
        if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
1010
                if (proto == PPP_MP) {
1011
                        isdn_ppp_mp_receive(net_dev, lp, skb);
1012
                        return;
1013
                }
1014
        }
1015
#endif
1016
        isdn_ppp_push_higher(net_dev, lp, skb, proto);
1017
}
1018
 
1019
/*
1020
 * we receive a reassembled frame, MPPP has been taken care of before.
1021
 * address/control and protocol have been stripped from the skb
1022
 * note: net_dev has to be master net_dev
1023
 */
1024
static void
1025
isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
1026
{
1027
        struct net_device *dev = &net_dev->dev;
1028
        struct ippp_struct *is, *mis;
1029
        isdn_net_local *mlp = NULL;
1030
        int slot;
1031
 
1032
        slot = lp->ppp_slot;
1033
        if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1034
                printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
1035
                        lp->ppp_slot);
1036
                goto drop_packet;
1037
        }
1038
        is = ippp_table[slot];
1039
 
1040
        if (lp->master) { // FIXME?
1041
                mlp = (isdn_net_local *) lp->master->priv;
1042
                slot = mlp->ppp_slot;
1043
                if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1044
                        printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
1045
                                lp->ppp_slot);
1046
                        goto drop_packet;
1047
                }
1048
        }
1049
        mis = ippp_table[slot];
1050
 
1051
        if (is->debug & 0x10) {
1052
                printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
1053
                isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
1054
        }
1055
        if (mis->compflags & SC_DECOMP_ON) {
1056
                skb = isdn_ppp_decompress(skb, is, mis, &proto);
1057
                if (!skb) // decompression error
1058
                        return;
1059
        }
1060
        switch (proto) {
1061
                case PPP_IPX:  /* untested */
1062
                        if (is->debug & 0x20)
1063
                                printk(KERN_DEBUG "isdn_ppp: IPX\n");
1064
                        skb->protocol = htons(ETH_P_IPX);
1065
                        break;
1066
                case PPP_IP:
1067
                        if (is->debug & 0x20)
1068
                                printk(KERN_DEBUG "isdn_ppp: IP\n");
1069
                        skb->protocol = htons(ETH_P_IP);
1070
                        break;
1071
                case PPP_COMP:
1072
                case PPP_COMPFRAG:
1073
                        printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
1074
                        goto drop_packet;
1075
#ifdef CONFIG_ISDN_PPP_VJ
1076
                case PPP_VJC_UNCOMP:
1077
                        if (is->debug & 0x20)
1078
                                printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
1079
                        if (net_dev->local->ppp_slot < 0) {
1080
                                printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
1081
                                        __FUNCTION__, net_dev->local->ppp_slot);
1082
                                goto drop_packet;
1083
                        }
1084
                        if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
1085
                                printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
1086
                                goto drop_packet;
1087
                        }
1088
                        skb->protocol = htons(ETH_P_IP);
1089
                        break;
1090
                case PPP_VJC_COMP:
1091
                        if (is->debug & 0x20)
1092
                                printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
1093
                        {
1094
                                struct sk_buff *skb_old = skb;
1095
                                int pkt_len;
1096
                                skb = dev_alloc_skb(skb_old->len + 128);
1097
 
1098
                                if (!skb) {
1099
                                        printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
1100
                                        skb = skb_old;
1101
                                        goto drop_packet;
1102
                                }
1103
                                skb_put(skb, skb_old->len + 128);
1104
                                memcpy(skb->data, skb_old->data, skb_old->len);
1105
                                if (net_dev->local->ppp_slot < 0) {
1106
                                        printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
1107
                                                __FUNCTION__, net_dev->local->ppp_slot);
1108
                                        goto drop_packet;
1109
                                }
1110
                                pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
1111
                                                skb->data, skb_old->len);
1112
                                kfree_skb(skb_old);
1113
                                if (pkt_len < 0)
1114
                                        goto drop_packet;
1115
 
1116
                                skb_trim(skb, pkt_len);
1117
                                skb->protocol = htons(ETH_P_IP);
1118
                        }
1119
                        break;
1120
#endif
1121
                case PPP_CCP:
1122
                case PPP_CCPFRAG:
1123
                        isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
1124
                        /* Dont pop up ResetReq/Ack stuff to the daemon any
1125
                           longer - the job is done already */
1126
                        if(skb->data[0] == CCP_RESETREQ ||
1127
                           skb->data[0] == CCP_RESETACK)
1128
                                break;
1129
                        /* fall through */
1130
                default:
1131
                        isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);     /* push data to pppd device */
1132
                        kfree_skb(skb);
1133
                        return;
1134
        }
1135
 
1136
#ifdef CONFIG_IPPP_FILTER
1137
        /* check if the packet passes the pass and active filters
1138
         * the filter instructions are constructed assuming
1139
         * a four-byte PPP header on each packet (which is still present) */
1140
        skb_push(skb, 4);
1141
        skb->data[0] = 0; /* indicate inbound */
1142
 
1143
        if (is->pass_filter.filter
1144
            && sk_run_filter(skb, is->pass_filter.filter,
1145
                            is->pass_filter.len) == 0) {
1146
                if (is->debug & 0x2)
1147
                        printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
1148
                kfree_skb(skb);
1149
                return;
1150
        }
1151
        if (!(is->active_filter.filter
1152
              && sk_run_filter(skb, is->active_filter.filter,
1153
                               is->active_filter.len) == 0)) {
1154
                if (is->debug & 0x2)
1155
                        printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
1156
                lp->huptimer = 0;
1157
                if (mlp)
1158
                        mlp->huptimer = 0;
1159
        }
1160
        skb_pull(skb, 4);
1161
#else /* CONFIG_IPPP_FILTER */
1162
        lp->huptimer = 0;
1163
        if (mlp)
1164
                mlp->huptimer = 0;
1165
#endif /* CONFIG_IPPP_FILTER */
1166
        skb->dev = dev;
1167
        skb->mac.raw = skb->data;
1168
        netif_rx(skb);
1169
        /* net_dev->local->stats.rx_packets++; done in isdn_net.c */
1170
        return;
1171
 
1172
 drop_packet:
1173
        net_dev->local->stats.rx_dropped++;
1174
        kfree_skb(skb);
1175
}
1176
 
1177
/*
1178
 * isdn_ppp_skb_push ..
1179
 * checks whether we have enough space at the beginning of the skb
1180
 * and allocs a new SKB if necessary
1181
 */
1182
static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
1183
{
1184
        struct sk_buff *skb = *skb_p;
1185
 
1186
        if(skb_headroom(skb) < len) {
1187
                struct sk_buff *nskb = skb_realloc_headroom(skb, len);
1188
 
1189
                if (!nskb) {
1190
                        printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
1191
                        dev_kfree_skb(skb);
1192
                        return NULL;
1193
                }
1194
                printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
1195
                dev_kfree_skb(skb);
1196
                *skb_p = nskb;
1197
                return skb_push(nskb, len);
1198
        }
1199
        return skb_push(skb,len);
1200
}
1201
 
1202
/*
1203
 * send ppp frame .. we expect a PIDCOMPressable proto --
1204
 *  (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
1205
 *
1206
 * VJ compression may change skb pointer!!! .. requeue with old
1207
 * skb isn't allowed!!
1208
 */
1209
 
1210
int
1211
isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
1212
{
1213
        isdn_net_local *lp,*mlp;
1214
        isdn_net_dev *nd;
1215
        unsigned int proto = PPP_IP;     /* 0x21 */
1216
        struct ippp_struct *ipt,*ipts;
1217
        int slot, retval = 0;
1218
 
1219
        mlp = (isdn_net_local *) (netdev->priv);
1220
        nd = mlp->netdev;       /* get master lp */
1221
 
1222
        slot = mlp->ppp_slot;
1223
        if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1224
                printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
1225
                        mlp->ppp_slot);
1226
                kfree_skb(skb);
1227
                goto out;
1228
        }
1229
        ipts = ippp_table[slot];
1230
 
1231
        if (!(ipts->pppcfg & SC_ENABLE_IP)) {   /* PPP connected ? */
1232
                if (ipts->debug & 0x1)
1233
                        printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
1234
                retval = 1;
1235
                goto out;
1236
        }
1237
 
1238
        switch (ntohs(skb->protocol)) {
1239
                case ETH_P_IP:
1240
                        proto = PPP_IP;
1241
                        break;
1242
                case ETH_P_IPX:
1243
                        proto = PPP_IPX;        /* untested */
1244
                        break;
1245
                default:
1246
                        printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
1247
                               skb->protocol);
1248
                        dev_kfree_skb(skb);
1249
                        goto out;
1250
        }
1251
 
1252
        lp = isdn_net_get_locked_lp(nd);
1253
        if (!lp) {
1254
                printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
1255
                retval = 1;
1256
                goto out;
1257
        }
1258
        /* we have our lp locked from now on */
1259
 
1260
        slot = lp->ppp_slot;
1261
        if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1262
                printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
1263
                        lp->ppp_slot);
1264
                kfree_skb(skb);
1265
                goto unlock;
1266
        }
1267
        ipt = ippp_table[slot];
1268
 
1269
        /*
1270
         * after this line .. requeueing in the device queue is no longer allowed!!!
1271
         */
1272
 
1273
        /* Pull off the fake header we stuck on earlier to keep
1274
         * the fragmentation code happy.
1275
         */
1276
        skb_pull(skb,IPPP_MAX_HEADER);
1277
 
1278
#ifdef CONFIG_IPPP_FILTER
1279
        /* check if we should pass this packet
1280
         * the filter instructions are constructed assuming
1281
         * a four-byte PPP header on each packet */
1282
        skb_push(skb, 4);
1283
        skb->data[0] = 1;        /* indicate outbound */
1284
        *(u_int16_t *)(skb->data + 2) = htons(proto);
1285
 
1286
        if (ipt->pass_filter.filter
1287
            && sk_run_filter(skb, ipt->pass_filter.filter,
1288
                             ipt->pass_filter.len) == 0) {
1289
                if (ipt->debug & 0x4)
1290
                        printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
1291
                kfree_skb(skb);
1292
                goto unlock;
1293
        }
1294
        if (!(ipt->active_filter.filter
1295
              && sk_run_filter(skb, ipt->active_filter.filter,
1296
                               ipt->active_filter.len) == 0)) {
1297
                if (ipt->debug & 0x4)
1298
                        printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
1299
                lp->huptimer = 0;
1300
        }
1301
        skb_pull(skb, 4);
1302
#else /* CONFIG_IPPP_FILTER */
1303
        lp->huptimer = 0;
1304
#endif /* CONFIG_IPPP_FILTER */
1305
 
1306
        if (ipt->debug & 0x4)
1307
                printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
1308
        if (ipts->debug & 0x40)
1309
                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);
1310
 
1311
#ifdef CONFIG_ISDN_PPP_VJ
1312
        if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {    /* ipts here? probably yes, but check this again */
1313
                struct sk_buff *new_skb;
1314
                unsigned short hl;
1315
                /*
1316
                 * we need to reserve enought space in front of
1317
                 * sk_buff. old call to dev_alloc_skb only reserved
1318
                 * 16 bytes, now we are looking what the driver want.
1319
                 */
1320
                hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER;
1321
                /*
1322
                 * Note: hl might still be insufficient because the method
1323
                 * above does not account for a possibible MPPP slave channel
1324
                 * which had larger HL header space requirements than the
1325
                 * master.
1326
                 */
1327
                new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
1328
                if (new_skb) {
1329
                        u_char *buf;
1330
                        int pktlen;
1331
 
1332
                        skb_reserve(new_skb, hl);
1333
                        new_skb->dev = skb->dev;
1334
                        skb_put(new_skb, skb->len);
1335
                        buf = skb->data;
1336
 
1337
                        pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
1338
                                 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
1339
 
1340
                        if (buf != skb->data) {
1341
                                if (new_skb->data != buf)
1342
                                        printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
1343
                                dev_kfree_skb(skb);
1344
                                skb = new_skb;
1345
                        } else {
1346
                                dev_kfree_skb(new_skb);
1347
                        }
1348
 
1349
                        skb_trim(skb, pktlen);
1350
                        if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) {     /* cslip? style -> PPP */
1351
                                proto = PPP_VJC_COMP;
1352
                                skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
1353
                        } else {
1354
                                if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
1355
                                        proto = PPP_VJC_UNCOMP;
1356
                                skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
1357
                        }
1358
                }
1359
        }
1360
#endif
1361
 
1362
        /*
1363
         * normal (single link) or bundle compression
1364
         */
1365
        if(ipts->compflags & SC_COMP_ON) {
1366
                /* We send compressed only if both down- und upstream
1367
                   compression is negotiated, that means, CCP is up */
1368
                if(ipts->compflags & SC_DECOMP_ON) {
1369
                        skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
1370
                } else {
1371
                        printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
1372
                }
1373
        }
1374
 
1375
        if (ipt->debug & 0x24)
1376
                printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
1377
 
1378
#ifdef CONFIG_ISDN_MPP
1379
        if (ipt->mpppcfg & SC_MP_PROT) {
1380
                /* we get mp_seqno from static isdn_net_local */
1381
                long mp_seqno = ipts->mp_seqno;
1382
                ipts->mp_seqno++;
1383
                if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
1384
                        unsigned char *data = isdn_ppp_skb_push(&skb, 3);
1385
                        if(!data)
1386
                                goto unlock;
1387
                        mp_seqno &= 0xfff;
1388
                        data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */
1389
                        data[1] = mp_seqno & 0xff;
1390
                        data[2] = proto;        /* PID compression */
1391
                } else {
1392
                        unsigned char *data = isdn_ppp_skb_push(&skb, 5);
1393
                        if(!data)
1394
                                goto unlock;
1395
                        data[0] = MP_BEGIN_FRAG | MP_END_FRAG;   /* (B)egin & (E)ndbit .. */
1396
                        data[1] = (mp_seqno >> 16) & 0xff;      /* sequence number: 24bit */
1397
                        data[2] = (mp_seqno >> 8) & 0xff;
1398
                        data[3] = (mp_seqno >> 0) & 0xff;
1399
                        data[4] = proto;        /* PID compression */
1400
                }
1401
                proto = PPP_MP; /* MP Protocol, 0x003d */
1402
        }
1403
#endif
1404
 
1405
        /*
1406
         * 'link in bundle' compression  ...
1407
         */
1408
        if(ipt->compflags & SC_LINK_COMP_ON)
1409
                skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
1410
 
1411
        if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
1412
                unsigned char *data = isdn_ppp_skb_push(&skb,1);
1413
                if(!data)
1414
                        goto unlock;
1415
                data[0] = proto & 0xff;
1416
        }
1417
        else {
1418
                unsigned char *data = isdn_ppp_skb_push(&skb,2);
1419
                if(!data)
1420
                        goto unlock;
1421
                data[0] = (proto >> 8) & 0xff;
1422
                data[1] = proto & 0xff;
1423
        }
1424
        if(!(ipt->pppcfg & SC_COMP_AC)) {
1425
                unsigned char *data = isdn_ppp_skb_push(&skb,2);
1426
                if(!data)
1427
                        goto unlock;
1428
                data[0] = 0xff;    /* All Stations */
1429
                data[1] = 0x03;    /* Unnumbered information */
1430
        }
1431
 
1432
        /* tx-stats are now updated via BSENT-callback */
1433
 
1434
        if (ipts->debug & 0x40) {
1435
                printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
1436
                isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
1437
        }
1438
 
1439
        isdn_net_writebuf_skb(lp, skb);
1440
 
1441
 unlock:
1442
        spin_unlock_bh(&lp->xmit_lock);
1443
 out:
1444
        return retval;
1445
}
1446
 
1447
#ifdef CONFIG_IPPP_FILTER
1448
/*
1449
 * check if this packet may trigger auto-dial.
1450
 */
1451
 
1452
int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
1453
{
1454
        struct ippp_struct *is = ippp_table[lp->ppp_slot];
1455
        u_int16_t proto;
1456
        int drop = 0;
1457
 
1458
        switch (ntohs(skb->protocol)) {
1459
        case ETH_P_IP:
1460
                proto = PPP_IP;
1461
                break;
1462
        case ETH_P_IPX:
1463
                proto = PPP_IPX;
1464
                break;
1465
        default:
1466
                printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
1467
                       skb->protocol);
1468
                return 1;
1469
        }
1470
 
1471
        /* the filter instructions are constructed assuming
1472
         * a four-byte PPP header on each packet. we have to
1473
         * temporarily remove part of the fake header stuck on
1474
         * earlier.
1475
         */
1476
        skb_pull(skb, IPPP_MAX_HEADER - 4);
1477
        skb->data[0] = 1;        /* indicate outbound */
1478
        *(u_int16_t *)(skb->data + 2) = htons(proto);
1479
 
1480
        drop |= is->pass_filter.filter
1481
                && sk_run_filter(skb, is->pass_filter.filter,
1482
                                 is->pass_filter.len) == 0;
1483
        drop |= is->active_filter.filter
1484
                && sk_run_filter(skb, is->active_filter.filter,
1485
                                 is->active_filter.len) == 0;
1486
 
1487
        skb_push(skb, IPPP_MAX_HEADER - 4);
1488
        return drop;
1489
}
1490
#endif
1491
#ifdef CONFIG_ISDN_MPP
1492
 
1493
/* this is _not_ rfc1990 header, but something we convert both short and long
1494
 * headers to for convinience's sake:
1495
 *      byte 0 is flags as in rfc1990
1496
 *      bytes 1...4 is 24-bit seqence number converted to host byte order
1497
 */
1498
#define MP_HEADER_LEN   5
1499
 
1500
#define MP_LONGSEQ_MASK         0x00ffffff
1501
#define MP_SHORTSEQ_MASK        0x00000fff
1502
#define MP_LONGSEQ_MAX          MP_LONGSEQ_MASK
1503
#define MP_SHORTSEQ_MAX         MP_SHORTSEQ_MASK
1504
#define MP_LONGSEQ_MAXBIT       ((MP_LONGSEQ_MASK+1)>>1)
1505
#define MP_SHORTSEQ_MAXBIT      ((MP_SHORTSEQ_MASK+1)>>1)
1506
 
1507
/* sequence-wrap safe comparisions (for long sequence)*/
1508
#define MP_LT(a,b)      ((a-b)&MP_LONGSEQ_MAXBIT)
1509
#define MP_LE(a,b)      !((b-a)&MP_LONGSEQ_MAXBIT)
1510
#define MP_GT(a,b)      ((b-a)&MP_LONGSEQ_MAXBIT)
1511
#define MP_GE(a,b)      !((a-b)&MP_LONGSEQ_MAXBIT)
1512
 
1513
#define MP_SEQ(f)       ((*(u32*)(f->data+1)))
1514
#define MP_FLAGS(f)     (f->data[0])
1515
 
1516
static int isdn_ppp_mp_bundle_array_init(void)
1517
{
1518
        int i;
1519
        int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
1520
        if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz,
1521
                                                        GFP_KERNEL)) == NULL )
1522
                return -ENOMEM;
1523
        memset(isdn_ppp_bundle_arr, 0, sz);
1524
        for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
1525
                spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
1526
        return 0;
1527
}
1528
 
1529
static ippp_bundle * isdn_ppp_mp_bundle_alloc(void)
1530
{
1531
        int i;
1532
        for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
1533
                if (isdn_ppp_bundle_arr[i].ref_ct <= 0)
1534
                        return (isdn_ppp_bundle_arr + i);
1535
        return NULL;
1536
}
1537
 
1538
static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
1539
{
1540
        struct ippp_struct * is;
1541
 
1542
        if (lp->ppp_slot < 0) {
1543
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1544
                        __FUNCTION__, lp->ppp_slot);
1545
                return(-EINVAL);
1546
        }
1547
 
1548
        is = ippp_table[lp->ppp_slot];
1549
        if (add_to) {
1550
                if( lp->netdev->pb )
1551
                        lp->netdev->pb->ref_ct--;
1552
                lp->netdev->pb = add_to;
1553
        } else {                /* first link in a bundle */
1554
                is->mp_seqno = 0;
1555
                if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
1556
                        return -ENOMEM;
1557
                lp->next = lp->last = lp;       /* nobody else in a queue */
1558
                lp->netdev->pb->frags = NULL;
1559
                lp->netdev->pb->frames = 0;
1560
                lp->netdev->pb->seq = LONG_MAX;
1561
        }
1562
        lp->netdev->pb->ref_ct++;
1563
 
1564
        is->last_link_seqno = 0;
1565
        return 0;
1566
}
1567
 
1568
static u32 isdn_ppp_mp_get_seq( int short_seq,
1569
                                        struct sk_buff * skb, u32 last_seq );
1570
static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
1571
                        struct sk_buff * from, struct sk_buff * to );
1572
static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
1573
                                struct sk_buff * from, struct sk_buff * to );
1574
static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
1575
static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
1576
 
1577
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
1578
                                                        struct sk_buff *skb)
1579
{
1580
        struct ippp_struct *is;
1581
        isdn_net_local * lpq;
1582
        ippp_bundle * mp;
1583
        isdn_mppp_stats * stats;
1584
        struct sk_buff * newfrag, * frag, * start, *nextf;
1585
        u32 newseq, minseq, thisseq;
1586
        unsigned long flags;
1587
        int slot;
1588
 
1589
        spin_lock_irqsave(&net_dev->pb->lock, flags);
1590
        mp = net_dev->pb;
1591
        stats = &mp->stats;
1592
        slot = lp->ppp_slot;
1593
        if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1594
                printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
1595
                        __FUNCTION__, lp->ppp_slot);
1596
                stats->frame_drops++;
1597
                dev_kfree_skb(skb);
1598
                spin_unlock_irqrestore(&mp->lock, flags);
1599
                return;
1600
        }
1601
        is = ippp_table[slot];
1602
        if( ++mp->frames > stats->max_queue_len )
1603
                stats->max_queue_len = mp->frames;
1604
 
1605
        if (is->debug & 0x8)
1606
                isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
1607
 
1608
        newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
1609
                                                skb, is->last_link_seqno);
1610
 
1611
 
1612
        /* if this packet seq # is less than last already processed one,
1613
         * toss it right away, but check for sequence start case first
1614
         */
1615
        if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
1616
                mp->seq = newseq;       /* the first packet: required for
1617
                                         * rfc1990 non-compliant clients --
1618
                                         * prevents constant packet toss */
1619
        } else if( MP_LT(newseq, mp->seq) ) {
1620
                stats->frame_drops++;
1621
                isdn_ppp_mp_free_skb(mp, skb);
1622
                spin_unlock_irqrestore(&mp->lock, flags);
1623
                return;
1624
        }
1625
 
1626
        /* find the minimum received sequence number over all links */
1627
        is->last_link_seqno = minseq = newseq;
1628
        for (lpq = net_dev->queue;;) {
1629
                slot = lpq->ppp_slot;
1630
                if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1631
                        printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
1632
                                __FUNCTION__, lpq->ppp_slot);
1633
                } else {
1634
                        u32 lls = ippp_table[slot]->last_link_seqno;
1635
                        if (MP_LT(lls, minseq))
1636
                                minseq = lls;
1637
                }
1638
                if ((lpq = lpq->next) == net_dev->queue)
1639
                        break;
1640
        }
1641
        if (MP_LT(minseq, mp->seq))
1642
                minseq = mp->seq;       /* can't go beyond already processed
1643
                                         * packets */
1644
        newfrag = skb;
1645
 
1646
        /* if this new fragment is before the first one, then enqueue it now. */
1647
        if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
1648
                newfrag->next = frag;
1649
                mp->frags = frag = newfrag;
1650
                newfrag = NULL;
1651
        }
1652
 
1653
        start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
1654
                                MP_SEQ(frag) == mp->seq ? frag : NULL;
1655
 
1656
        /*
1657
         * main fragment traversing loop
1658
         *
1659
         * try to accomplish several tasks:
1660
         * - insert new fragment into the proper sequence slot (once that's done
1661
         *   newfrag will be set to NULL)
1662
         * - reassemble any complete fragment sequence (non-null 'start'
1663
         *   indicates there is a continguous sequence present)
1664
         * - discard any incomplete sequences that are below minseq -- due
1665
         *   to the fact that sender always increment sequence number, if there
1666
         *   is an incomplete sequence below minseq, no new fragments would
1667
         *   come to complete such sequence and it should be discarded
1668
         *
1669
         * loop completes when we accomplished the following tasks:
1670
         * - new fragment is inserted in the proper sequence ('newfrag' is
1671
         *   set to NULL)
1672
         * - we hit a gap in the sequence, so no reassembly/processing is
1673
         *   possible ('start' would be set to NULL)
1674
         *
1675
         * algorightm for this code is derived from code in the book
1676
         * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
1677
         */
1678
        while (start != NULL || newfrag != NULL) {
1679
 
1680
                thisseq = MP_SEQ(frag);
1681
                nextf = frag->next;
1682
 
1683
                /* drop any duplicate fragments */
1684
                if (newfrag != NULL && thisseq == newseq) {
1685
                        isdn_ppp_mp_free_skb(mp, newfrag);
1686
                        newfrag = NULL;
1687
                }
1688
 
1689
                /* insert new fragment before next element if possible. */
1690
                if (newfrag != NULL && (nextf == NULL ||
1691
                                                MP_LT(newseq, MP_SEQ(nextf)))) {
1692
                        newfrag->next = nextf;
1693
                        frag->next = nextf = newfrag;
1694
                        newfrag = NULL;
1695
                }
1696
 
1697
                if (start != NULL) {
1698
                        /* check for misplaced start */
1699
                        if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
1700
                                printk(KERN_WARNING"isdn_mppp(seq %d): new "
1701
                                      "BEGIN flag with no prior END", thisseq);
1702
                                stats->seqerrs++;
1703
                                stats->frame_drops++;
1704
                                start = isdn_ppp_mp_discard(mp, start,frag);
1705
                                nextf = frag->next;
1706
                        }
1707
                } else if (MP_LE(thisseq, minseq)) {
1708
                        if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
1709
                                start = frag;
1710
                        else {
1711
                                if (MP_FLAGS(frag) & MP_END_FRAG)
1712
                                        stats->frame_drops++;
1713
                                if( mp->frags == frag )
1714
                                        mp->frags = nextf;
1715
                                isdn_ppp_mp_free_skb(mp, frag);
1716
                                frag = nextf;
1717
                                continue;
1718
                        }
1719
                }
1720
 
1721
                /* if start is non-null and we have end fragment, then
1722
                 * we have full reassembly sequence -- reassemble
1723
                 * and process packet now
1724
                 */
1725
                if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
1726
                        minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
1727
                        /* Reassemble the packet then dispatch it */
1728
                        isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
1729
 
1730
                        start = NULL;
1731
                        frag = NULL;
1732
 
1733
                        mp->frags = nextf;
1734
                }
1735
 
1736
                /* check if need to update start pointer: if we just
1737
                 * reassembled the packet and sequence is contiguous
1738
                 * then next fragment should be the start of new reassembly
1739
                 * if sequence is contiguous, but we haven't reassembled yet,
1740
                 * keep going.
1741
                 * if sequence is not contiguous, either clear everyting
1742
                 * below low watermark and set start to the next frag or
1743
                 * clear start ptr.
1744
                 */
1745
                if (nextf != NULL &&
1746
                    ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
1747
                        /* if we just reassembled and the next one is here,
1748
                         * then start another reassembly. */
1749
 
1750
                        if (frag == NULL) {
1751
                                if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
1752
                                        start = nextf;
1753
                                else
1754
                                {
1755
                                        printk(KERN_WARNING"isdn_mppp(seq %d):"
1756
                                                " END flag with no following "
1757
                                                "BEGIN", thisseq);
1758
                                        stats->seqerrs++;
1759
                                }
1760
                        }
1761
 
1762
                } else {
1763
                        if ( nextf != NULL && frag != NULL &&
1764
                                                MP_LT(thisseq, minseq)) {
1765
                                /* we've got a break in the sequence
1766
                                 * and we not at the end yet
1767
                                 * and we did not just reassembled
1768
                                 *(if we did, there wouldn't be anything before)
1769
                                 * and we below the low watermark
1770
                                 * discard all the frames below low watermark
1771
                                 * and start over */
1772
                                stats->frame_drops++;
1773
                                mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
1774
                        }
1775
                        /* break in the sequence, no reassembly */
1776
                        start = NULL;
1777
                }
1778
 
1779
                frag = nextf;
1780
        }       /* while -- main loop */
1781
 
1782
        if (mp->frags == NULL)
1783
                mp->frags = frag;
1784
 
1785
        /* rather straighforward way to deal with (not very) possible
1786
         * queue overflow */
1787
        if (mp->frames > MP_MAX_QUEUE_LEN) {
1788
                stats->overflows++;
1789
                while (mp->frames > MP_MAX_QUEUE_LEN) {
1790
                        frag = mp->frags->next;
1791
                        isdn_ppp_mp_free_skb(mp, mp->frags);
1792
                        mp->frags = frag;
1793
                }
1794
        }
1795
        spin_unlock_irqrestore(&mp->lock, flags);
1796
}
1797
 
1798
static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
1799
{
1800
        struct sk_buff * frag = lp->netdev->pb->frags;
1801
        struct sk_buff * nextfrag;
1802
        while( frag ) {
1803
                nextfrag = frag->next;
1804
                isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
1805
                frag = nextfrag;
1806
        }
1807
        lp->netdev->pb->frags = NULL;
1808
}
1809
 
1810
static u32 isdn_ppp_mp_get_seq( int short_seq,
1811
                                        struct sk_buff * skb, u32 last_seq )
1812
{
1813
        u32 seq;
1814
        int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG);
1815
 
1816
        if( !short_seq )
1817
        {
1818
                seq = ntohl(*(u32*)skb->data) & MP_LONGSEQ_MASK;
1819
                skb_push(skb,1);
1820
        }
1821
        else
1822
        {
1823
                /* convert 12-bit short seq number to 24-bit long one
1824
                */
1825
                seq = ntohs(*(u16*)skb->data) & MP_SHORTSEQ_MASK;
1826
 
1827
                /* check for seqence wrap */
1828
                if( !(seq &  MP_SHORTSEQ_MAXBIT) &&
1829
                     (last_seq &  MP_SHORTSEQ_MAXBIT) &&
1830
                     (unsigned long)last_seq <= MP_LONGSEQ_MAX )
1831
                        seq |= (last_seq + MP_SHORTSEQ_MAX+1) &
1832
                                        (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
1833
                else
1834
                        seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
1835
 
1836
                skb_push(skb, 3);       /* put converted seqence back in skb */
1837
        }
1838
        *(u32*)(skb->data+1) = seq;     /* put seqence back in _host_ byte
1839
                                         * order */
1840
        skb->data[0] = flags;            /* restore flags */
1841
        return seq;
1842
}
1843
 
1844
struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
1845
                        struct sk_buff * from, struct sk_buff * to )
1846
{
1847
        if( from )
1848
                while (from != to) {
1849
                        struct sk_buff * next = from->next;
1850
                        isdn_ppp_mp_free_skb(mp, from);
1851
                        from = next;
1852
                }
1853
        return from;
1854
}
1855
 
1856
void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
1857
                                struct sk_buff * from, struct sk_buff * to )
1858
{
1859
        ippp_bundle * mp = net_dev->pb;
1860
        int proto;
1861
        struct sk_buff * skb;
1862
        unsigned int tot_len;
1863
 
1864
        if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
1865
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1866
                        __FUNCTION__, lp->ppp_slot);
1867
                return;
1868
        }
1869
        if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
1870
                if( ippp_table[lp->ppp_slot]->debug & 0x40 )
1871
                        printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
1872
                                        "len %d\n", MP_SEQ(from), from->len );
1873
                skb = from;
1874
                skb_pull(skb, MP_HEADER_LEN);
1875
                mp->frames--;
1876
        } else {
1877
                struct sk_buff * frag;
1878
                int n;
1879
 
1880
                for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
1881
                        tot_len += frag->len - MP_HEADER_LEN;
1882
 
1883
                if( ippp_table[lp->ppp_slot]->debug & 0x40 )
1884
                        printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
1885
                                "to %d, len %d\n", MP_SEQ(from),
1886
                                (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
1887
                if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
1888
                        printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
1889
                                        "of size %d\n", tot_len);
1890
                        isdn_ppp_mp_discard(mp, from, to);
1891
                        return;
1892
                }
1893
 
1894
                while( from != to ) {
1895
                        unsigned int len = from->len - MP_HEADER_LEN;
1896
 
1897
                        memcpy(skb_put(skb,len), from->data+MP_HEADER_LEN, len);
1898
                        frag = from->next;
1899
                        isdn_ppp_mp_free_skb(mp, from);
1900
                        from = frag;
1901
                }
1902
        }
1903
        proto = isdn_ppp_strip_proto(skb);
1904
        isdn_ppp_push_higher(net_dev, lp, skb, proto);
1905
}
1906
 
1907
static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
1908
{
1909
        dev_kfree_skb(skb);
1910
        mp->frames--;
1911
}
1912
 
1913
static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb )
1914
{
1915
        printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n",
1916
                slot, (int) skb->len,
1917
                (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
1918
                (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
1919
}
1920
 
1921
static int
1922
isdn_ppp_bundle(struct ippp_struct *is, int unit)
1923
{
1924
        char ifn[IFNAMSIZ + 1];
1925
        isdn_net_dev *p;
1926
        isdn_net_local *lp, *nlp;
1927
        int rc;
1928
        unsigned long flags;
1929
 
1930
        sprintf(ifn, "ippp%d", unit);
1931
        p = isdn_net_findif(ifn);
1932
        if (!p) {
1933
                printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn);
1934
                return -EINVAL;
1935
        }
1936
 
1937
        spin_lock_irqsave(&p->pb->lock, flags);
1938
 
1939
        nlp = is->lp;
1940
        lp = p->queue;
1941
        if( nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ||
1942
                lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS ) {
1943
                printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
1944
                        nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ?
1945
                        nlp->ppp_slot : lp->ppp_slot );
1946
                rc = -EINVAL;
1947
                goto out;
1948
        }
1949
 
1950
        isdn_net_add_to_bundle(p, nlp);
1951
 
1952
        ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
1953
 
1954
        /* maybe also SC_CCP stuff */
1955
        ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
1956
                (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
1957
        ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
1958
                (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
1959
        rc = isdn_ppp_mp_init(nlp, p->pb);
1960
out:
1961
        spin_unlock_irqrestore(&p->pb->lock, flags);
1962
        return rc;
1963
}
1964
 
1965
#endif /* CONFIG_ISDN_MPP */
1966
 
1967
/*
1968
 * network device ioctl handlers
1969
 */
1970
 
1971
static int
1972
isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
1973
{
1974
        struct ppp_stats *res,
1975
         t;
1976
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
1977
        int err;
1978
 
1979
        res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
1980
        err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats));
1981
 
1982
        if (err)
1983
                return err;
1984
 
1985
        /* build a temporary stat struct and copy it to user space */
1986
 
1987
        memset(&t, 0, sizeof(struct ppp_stats));
1988
        if (dev->flags & IFF_UP) {
1989
                t.p.ppp_ipackets = lp->stats.rx_packets;
1990
                t.p.ppp_ibytes = lp->stats.rx_bytes;
1991
                t.p.ppp_ierrors = lp->stats.rx_errors;
1992
                t.p.ppp_opackets = lp->stats.tx_packets;
1993
                t.p.ppp_obytes = lp->stats.tx_bytes;
1994
                t.p.ppp_oerrors = lp->stats.tx_errors;
1995
#ifdef CONFIG_ISDN_PPP_VJ
1996
                if (slot >= 0 && ippp_table[slot]->slcomp) {
1997
                        struct slcompress *slcomp = ippp_table[slot]->slcomp;
1998
                        t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
1999
                        t.vj.vjs_compressed = slcomp->sls_o_compressed;
2000
                        t.vj.vjs_searches = slcomp->sls_o_searches;
2001
                        t.vj.vjs_misses = slcomp->sls_o_misses;
2002
                        t.vj.vjs_errorin = slcomp->sls_i_error;
2003
                        t.vj.vjs_tossed = slcomp->sls_i_tossed;
2004
                        t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
2005
                        t.vj.vjs_compressedin = slcomp->sls_i_compressed;
2006
                }
2007
#endif
2008
        }
2009
        if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT;
2010
        return 0;
2011
}
2012
 
2013
int
2014
isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2015
{
2016
        int error=0;
2017
        char *r;
2018
        int len;
2019
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
2020
 
2021
 
2022
        if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
2023
                return -EINVAL;
2024
 
2025
        switch (cmd) {
2026
                case SIOCGPPPVER:
2027
                        r = (char *) ifr->ifr_ifru.ifru_data;
2028
                        len = strlen(PPP_VERSION) + 1;
2029
                        if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
2030
                        break;
2031
                case SIOCGPPPSTATS:
2032
                        error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
2033
                        break;
2034
                default:
2035
                        error = -EINVAL;
2036
                        break;
2037
        }
2038
        return error;
2039
}
2040
 
2041
static int
2042
isdn_ppp_if_get_unit(char *name)
2043
{
2044
        int len,
2045
         i,
2046
         unit = 0,
2047
         deci;
2048
 
2049
        len = strlen(name);
2050
 
2051
        if (strncmp("ippp", name, 4) || len > 8)
2052
                return -1;
2053
 
2054
        for (i = 0, deci = 1; i < len; i++, deci *= 10) {
2055
                char a = name[len - i - 1];
2056
                if (a >= '0' && a <= '9')
2057
                        unit += (a - '0') * deci;
2058
                else
2059
                        break;
2060
        }
2061
        if (!i || len - i != 4)
2062
                unit = -1;
2063
 
2064
        return unit;
2065
}
2066
 
2067
 
2068
int
2069
isdn_ppp_dial_slave(char *name)
2070
{
2071
#ifdef CONFIG_ISDN_MPP
2072
        isdn_net_dev *ndev;
2073
        isdn_net_local *lp;
2074
        struct net_device *sdev;
2075
 
2076
        if (!(ndev = isdn_net_findif(name)))
2077
                return 1;
2078
        lp = ndev->local;
2079
        if (!(lp->flags & ISDN_NET_CONNECTED))
2080
                return 5;
2081
 
2082
        sdev = lp->slave;
2083
        while (sdev) {
2084
                isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
2085
                if (!(mlp->flags & ISDN_NET_CONNECTED))
2086
                        break;
2087
                sdev = mlp->slave;
2088
        }
2089
        if (!sdev)
2090
                return 2;
2091
 
2092
        isdn_net_dial_req((isdn_net_local *) sdev->priv);
2093
        return 0;
2094
#else
2095
        return -1;
2096
#endif
2097
}
2098
 
2099
int
2100
isdn_ppp_hangup_slave(char *name)
2101
{
2102
#ifdef CONFIG_ISDN_MPP
2103
        isdn_net_dev *ndev;
2104
        isdn_net_local *lp;
2105
        struct net_device *sdev;
2106
 
2107
        if (!(ndev = isdn_net_findif(name)))
2108
                return 1;
2109
        lp = ndev->local;
2110
        if (!(lp->flags & ISDN_NET_CONNECTED))
2111
                return 5;
2112
 
2113
        sdev = lp->slave;
2114
        while (sdev) {
2115
                isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
2116
 
2117
                if (mlp->slave) { /* find last connected link in chain */
2118
                        isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv;
2119
 
2120
                        if (!(nlp->flags & ISDN_NET_CONNECTED))
2121
                                break;
2122
                } else if (mlp->flags & ISDN_NET_CONNECTED)
2123
                        break;
2124
 
2125
                sdev = mlp->slave;
2126
        }
2127
        if (!sdev)
2128
                return 2;
2129
 
2130
        isdn_net_hangup(sdev);
2131
        return 0;
2132
#else
2133
        return -1;
2134
#endif
2135
}
2136
 
2137
/*
2138
 * PPP compression stuff
2139
 */
2140
 
2141
 
2142
/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
2143
   generate a CCP Reset-Request or tear down CCP altogether */
2144
 
2145
static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
2146
{
2147
        isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
2148
}
2149
 
2150
/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
2151
   but absolutely nontrivial. The most abstruse problem we are facing is
2152
   that the generation, reception and all the handling of timeouts and
2153
   resends including proper request id management should be entirely left
2154
   to the (de)compressor, but indeed is not covered by the current API to
2155
   the (de)compressor. The API is a prototype version from PPP where only
2156
   some (de)compressors have yet been implemented and all of them are
2157
   rather simple in their reset handling. Especially, their is only one
2158
   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
2159
   not have parameters. For this very special case it was sufficient to
2160
   just return an error code from the decompressor and have a single
2161
   reset() entry to communicate all the necessary information between
2162
   the framework and the (de)compressor. Bad enough, LZS is different
2163
   (and any other compressor may be different, too). It has multiple
2164
   histories (eventually) and needs to Reset each of them independently
2165
   and thus uses multiple outstanding Acks and history numbers as an
2166
   additional parameter to Reqs/Acks.
2167
   All that makes it harder to port the reset state engine into the
2168
   kernel because it is not just the same simple one as in (i)pppd but
2169
   it must be able to pass additional parameters and have multiple out-
2170
   standing Acks. We are trying to achieve the impossible by handling
2171
   reset transactions independent by their id. The id MUST change when
2172
   the data portion changes, thus any (de)compressor who uses more than
2173
   one resettable state must provide and recognize individual ids for
2174
   each individual reset transaction. The framework itself does _only_
2175
   differentiate them by id, because it has no other semantics like the
2176
   (de)compressor might.
2177
   This looks like a major redesign of the interface would be nice,
2178
   but I don't have an idea how to do it better. */
2179
 
2180
/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
2181
   getting that lengthy because there is no simple "send-this-frame-out"
2182
   function above but every wrapper does a bit different. Hope I guess
2183
   correct in this hack... */
2184
 
2185
static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
2186
                                    unsigned char code, unsigned char id,
2187
                                    unsigned char *data, int len)
2188
{
2189
        struct sk_buff *skb;
2190
        unsigned char *p;
2191
        int hl;
2192
        int cnt = 0;
2193
        isdn_net_local *lp = is->lp;
2194
 
2195
        /* Alloc large enough skb */
2196
        hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
2197
        skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
2198
        if(!skb) {
2199
                printk(KERN_WARNING
2200
                       "ippp: CCP cannot send reset - out of memory\n");
2201
                return;
2202
        }
2203
        skb_reserve(skb, hl);
2204
 
2205
        /* We may need to stuff an address and control field first */
2206
        if(!(is->pppcfg & SC_COMP_AC)) {
2207
                p = skb_put(skb, 2);
2208
                *p++ = 0xff;
2209
                *p++ = 0x03;
2210
        }
2211
 
2212
        /* Stuff proto, code, id and length */
2213
        p = skb_put(skb, 6);
2214
        *p++ = (proto >> 8);
2215
        *p++ = (proto & 0xff);
2216
        *p++ = code;
2217
        *p++ = id;
2218
        cnt = 4 + len;
2219
        *p++ = (cnt >> 8);
2220
        *p++ = (cnt & 0xff);
2221
 
2222
        /* Now stuff remaining bytes */
2223
        if(len) {
2224
                p = skb_put(skb, len);
2225
                memcpy(p, data, len);
2226
        }
2227
 
2228
        /* skb is now ready for xmit */
2229
        printk(KERN_DEBUG "Sending CCP Frame:\n");
2230
        isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
2231
 
2232
        isdn_net_write_super(lp, skb);
2233
}
2234
 
2235
/* Allocate the reset state vector */
2236
static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
2237
{
2238
        struct ippp_ccp_reset *r;
2239
        r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
2240
        if(!r) {
2241
                printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
2242
                       " structure - no mem\n");
2243
                return NULL;
2244
        }
2245
        memset(r, 0, sizeof(struct ippp_ccp_reset));
2246
        printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
2247
        is->reset = r;
2248
        return r;
2249
}
2250
 
2251
/* Destroy the reset state vector. Kill all pending timers first. */
2252
static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
2253
{
2254
        unsigned int id;
2255
 
2256
        printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
2257
               is->reset);
2258
        for(id = 0; id < 256; id++) {
2259
                if(is->reset->rs[id]) {
2260
                        isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
2261
                }
2262
        }
2263
        kfree(is->reset);
2264
        is->reset = NULL;
2265
}
2266
 
2267
/* Free a given state and clear everything up for later reallocation */
2268
static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
2269
                                          unsigned char id)
2270
{
2271
        struct ippp_ccp_reset_state *rs;
2272
 
2273
        if(is->reset->rs[id]) {
2274
                printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
2275
                rs = is->reset->rs[id];
2276
                /* Make sure the kernel will not call back later */
2277
                if(rs->ta)
2278
                        del_timer(&rs->timer);
2279
                is->reset->rs[id] = NULL;
2280
                kfree(rs);
2281
        } else {
2282
                printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
2283
        }
2284
}
2285
 
2286
/* The timer callback function which is called when a ResetReq has timed out,
2287
   aka has never been answered by a ResetAck */
2288
static void isdn_ppp_ccp_timer_callback(unsigned long closure)
2289
{
2290
        struct ippp_ccp_reset_state *rs =
2291
                (struct ippp_ccp_reset_state *)closure;
2292
 
2293
        if(!rs) {
2294
                printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
2295
                return;
2296
        }
2297
        if(rs->ta && rs->state == CCPResetSentReq) {
2298
                /* We are correct here */
2299
                if(!rs->expra) {
2300
                        /* Hmm, there is no Ack really expected. We can clean
2301
                           up the state now, it will be reallocated if the
2302
                           decompressor insists on another reset */
2303
                        rs->ta = 0;
2304
                        isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
2305
                        return;
2306
                }
2307
                printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
2308
                       rs->id);
2309
                /* Push it again */
2310
                isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
2311
                                        rs->data, rs->dlen);
2312
                /* Restart timer */
2313
                rs->timer.expires = jiffies + HZ*5;
2314
                add_timer(&rs->timer);
2315
        } else {
2316
                printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
2317
                       rs->state);
2318
        }
2319
}
2320
 
2321
/* Allocate a new reset transaction state */
2322
static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
2323
                                                      unsigned char id)
2324
{
2325
        struct ippp_ccp_reset_state *rs;
2326
        if(is->reset->rs[id]) {
2327
                printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
2328
                       id);
2329
                return NULL;
2330
        } else {
2331
                rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
2332
                if(!rs)
2333
                        return NULL;
2334
                memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
2335
                rs->state = CCPResetIdle;
2336
                rs->is = is;
2337
                rs->id = id;
2338
                rs->timer.data = (unsigned long)rs;
2339
                rs->timer.function = isdn_ppp_ccp_timer_callback;
2340
                is->reset->rs[id] = rs;
2341
        }
2342
        return rs;
2343
}
2344
 
2345
 
2346
/* A decompressor wants a reset with a set of parameters - do what is
2347
   necessary to fulfill it */
2348
static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
2349
                                     struct isdn_ppp_resetparams *rp)
2350
{
2351
        struct ippp_ccp_reset_state *rs;
2352
 
2353
        if(rp->valid) {
2354
                /* The decompressor defines parameters by itself */
2355
                if(rp->rsend) {
2356
                        /* And he wants us to send a request */
2357
                        if(!(rp->idval)) {
2358
                                printk(KERN_ERR "ippp_ccp: decompressor must"
2359
                                       " specify reset id\n");
2360
                                return;
2361
                        }
2362
                        if(is->reset->rs[rp->id]) {
2363
                                /* There is already a transaction in existence
2364
                                   for this id. May be still waiting for a
2365
                                   Ack or may be wrong. */
2366
                                rs = is->reset->rs[rp->id];
2367
                                if(rs->state == CCPResetSentReq && rs->ta) {
2368
                                        printk(KERN_DEBUG "ippp_ccp: reset"
2369
                                               " trans still in progress"
2370
                                               " for id %d\n", rp->id);
2371
                                } else {
2372
                                        printk(KERN_WARNING "ippp_ccp: reset"
2373
                                               " trans in wrong state %d for"
2374
                                               " id %d\n", rs->state, rp->id);
2375
                                }
2376
                        } else {
2377
                                /* Ok, this is a new transaction */
2378
                                printk(KERN_DEBUG "ippp_ccp: new trans for id"
2379
                                       " %d to be started\n", rp->id);
2380
                                rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
2381
                                if(!rs) {
2382
                                        printk(KERN_ERR "ippp_ccp: out of mem"
2383
                                               " allocing ccp trans\n");
2384
                                        return;
2385
                                }
2386
                                rs->state = CCPResetSentReq;
2387
                                rs->expra = rp->expra;
2388
                                if(rp->dtval) {
2389
                                        rs->dlen = rp->dlen;
2390
                                        memcpy(rs->data, rp->data, rp->dlen);
2391
                                }
2392
                                /* HACK TODO - add link comp here */
2393
                                isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
2394
                                                        CCP_RESETREQ, rs->id,
2395
                                                        rs->data, rs->dlen);
2396
                                /* Start the timer */
2397
                                rs->timer.expires = jiffies + 5*HZ;
2398
                                add_timer(&rs->timer);
2399
                                rs->ta = 1;
2400
                        }
2401
                } else {
2402
                        printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
2403
                }
2404
        } else {
2405
                /* The reset params are invalid. The decompressor does not
2406
                   care about them, so we just send the minimal requests
2407
                   and increase ids only when an Ack is received for a
2408
                   given id */
2409
                if(is->reset->rs[is->reset->lastid]) {
2410
                        /* There is already a transaction in existence
2411
                           for this id. May be still waiting for a
2412
                           Ack or may be wrong. */
2413
                        rs = is->reset->rs[is->reset->lastid];
2414
                        if(rs->state == CCPResetSentReq && rs->ta) {
2415
                                printk(KERN_DEBUG "ippp_ccp: reset"
2416
                                       " trans still in progress"
2417
                                       " for id %d\n", rp->id);
2418
                        } else {
2419
                                printk(KERN_WARNING "ippp_ccp: reset"
2420
                                       " trans in wrong state %d for"
2421
                                       " id %d\n", rs->state, rp->id);
2422
                        }
2423
                } else {
2424
                        printk(KERN_DEBUG "ippp_ccp: new trans for id"
2425
                               " %d to be started\n", is->reset->lastid);
2426
                        rs = isdn_ppp_ccp_reset_alloc_state(is,
2427
                                                            is->reset->lastid);
2428
                        if(!rs) {
2429
                                printk(KERN_ERR "ippp_ccp: out of mem"
2430
                                       " allocing ccp trans\n");
2431
                                return;
2432
                        }
2433
                        rs->state = CCPResetSentReq;
2434
                        /* We always expect an Ack if the decompressor doesn't
2435
                           know better */
2436
                        rs->expra = 1;
2437
                        rs->dlen = 0;
2438
                        /* HACK TODO - add link comp here */
2439
                        isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
2440
                                                rs->id, NULL, 0);
2441
                        /* Start the timer */
2442
                        rs->timer.expires = jiffies + 5*HZ;
2443
                        add_timer(&rs->timer);
2444
                        rs->ta = 1;
2445
                }
2446
        }
2447
}
2448
 
2449
/* An Ack was received for this id. This means we stop the timer and clean
2450
   up the state prior to calling the decompressors reset routine. */
2451
static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
2452
                                        unsigned char id)
2453
{
2454
        struct ippp_ccp_reset_state *rs = is->reset->rs[id];
2455
 
2456
        if(rs) {
2457
                if(rs->ta && rs->state == CCPResetSentReq) {
2458
                        /* Great, we are correct */
2459
                        if(!rs->expra)
2460
                                printk(KERN_DEBUG "ippp_ccp: ResetAck received"
2461
                                       " for id %d but not expected\n", id);
2462
                } else {
2463
                        printk(KERN_INFO "ippp_ccp: ResetAck received out of"
2464
                               "sync for id %d\n", id);
2465
                }
2466
                if(rs->ta) {
2467
                        rs->ta = 0;
2468
                        del_timer(&rs->timer);
2469
                }
2470
                isdn_ppp_ccp_reset_free_state(is, id);
2471
        } else {
2472
                printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
2473
                       " %d\n", id);
2474
        }
2475
        /* Make sure the simple reset stuff uses a new id next time */
2476
        is->reset->lastid++;
2477
}
2478
 
2479
/*
2480
 * decompress packet
2481
 *
2482
 * if master = 0, we're trying to uncompress an per-link compressed packet,
2483
 * as opposed to an compressed reconstructed-from-MPPP packet.
2484
 * proto is updated to protocol field of uncompressed packet.
2485
 *
2486
 * retval: decompressed packet,
2487
 *         same packet if uncompressed,
2488
 *         NULL if decompression error
2489
 */
2490
 
2491
static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
2492
        int *proto)
2493
{
2494
        void *stat = NULL;
2495
        struct isdn_ppp_compressor *ipc = NULL;
2496
        struct sk_buff *skb_out;
2497
        int len;
2498
        struct ippp_struct *ri;
2499
        struct isdn_ppp_resetparams rsparm;
2500
        unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
2501
 
2502
        if(!master) {
2503
                // per-link decompression 
2504
                stat = is->link_decomp_stat;
2505
                ipc = is->link_decompressor;
2506
                ri = is;
2507
        } else {
2508
                stat = master->decomp_stat;
2509
                ipc = master->decompressor;
2510
                ri = master;
2511
        }
2512
 
2513
        if (!ipc) {
2514
                // no decompressor -> we can't decompress.
2515
                printk(KERN_DEBUG "ippp: no decompressor defined!\n");
2516
                return skb;
2517
        }
2518
        if (!stat) // if we have a compressor, stat has been set as well
2519
                BUG();
2520
 
2521
        if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
2522
                // compressed packets are compressed by their protocol type
2523
 
2524
                // Set up reset params for the decompressor
2525
                memset(&rsparm, 0, sizeof(rsparm));
2526
                rsparm.data = rsdata;
2527
                rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
2528
 
2529
                skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
2530
                len = ipc->decompress(stat, skb, skb_out, &rsparm);
2531
                kfree_skb(skb);
2532
                if (len <= 0) {
2533
                        switch(len) {
2534
                        case DECOMP_ERROR:
2535
                                printk(KERN_INFO "ippp: decomp wants reset %s params\n",
2536
                                       rsparm.valid ? "with" : "without");
2537
 
2538
                                isdn_ppp_ccp_reset_trans(ri, &rsparm);
2539
                                break;
2540
                        case DECOMP_FATALERROR:
2541
                                ri->pppcfg |= SC_DC_FERROR;
2542
                                /* Kick ipppd to recognize the error */
2543
                                isdn_ppp_ccp_kickup(ri);
2544
                                break;
2545
                        }
2546
                        kfree_skb(skb_out);
2547
                        return NULL;
2548
                }
2549
                *proto = isdn_ppp_strip_proto(skb_out);
2550
                if (*proto < 0) {
2551
                        kfree_skb(skb_out);
2552
                        return NULL;
2553
                }
2554
                return skb_out;
2555
        } else {
2556
                // uncompressed packets are fed through the decompressor to
2557
                // update the decompressor state
2558
                ipc->incomp(stat, skb, *proto);
2559
                return skb;
2560
        }
2561
}
2562
 
2563
/*
2564
 * compress a frame
2565
 *   type=0: normal/bundle compression
2566
 *       =1: link compression
2567
 * returns original skb if we haven't compressed the frame
2568
 * and a new skb pointer if we've done it
2569
 */
2570
static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
2571
        struct ippp_struct *is,struct ippp_struct *master,int type)
2572
{
2573
    int ret;
2574
    int new_proto;
2575
    struct isdn_ppp_compressor *compressor;
2576
    void *stat;
2577
    struct sk_buff *skb_out;
2578
 
2579
        /* we do not compress control protocols */
2580
    if(*proto < 0 || *proto > 0x3fff) {
2581
            return skb_in;
2582
    }
2583
 
2584
        if(type) { /* type=1 => Link compression */
2585
                return skb_in;
2586
        }
2587
        else {
2588
                if(!master) {
2589
                        compressor = is->compressor;
2590
                        stat = is->comp_stat;
2591
                }
2592
                else {
2593
                        compressor = master->compressor;
2594
                        stat = master->comp_stat;
2595
                }
2596
                new_proto = PPP_COMP;
2597
        }
2598
 
2599
        if(!compressor) {
2600
                printk(KERN_ERR "isdn_ppp: No compressor set!\n");
2601
                return skb_in;
2602
        }
2603
        if(!stat) {
2604
                printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
2605
                return skb_in;
2606
        }
2607
 
2608
        /* Allow for at least 150 % expansion (for now) */
2609
        skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 +
2610
                skb_headroom(skb_in), GFP_ATOMIC);
2611
        if(!skb_out)
2612
                return skb_in;
2613
        skb_reserve(skb_out, skb_headroom(skb_in));
2614
 
2615
        ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
2616
        if(!ret) {
2617
                dev_kfree_skb(skb_out);
2618
                return skb_in;
2619
        }
2620
 
2621
        dev_kfree_skb(skb_in);
2622
        *proto = new_proto;
2623
        return skb_out;
2624
}
2625
 
2626
/*
2627
 * we received a CCP frame ..
2628
 * not a clean solution, but we MUST handle a few cases in the kernel
2629
 */
2630
static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
2631
         struct sk_buff *skb,int proto)
2632
{
2633
        struct ippp_struct *is;
2634
        struct ippp_struct *mis;
2635
        int len;
2636
        struct isdn_ppp_resetparams rsparm;
2637
        unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
2638
 
2639
        printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
2640
                lp->ppp_slot);
2641
        if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
2642
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
2643
                        __FUNCTION__, lp->ppp_slot);
2644
                return;
2645
        }
2646
        is = ippp_table[lp->ppp_slot];
2647
        isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
2648
 
2649
        if(lp->master) {
2650
                int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
2651
                if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
2652
                        printk(KERN_ERR "%s: slot(%d) out of range\n",
2653
                                __FUNCTION__, slot);
2654
                        return;
2655
                }
2656
                mis = ippp_table[slot];
2657
        } else
2658
                mis = is;
2659
 
2660
        switch(skb->data[0]) {
2661
        case CCP_CONFREQ:
2662
                if(is->debug & 0x10)
2663
                        printk(KERN_DEBUG "Disable compression here!\n");
2664
                if(proto == PPP_CCP)
2665
                        mis->compflags &= ~SC_COMP_ON;
2666
                else
2667
                        is->compflags &= ~SC_LINK_COMP_ON;
2668
                break;
2669
        case CCP_TERMREQ:
2670
        case CCP_TERMACK:
2671
                if(is->debug & 0x10)
2672
                        printk(KERN_DEBUG "Disable (de)compression here!\n");
2673
                if(proto == PPP_CCP)
2674
                        mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
2675
                else
2676
                        is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
2677
                break;
2678
        case CCP_CONFACK:
2679
                /* if we RECEIVE an ackowledge we enable the decompressor */
2680
                if(is->debug & 0x10)
2681
                        printk(KERN_DEBUG "Enable decompression here!\n");
2682
                if(proto == PPP_CCP) {
2683
                        if (!mis->decompressor)
2684
                                break;
2685
                        mis->compflags |= SC_DECOMP_ON;
2686
                } else {
2687
                        if (!is->decompressor)
2688
                                break;
2689
                        is->compflags |= SC_LINK_DECOMP_ON;
2690
                }
2691
                break;
2692
 
2693
        case CCP_RESETACK:
2694
                printk(KERN_DEBUG "Received ResetAck from peer\n");
2695
                len = (skb->data[2] << 8) | skb->data[3];
2696
                len -= 4;
2697
 
2698
                if(proto == PPP_CCP) {
2699
                        /* If a reset Ack was outstanding for this id, then
2700
                           clean up the state engine */
2701
                        isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
2702
                        if(mis->decompressor && mis->decomp_stat)
2703
                                mis->decompressor->
2704
                                        reset(mis->decomp_stat,
2705
                                              skb->data[0],
2706
                                              skb->data[1],
2707
                                              len ? &skb->data[4] : NULL,
2708
                                              len, NULL);
2709
                        /* TODO: This is not easy to decide here */
2710
                        mis->compflags &= ~SC_DECOMP_DISCARD;
2711
                }
2712
                else {
2713
                        isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
2714
                        if(is->link_decompressor && is->link_decomp_stat)
2715
                                is->link_decompressor->
2716
                                        reset(is->link_decomp_stat,
2717
                                              skb->data[0],
2718
                                              skb->data[1],
2719
                                              len ? &skb->data[4] : NULL,
2720
                                              len, NULL);
2721
                        /* TODO: neither here */
2722
                        is->compflags &= ~SC_LINK_DECOMP_DISCARD;
2723
                }
2724
                break;
2725
 
2726
        case CCP_RESETREQ:
2727
                printk(KERN_DEBUG "Received ResetReq from peer\n");
2728
                /* Receiving a ResetReq means we must reset our compressor */
2729
                /* Set up reset params for the reset entry */
2730
                memset(&rsparm, 0, sizeof(rsparm));
2731
                rsparm.data = rsdata;
2732
                rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
2733
                /* Isolate data length */
2734
                len = (skb->data[2] << 8) | skb->data[3];
2735
                len -= 4;
2736
                if(proto == PPP_CCP) {
2737
                        if(mis->compressor && mis->comp_stat)
2738
                                mis->compressor->
2739
                                        reset(mis->comp_stat,
2740
                                              skb->data[0],
2741
                                              skb->data[1],
2742
                                              len ? &skb->data[4] : NULL,
2743
                                              len, &rsparm);
2744
                }
2745
                else {
2746
                        if(is->link_compressor && is->link_comp_stat)
2747
                                is->link_compressor->
2748
                                        reset(is->link_comp_stat,
2749
                                              skb->data[0],
2750
                                              skb->data[1],
2751
                                              len ? &skb->data[4] : NULL,
2752
                                              len, &rsparm);
2753
                }
2754
                /* Ack the Req as specified by rsparm */
2755
                if(rsparm.valid) {
2756
                        /* Compressor reset handler decided how to answer */
2757
                        if(rsparm.rsend) {
2758
                                /* We should send a Frame */
2759
                                isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
2760
                                                        rsparm.idval ? rsparm.id
2761
                                                        : skb->data[1],
2762
                                                        rsparm.dtval ?
2763
                                                        rsparm.data : NULL,
2764
                                                        rsparm.dtval ?
2765
                                                        rsparm.dlen : 0);
2766
                        } else {
2767
                                printk(KERN_DEBUG "ResetAck suppressed\n");
2768
                        }
2769
                } else {
2770
                        /* We answer with a straight reflected Ack */
2771
                        isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
2772
                                                skb->data[1],
2773
                                                len ? &skb->data[4] : NULL,
2774
                                                len);
2775
                }
2776
                break;
2777
        }
2778
}
2779
 
2780
 
2781
/*
2782
 * Daemon sends a CCP frame ...
2783
 */
2784
 
2785
/* TODO: Clean this up with new Reset semantics */
2786
 
2787
/* I believe the CCP handling as-is is done wrong. Compressed frames
2788
 * should only be sent/received after CCP reaches UP state, which means
2789
 * both sides have sent CONF_ACK. Currently, we handle both directions
2790
 * independently, which means we may accept compressed frames too early
2791
 * (supposedly not a problem), but may also mean we send compressed frames
2792
 * too early, which may turn out to be a problem.
2793
 * This part of state machine should actually be handled by (i)pppd, but
2794
 * that's too big of a change now. --kai
2795
 */
2796
 
2797
/* Actually, we might turn this into an advantage: deal with the RFC in
2798
 * the old tradition of beeing generous on what we accept, but beeing
2799
 * strict on what we send. Thus we should just
2800
 * - accept compressed frames as soon as decompression is negotiated
2801
 * - send compressed frames only when decomp *and* comp are negotiated
2802
 * - drop rx compressed frames if we cannot decomp (instead of pushing them
2803
 *   up to ipppd)
2804
 * and I tried to modify this file according to that. --abp
2805
 */
2806
 
2807
static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
2808
{
2809
        struct ippp_struct *mis,*is;
2810
        int proto, slot = lp->ppp_slot;
2811
        unsigned char *data;
2812
 
2813
        if(!skb || skb->len < 3)
2814
                return;
2815
        if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
2816
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
2817
                        __FUNCTION__, slot);
2818
                return;
2819
        }
2820
        is = ippp_table[slot];
2821
        /* Daemon may send with or without address and control field comp */
2822
        data = skb->data;
2823
        if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
2824
                data += 2;
2825
                if(skb->len < 5)
2826
                        return;
2827
        }
2828
 
2829
        proto = ((int)data[0]<<8)+data[1];
2830
        if(proto != PPP_CCP && proto != PPP_CCPFRAG)
2831
                return;
2832
 
2833
        printk(KERN_DEBUG "Received CCP frame from daemon:\n");
2834
        isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
2835
 
2836
        if (lp->master) {
2837
                slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
2838
                if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
2839
                        printk(KERN_ERR "%s: slot(%d) out of range\n",
2840
                                __FUNCTION__, slot);
2841
                        return;
2842
                }
2843
                mis = ippp_table[slot];
2844
        } else
2845
                mis = is;
2846
        if (mis != is)
2847
                printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
2848
 
2849
        switch(data[2]) {
2850
        case CCP_CONFREQ:
2851
                if(is->debug & 0x10)
2852
                        printk(KERN_DEBUG "Disable decompression here!\n");
2853
                if(proto == PPP_CCP)
2854
                        is->compflags &= ~SC_DECOMP_ON;
2855
                else
2856
                        is->compflags &= ~SC_LINK_DECOMP_ON;
2857
                break;
2858
        case CCP_TERMREQ:
2859
        case CCP_TERMACK:
2860
                if(is->debug & 0x10)
2861
                        printk(KERN_DEBUG "Disable (de)compression here!\n");
2862
                if(proto == PPP_CCP)
2863
                        is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
2864
                else
2865
                        is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
2866
                break;
2867
        case CCP_CONFACK:
2868
                /* if we SEND an ackowledge we can/must enable the compressor */
2869
                if(is->debug & 0x10)
2870
                        printk(KERN_DEBUG "Enable compression here!\n");
2871
                if(proto == PPP_CCP) {
2872
                        if (!is->compressor)
2873
                                break;
2874
                        is->compflags |= SC_COMP_ON;
2875
                } else {
2876
                        if (!is->compressor)
2877
                                break;
2878
                        is->compflags |= SC_LINK_COMP_ON;
2879
                }
2880
                break;
2881
        case CCP_RESETACK:
2882
                /* If we send a ACK we should reset our compressor */
2883
                if(is->debug & 0x10)
2884
                        printk(KERN_DEBUG "Reset decompression state here!\n");
2885
                printk(KERN_DEBUG "ResetAck from daemon passed by\n");
2886
                if(proto == PPP_CCP) {
2887
                        /* link to master? */
2888
                        if(is->compressor && is->comp_stat)
2889
                                is->compressor->reset(is->comp_stat, 0, 0,
2890
                                                      NULL, 0, NULL);
2891
                        is->compflags &= ~SC_COMP_DISCARD;
2892
                }
2893
                else {
2894
                        if(is->link_compressor && is->link_comp_stat)
2895
                                is->link_compressor->reset(is->link_comp_stat,
2896
                                                           0, 0, NULL, 0, NULL);
2897
                        is->compflags &= ~SC_LINK_COMP_DISCARD;
2898
                }
2899
                break;
2900
        case CCP_RESETREQ:
2901
                /* Just let it pass by */
2902
                printk(KERN_DEBUG "ResetReq from daemon passed by\n");
2903
                break;
2904
        }
2905
}
2906
 
2907
int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
2908
{
2909
        ipc->next = ipc_head;
2910
        ipc->prev = NULL;
2911
        if(ipc_head) {
2912
                ipc_head->prev = ipc;
2913
        }
2914
        ipc_head = ipc;
2915
        return 0;
2916
}
2917
 
2918
int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
2919
{
2920
        if(ipc->prev)
2921
                ipc->prev->next = ipc->next;
2922
        else
2923
                ipc_head = ipc->next;
2924
        if(ipc->next)
2925
                ipc->next->prev = ipc->prev;
2926
        ipc->prev = ipc->next = NULL;
2927
        return 0;
2928
}
2929
 
2930
static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
2931
{
2932
        struct isdn_ppp_compressor *ipc = ipc_head;
2933
        int ret;
2934
        void *stat;
2935
        int num = data->num;
2936
 
2937
        if(is->debug & 0x10)
2938
                printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
2939
                        (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
2940
 
2941
        /* If is has no valid reset state vector, we cannot allocate a
2942
           decompressor. The decompressor would cause reset transactions
2943
           sooner or later, and they need that vector. */
2944
 
2945
        if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
2946
                printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
2947
                       " allow decompression.\n");
2948
                return -ENOMEM;
2949
        }
2950
 
2951
        while(ipc) {
2952
                if(ipc->num == num) {
2953
                        stat = ipc->alloc(data);
2954
                        if(stat) {
2955
                                ret = ipc->init(stat,data,is->unit,0);
2956
                                if(!ret) {
2957
                                        printk(KERN_ERR "Can't init (de)compression!\n");
2958
                                        ipc->free(stat);
2959
                                        stat = NULL;
2960
                                        break;
2961
                                }
2962
                        }
2963
                        else {
2964
                                printk(KERN_ERR "Can't alloc (de)compression!\n");
2965
                                break;
2966
                        }
2967
 
2968
                        if(data->flags & IPPP_COMP_FLAG_XMIT) {
2969
                                if(data->flags & IPPP_COMP_FLAG_LINK) {
2970
                                        if(is->link_comp_stat)
2971
                                                is->link_compressor->free(is->link_comp_stat);
2972
                                        is->link_comp_stat = stat;
2973
                                        is->link_compressor = ipc;
2974
                                }
2975
                                else {
2976
                                        if(is->comp_stat)
2977
                                                is->compressor->free(is->comp_stat);
2978
                                        is->comp_stat = stat;
2979
                                        is->compressor = ipc;
2980
                                }
2981
                        }
2982
                        else {
2983
                                if(data->flags & IPPP_COMP_FLAG_LINK) {
2984
                                        if(is->link_decomp_stat)
2985
                                                is->link_decompressor->free(is->link_decomp_stat);
2986
                                        is->link_decomp_stat = stat;
2987
                                        is->link_decompressor = ipc;
2988
                                }
2989
                                else {
2990
                                        if(is->decomp_stat)
2991
                                                is->decompressor->free(is->decomp_stat);
2992
                                        is->decomp_stat = stat;
2993
                                        is->decompressor = ipc;
2994
                                }
2995
                        }
2996
                        return 0;
2997
                }
2998
                ipc = ipc->next;
2999
        }
3000
        return -EINVAL;
3001
}

powered by: WebSVN 2.1.0

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