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