This source file includes following definitions.
- isdn_ppp_free
- isdn_ppp_bind
- isdn_ppp_hangup
- isdn_ppp_open
- isdn_ppp_release
- get_arg
- set_arg
- isdn_ppp_ioctl
- isdn_ppp_select
- isdn_ppp_fill_rq
- isdn_ppp_read
- isdn_ppp_write
- isdn_ppp_init
- isdn_ppp_cleanup
- isdn_ppp_receive
- isdn_ppp_push_higher
- isdn_ppp_xmit
- isdn_ppp_free_mpqueue
- isdn_ppp_bundle
- isdn_ppp_mask_queue
- isdn_ppp_fill_mpqueue
- isdn_ppp_cleanup_queue
- isdn_ppp_timer_timeout
- isdn_ppp_dev_ioctl
- isdn_ppp_if_get_unit
- isdn_ppp_dial_slave
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 #ifndef STANDALONE
43 #include <linux/config.h>
44 #endif
45 #define __NO_VERSION__
46 #include <linux/module.h>
47 #include <linux/isdn.h>
48 #include "isdn_common.h"
49 #include "isdn_ppp.h"
50 #include "isdn_net.h"
51
52 #ifndef PPP_IPX
53 #define PPP_IPX 0x002b
54 #endif
55
56
57 static int isdn_ppp_fill_rq(char *buf, int len, int minor);
58 static int isdn_ppp_hangup(int);
59 static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
60 struct sk_buff *skb, int proto);
61 static int isdn_ppp_if_get_unit(char **namebuf);
62
63 #ifdef CONFIG_ISDN_MPP
64 static int isdn_ppp_bundle(int, int);
65 static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
66 static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min);
67 static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
68 int BEbyte, int *sqno, int min_sqno);
69 #endif
70
71 char *isdn_ppp_revision = "$Revision: 1.4 $";
72 struct ippp_struct *ippp_table = (struct ippp_struct *) 0;
73
74 extern int isdn_net_force_dial_lp(isdn_net_local *);
75
76 int isdn_ppp_free(isdn_net_local * lp)
77 {
78 if (lp->ppp_minor < 0)
79 return 0;
80
81 #ifdef CONFIG_ISDN_MPP
82 if(lp->master)
83 {
84 isdn_net_dev *p = dev->netdev;
85 lp->last->next = lp->next;
86 lp->next->last = lp->last;
87 if(lp->netdev->queue == lp)
88 lp->netdev->queue = lp->next;
89 lp->next = lp->last = lp;
90 while(p) {
91 if(lp == &p->local) {
92 lp->netdev = p;
93 break;
94 }
95 p=p->next;
96 }
97 } else {
98 lp->netdev->ib.bundled = 0;
99
100 }
101
102 #endif
103
104 isdn_ppp_hangup(lp->ppp_minor);
105 #if 0
106 printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_minor, (long) lp,(long) ippp_table[lp->ppp_minor].lp);
107 #endif
108 ippp_table[lp->ppp_minor].lp = NULL;
109 return 0;
110 }
111
112 int isdn_ppp_bind(isdn_net_local * lp)
113 {
114 int i;
115 int unit = 0;
116 char *name;
117 long flags;
118
119 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
120 return 0;
121
122 save_flags(flags);
123 cli();
124
125
126
127
128 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
129 if (ippp_table[i].state == IPPP_OPEN) {
130 #if 0
131 printk(KERN_DEBUG "find_minor, %d lp: %08lx\n", i, (long) lp);
132 #endif
133 break;
134 }
135 }
136
137 if (i >= ISDN_MAX_CHANNELS) {
138 restore_flags(flags);
139 printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
140 return -1;
141 }
142 lp->ppp_minor = i;
143 ippp_table[lp->ppp_minor].lp = lp;
144
145 name = lp->name;
146 unit = isdn_ppp_if_get_unit(&name);
147 ippp_table[lp->ppp_minor].unit = unit;
148
149 ippp_table[lp->ppp_minor].state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
150
151 restore_flags(flags);
152
153
154
155
156 if (ippp_table[lp->ppp_minor].wq)
157 wake_up_interruptible(&ippp_table[lp->ppp_minor].wq);
158
159 return lp->ppp_minor;
160 }
161
162 static int isdn_ppp_hangup(int minor)
163 {
164 if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
165 return 0;
166
167 if (ippp_table[minor].state && ippp_table[minor].wq)
168 wake_up_interruptible(&ippp_table[minor].wq);
169
170 ippp_table[minor].state = IPPP_CLOSEWAIT;
171 return 1;
172 }
173
174
175
176
177
178 int isdn_ppp_open(int minor, struct file *file)
179 {
180 #if 0
181 printk(KERN_DEBUG "ippp, open, minor: %d state: %04x\n", minor,ippp_table[minor].state);
182 #endif
183 if (ippp_table[minor].state)
184 return -EBUSY;
185
186 ippp_table[minor].lp = 0;
187 ippp_table[minor].mp_seqno = 0;
188 ippp_table[minor].pppcfg = 0;
189 ippp_table[minor].mpppcfg = 0;
190 ippp_table[minor].range = 0x1000000;
191 ippp_table[minor].last_link_seqno = -1;
192 ippp_table[minor].unit = -1;
193 ippp_table[minor].mru = 1524;
194 ippp_table[minor].maxcid = 16;
195 ippp_table[minor].tk = current;
196 ippp_table[minor].wq = NULL;
197 ippp_table[minor].wq1 = NULL;
198 ippp_table[minor].first = ippp_table[minor].rq + NUM_RCV_BUFFS - 1;
199 ippp_table[minor].last = ippp_table[minor].rq;
200 #ifdef CONFIG_ISDN_PPP_VJ
201
202
203
204 ippp_table[minor].cbuf = kmalloc(ippp_table[minor].mru + PPP_HARD_HDR_LEN + 2, GFP_KERNEL);
205
206 if (ippp_table[minor].cbuf == NULL) {
207 printk(KERN_DEBUG "ippp: Can't allocate memory buffer for VJ compression.\n");
208 return -ENOMEM;
209 }
210 ippp_table[minor].slcomp = slhc_init(16, 16);
211 #endif
212
213 ippp_table[minor].state = IPPP_OPEN;
214
215 return 0;
216 }
217
218 void isdn_ppp_release(int minor, struct file *file)
219 {
220 int i;
221
222 if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
223 return;
224
225 #if 0
226 printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) ippp_table[minor].lp);
227 #endif
228
229 if (ippp_table[minor].lp) {
230 isdn_net_dev *p = dev->netdev;
231 while(p) {
232 if(&p->local == ippp_table[minor].lp)
233 break;
234 p = p->next;
235 }
236 if(!p) {
237 printk(KERN_ERR "isdn_ppp_release: Can't find device for net_local\n");
238 p = ippp_table[minor].lp->netdev;
239 }
240 ippp_table[minor].lp->ppp_minor = -1;
241 isdn_net_hangup(&p->dev);
242 ippp_table[minor].lp = NULL;
243 }
244 for (i = 0; i < NUM_RCV_BUFFS; i++) {
245 if (ippp_table[minor].rq[i].buf)
246 kfree(ippp_table[minor].rq[i].buf);
247 }
248
249 #ifdef CONFIG_ISDN_PPP_VJ
250 slhc_free(ippp_table[minor].slcomp);
251 kfree(ippp_table[minor].cbuf);
252 #endif
253
254 ippp_table[minor].state = 0;
255 }
256
257 static int get_arg(void *b, unsigned long *val)
258 {
259 int r;
260 if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long))))
261 return r;
262 memcpy_fromfs((void *) val, b, sizeof(unsigned long));
263 return 0;
264 }
265
266 static int set_arg(void *b, unsigned long val)
267 {
268 int r;
269 if ((r = verify_area(VERIFY_WRITE, b, sizeof(unsigned long))))
270 return r;
271 memcpy_tofs(b, (void *) &val, sizeof(unsigned long));
272 return 0;
273 }
274
275 int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long arg)
276 {
277 unsigned long val;
278 int r;
279
280 #if 0
281 printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x",minor,cmd);
282 printk(KERN_DEBUG " state: %x\n",ippp_table[minor].state);
283 #endif
284
285 if (!(ippp_table[minor].state & IPPP_OPEN))
286 return -EINVAL;
287
288 switch (cmd) {
289 #if 0
290 case PPPIOCSINPSIG:
291
292 break;
293 #endif
294 case PPPIOCBUNDLE:
295 #ifdef CONFIG_ISDN_MPP
296 if ((r = get_arg((void *) arg, &val)))
297 return r;
298 printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
299 (int) minor, (int) ippp_table[minor].unit, (int) val);
300 return isdn_ppp_bundle(minor, val);
301 #else
302 return -1;
303 #endif
304 break;
305 case PPPIOCGUNIT:
306 if ((r = set_arg((void *) arg, ippp_table[minor].unit)))
307 return r;
308 break;
309 case PPPIOCGMPFLAGS:
310 if ((r = set_arg((void *) arg, ippp_table[minor].mpppcfg)))
311 return r;
312 break;
313 case PPPIOCSMPFLAGS:
314 if ((r = get_arg((void *) arg, &val)))
315 return r;
316 ippp_table[minor].mpppcfg = val;
317 break;
318 case PPPIOCGFLAGS:
319 if ((r = set_arg((void *) arg, ippp_table[minor].pppcfg)))
320 return r;
321 break;
322 case PPPIOCSFLAGS:
323 if ((r = get_arg((void *) arg, &val))) {
324 return r;
325 }
326 if (val & SC_ENABLE_IP && !(ippp_table[minor].pppcfg & SC_ENABLE_IP)) {
327 ippp_table[minor].lp->netdev->dev.tbusy = 0;
328 mark_bh(NET_BH);
329 }
330 ippp_table[minor].pppcfg = val;
331 break;
332 #if 0
333 case PPPIOCGSTAT:
334 break;
335 case PPPIOCGTIME:
336 break;
337 #endif
338 case PPPIOCSMRU:
339 if ((r = get_arg((void *) arg, &val)))
340 return r;
341 ippp_table[minor].mru = val;
342 break;
343 case PPPIOCSMPMRU:
344 break;
345 case PPPIOCSMPMTU:
346 break;
347 case PPPIOCSMAXCID:
348 if ((r = get_arg((void *) arg, &val)))
349 return r;
350 ippp_table[minor].maxcid = val;
351 break;
352 case PPPIOCGDEBUG:
353 break;
354 case PPPIOCSDEBUG:
355 break;
356 default:
357 break;
358 }
359 return 0;
360 }
361
362 int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
363 {
364 struct ippp_buf_queue *bf, *bl;
365 unsigned long flags;
366
367 #if 0
368 printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",minor,type);
369 #endif
370
371 if (!(ippp_table[minor].state & IPPP_OPEN))
372 return -EINVAL;
373
374 switch (type) {
375 case SEL_IN:
376 save_flags(flags);
377 cli();
378 bl = ippp_table[minor].last;
379 bf = ippp_table[minor].first;
380 if (bf->next == bl && !(ippp_table[minor].state & IPPP_NOBLOCK)) {
381 select_wait(&ippp_table[minor].wq, st);
382 restore_flags(flags);
383 return 0;
384 }
385 ippp_table[minor].state &= ~IPPP_NOBLOCK;
386 restore_flags(flags);
387 return 1;
388 case SEL_OUT:
389
390 return 1;
391 case SEL_EX:
392 select_wait(&ippp_table[minor].wq1, st);
393 return 0;
394 }
395 return 1;
396 }
397
398
399
400
401
402 static int isdn_ppp_fill_rq(char *buf, int len, int minor)
403 {
404 struct ippp_buf_queue *bf, *bl;
405 unsigned long flags;
406
407 if (minor < 0 || minor >= ISDN_MAX_CHANNELS) {
408 printk(KERN_WARNING "ippp: illegal minor.\n");
409 return 0;
410 }
411 if (!(ippp_table[minor].state & IPPP_CONNECT)) {
412 printk(KERN_DEBUG "ippp: device not activated.\n");
413 return 0;
414 }
415 save_flags(flags);
416 cli();
417
418 bf = ippp_table[minor].first;
419 bl = ippp_table[minor].last;
420
421 if (bf == bl) {
422 printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
423 bf = bf->next;
424 kfree(bf->buf);
425 ippp_table[minor].first = bf;
426 }
427 bl->buf = (char *) kmalloc(len, GFP_ATOMIC);
428 if (!bl->buf) {
429 printk(KERN_WARNING "ippp: Can't alloc buf\n");
430 restore_flags(flags);
431 return 0;
432 }
433 bl->len = len;
434
435 memcpy(bl->buf, buf, len);
436
437 ippp_table[minor].last = bl->next;
438 restore_flags(flags);
439
440 if (ippp_table[minor].wq)
441 wake_up_interruptible(&ippp_table[minor].wq);
442
443 return len;
444 }
445
446
447
448
449
450
451 int isdn_ppp_read(int minor, struct file *file, char *buf, int count)
452 {
453 struct ippp_struct *c = &ippp_table[minor];
454 struct ippp_buf_queue *b;
455 int r;
456 unsigned long flags;
457
458 if (!(ippp_table[minor].state & IPPP_OPEN))
459 return 0;
460
461 if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
462 return r;
463
464 save_flags(flags);
465 cli();
466
467 b = c->first->next;
468 if (!b->buf) {
469 restore_flags(flags);
470 return -EAGAIN;
471 }
472 if (b->len < count)
473 count = b->len;
474 memcpy_tofs(buf, b->buf, count);
475 kfree(b->buf);
476 b->buf = NULL;
477 c->first = b;
478 restore_flags(flags);
479
480 return count;
481 }
482
483
484
485
486
487 int isdn_ppp_write(int minor, struct file *file, const char *buf, int count)
488 {
489 isdn_net_local *lp;
490
491 if (!(ippp_table[minor].state & IPPP_CONNECT))
492 return 0;
493
494 lp = ippp_table[minor].lp;
495
496
497
498 if (!lp)
499 printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
500 else {
501 if (lp->isdn_device < 0 || lp->isdn_channel < 0)
502 return 0;
503
504 if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
505 (lp->flags & ISDN_NET_CONNECTED))
506 dev->drv[lp->isdn_device]->interface->writebuf(
507 lp->isdn_device,lp->isdn_channel, buf, count, 1);
508 }
509
510 return count;
511 }
512
513
514
515
516
517 int isdn_ppp_init(void)
518 {
519 int i, j;
520
521 if (!(ippp_table = (struct ippp_struct *)
522 kmalloc(sizeof(struct ippp_struct) * ISDN_MAX_CHANNELS, GFP_KERNEL))) {
523 printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
524 return -1;
525 }
526 memset((char *) ippp_table, 0, sizeof(struct ippp_struct) * ISDN_MAX_CHANNELS);
527 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
528 ippp_table[i].state = 0;
529 ippp_table[i].first = ippp_table[i].rq + NUM_RCV_BUFFS - 1;
530 ippp_table[i].last = ippp_table[i].rq;
531
532 for (j = 0; j < NUM_RCV_BUFFS; j++) {
533 ippp_table[i].rq[j].buf = NULL;
534 ippp_table[i].rq[j].last = ippp_table[i].rq +
535 (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
536 ippp_table[i].rq[j].next = ippp_table[i].rq + (j + 1) % NUM_RCV_BUFFS;
537 }
538 }
539 return 0;
540 }
541
542 void isdn_ppp_cleanup(void)
543 {
544 kfree(ippp_table);
545 }
546
547
548
549
550
551 void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
552 {
553 #if 0
554 printk(KERN_DEBUG "recv, skb %d\n",skb->len);
555 #endif
556
557 if(skb->data[0] == 0xff && skb->data[1] == 0x03)
558 skb_pull(skb,2);
559 else if (ippp_table[lp->ppp_minor].pppcfg & SC_REJ_COMP_AC)
560 return;
561
562 #ifdef CONFIG_ISDN_MPP
563 if (!(ippp_table[lp->ppp_minor].mpppcfg & SC_REJ_MP_PROT)) {
564 int proto;
565 int sqno_end;
566 if (skb->data[0] & 0x1) {
567 proto = skb->data[0];
568 skb_pull(skb,1);
569 } else {
570 proto = ((int) skb->data[0] << 8) + skb->data[1];
571 skb_pull(skb,2);
572 }
573 if (proto == PPP_MP) {
574 isdn_net_local *lpq;
575 int sqno, min_sqno, tseq;
576 u_char BEbyte = skb->data[0];
577 #if 0
578 printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_minor, proto ,
579 (int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
580 (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
581 #endif
582 if (!(ippp_table[lp->ppp_minor].mpppcfg & SC_IN_SHORT_SEQ)) {
583 sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3];
584 skb_pull(skb,4);
585 } else {
586 sqno = (((int) skb->data[0] & 0xf) << 8) + (int) skb->data[1];
587 skb_pull(skb,2);
588 }
589
590 if ((tseq = ippp_table[lp->ppp_minor].last_link_seqno) >= sqno) {
591 int range = ippp_table[lp->ppp_minor].range;
592 if (tseq + 1024 < range + sqno)
593 printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %d, last: %d !!!\n", sqno, tseq);
594 else {
595 sqno += range;
596 ippp_table[lp->ppp_minor].last_link_seqno = sqno;
597 }
598 } else
599 ippp_table[lp->ppp_minor].last_link_seqno = sqno;
600
601 for (min_sqno = 0, lpq = net_dev->queue;;) {
602 if (ippp_table[lpq->ppp_minor].last_link_seqno > min_sqno)
603 min_sqno = ippp_table[lpq->ppp_minor].last_link_seqno;
604 lpq = lpq->next;
605 if (lpq == net_dev->queue)
606 break;
607 }
608 if (min_sqno >= ippp_table[lpq->ppp_minor].range) {
609 int mask = ippp_table[lpq->ppp_minor].range - 1;
610 isdn_ppp_cleanup_queue(net_dev, min_sqno);
611 isdn_ppp_mask_queue(net_dev, mask);
612 net_dev->ib.next_num &= mask;
613 {
614 struct sqqueue *q = net_dev->ib.sq;
615 while (q) {
616 q->sqno_start &= mask;
617 q->sqno_end &= mask;
618 }
619 }
620 min_sqno &= mask;
621 for (lpq = net_dev->queue;;) {
622 ippp_table[lpq->ppp_minor].last_link_seqno &= mask;
623 lpq = lpq->next;
624 if (lpq == net_dev->queue)
625 break;
626 }
627 }
628 if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
629 printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_minor);
630 if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0)
631 return;
632 } else
633 sqno_end = sqno;
634
635
636
637
638
639
640
641
642 net_dev->ib.modify = 1;
643 if (net_dev->ib.bundled && net_dev->ib.next_num != sqno) {
644
645
646
647 struct sqqueue *q;
648
649 q = (struct sqqueue *) kmalloc(sizeof(struct sqqueue), GFP_ATOMIC);
650 if (!q) {
651 printk(KERN_WARNING "ippp: err, no memory !!\n");
652 net_dev->ib.modify = 0;
653 return;
654 }
655 q->skb = skb;
656 q->sqno_end = sqno_end;
657 q->sqno_start = sqno;
658 q->timer = jiffies + (ISDN_TIMER_1SEC) * 5;
659
660 if (!net_dev->ib.sq) {
661 net_dev->ib.sq = q;
662 q->next = NULL;
663 } else {
664 struct sqqueue *ql = net_dev->ib.sq;
665 if (ql->sqno_start > q->sqno_start) {
666 q->next = ql;
667 net_dev->ib.sq = q;
668 } else {
669 while (ql->next && ql->next->sqno_start < q->sqno_start)
670 ql = ql->next;
671 q->next = ql->next;
672 ql->next = q;
673 }
674 }
675 net_dev->ib.modify = 0;
676 return;
677 } else {
678
679
680
681 struct sqqueue *q;
682
683 net_dev->ib.next_num = sqno_end + 1;
684 isdn_ppp_push_higher(net_dev, lp, skb, -1);
685
686
687
688
689 while ((q = net_dev->ib.sq) && q->sqno_start == net_dev->ib.next_num) {
690 isdn_ppp_push_higher(net_dev, lp, q->skb, -1);
691 net_dev->ib.sq = q->next;
692 net_dev->ib.next_num = q->sqno_end + 1;
693 kfree(q);
694 }
695 }
696 net_dev->ib.modify = 0;
697
698 } else
699 isdn_ppp_push_higher(net_dev, lp, skb , proto);
700 } else
701 #endif
702 isdn_ppp_push_higher(net_dev, lp, skb , -1);
703 }
704
705
706 static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb,int proto)
707 {
708 struct device *dev = &net_dev->dev;
709
710 if (proto < 0) {
711 if (skb->data[0] & 0x01) {
712 proto = (unsigned char) skb->data[0];
713 skb_pull(skb,1);
714 } else {
715 proto = ((int) (unsigned char) skb->data[0] << 8) + (unsigned char) skb->data[1];
716 skb_pull(skb,2);
717 }
718 }
719
720 #if 0
721 printk(KERN_DEBUG "push, skb %d %04x\n",skb->len,proto);
722 #endif
723
724 switch (proto) {
725 case PPP_IPX:
726 skb->dev = dev;
727 skb->mac.raw = skb->data;
728 skb->protocol = htons(ETH_P_IPX);
729 break;
730 #ifdef CONFIG_ISDN_PPP_VJ
731 case PPP_VJC_UNCOMP:
732 slhc_remember(ippp_table[net_dev->local.ppp_minor].slcomp, skb->data, skb->len);
733 #endif
734 case PPP_IP:
735 skb->dev = dev;
736 skb->mac.raw = skb->data;
737 skb->protocol = htons(ETH_P_IP);
738 break;
739 case PPP_VJC_COMP:
740 #ifdef CONFIG_ISDN_PPP_VJ
741 {
742 struct sk_buff *skb_old = skb;
743 int pkt_len;
744 skb = dev_alloc_skb(skb_old->len + 40);
745
746 if (!skb) {
747 printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
748 net_dev->local.stats.rx_dropped++;
749 return;
750 }
751 skb->dev = dev;
752 skb_put(skb,skb_old->len + 40);
753 memcpy(skb->data, skb_old->data, skb_old->len);
754 skb->mac.raw = skb->data;
755 pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_minor].slcomp,
756 skb->data, skb_old->len);
757 skb_trim(skb, pkt_len);
758 dev_kfree_skb(skb_old,FREE_WRITE);
759 skb->protocol = htons(ETH_P_IP);
760 }
761 #else
762 printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n");
763 lp->stats.rx_dropped++;
764 return;
765 #endif
766 break;
767 default:
768 skb_push(skb,4);
769 skb->data[0] = 0xff;
770 skb->data[1] = 0x03;
771 skb->data[2] = (proto>>8);
772 skb->data[3] = proto & 0xff;
773 isdn_ppp_fill_rq(skb->data, skb->len, lp->ppp_minor);
774 dev_kfree_skb(skb,FREE_WRITE);
775 return;
776 }
777
778 netif_rx(skb);
779 net_dev->local.stats.rx_packets++;
780
781 lp->huptimer = 0;
782
783 return;
784 }
785
786
787
788
789
790 int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
791 {
792 isdn_net_dev *nd = ((isdn_net_local *) dev->priv)->netdev;
793 isdn_net_local *lp = nd->queue;
794 int proto = PPP_IP;
795 struct ippp_struct *ipt = ippp_table + lp->ppp_minor;
796 struct ippp_struct *ipts = ippp_table + lp->netdev->local.ppp_minor;
797
798
799
800
801
802 if (*((unsigned long *)skb->data) != 0)
803 return (isdn_net_send_skb(dev , lp , skb));
804
805
806
807
808
809 #if 0
810 printk(KERN_DEBUG "xmit, skb %d\n",skb->len);
811 #endif
812
813 #ifdef CONFIG_ISDN_PPP_VJ
814 if (ipt->pppcfg & SC_COMP_TCP) {
815 u_char *buf = skb->data;
816 int pktlen;
817 int len = 4;
818 #ifdef CONFIG_ISDN_MPP
819 if (ipt->mpppcfg & SC_MP_PROT)
820 if (ipt->mpppcfg & SC_OUT_SHORT_SEQ)
821 len += 3;
822 else
823 len += 5;
824 #endif
825 buf += len;
826 pktlen = slhc_compress(ipts->slcomp, buf, skb->len-len, ipts->cbuf,
827 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
828 skb_trim(skb,pktlen+len);
829 if(buf != skb->data+len) {
830 memcpy(skb->data+len,buf,pktlen);
831 }
832 if (skb->data[len] & SL_TYPE_COMPRESSED_TCP) {
833 proto = PPP_VJC_COMP;
834 skb->data[len] ^= SL_TYPE_COMPRESSED_TCP;
835 } else {
836 if (skb->data[len] >= SL_TYPE_UNCOMPRESSED_TCP)
837 proto = PPP_VJC_UNCOMP;
838 skb->data[len] = (skb->data[len] & 0x0f) | 0x40;
839 }
840 }
841 #endif
842
843 #if 0
844 printk(KERN_DEBUG "xmit, skb %d %04x\n",skb->len,proto);
845 #endif
846
847 #ifdef CONFIG_ISDN_MPP
848 if (ipt->mpppcfg & SC_MP_PROT) {
849
850 long mp_seqno = ipts->mp_seqno;
851 ipts->mp_seqno++;
852 nd->queue = nd->queue->next;
853 if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
854
855 mp_seqno &= 0xfff;
856 skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8);
857 skb->data[5] = mp_seqno & 0xff;
858 skb->data[6] = proto;
859 } else {
860
861 skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG;
862 skb->data[5] = (mp_seqno >> 16) & 0xff;
863 skb->data[6] = (mp_seqno >> 8) & 0xff;
864 skb->data[7] = (mp_seqno >> 0) & 0xff;
865 skb->data[8] = proto;
866 }
867 proto = PPP_MP;
868 }
869 #endif
870 skb->data[0] = 0xff;
871 skb->data[1] = 0x03;
872 skb->data[2] = proto >> 8;
873 skb->data[3] = proto & 0xff;
874
875 lp->huptimer = 0;
876 if (!(ipt->pppcfg & SC_ENABLE_IP)) {
877 printk(KERN_INFO "isdn, xmit: Packet blocked: %d %d\n", lp->isdn_device, lp->isdn_channel);
878 return 1;
879 }
880
881 return (isdn_net_send_skb(dev , lp , skb));
882 }
883
884 void isdn_ppp_free_mpqueue(isdn_net_dev * p)
885 {
886 struct mpqueue *ql, *q = p->mp_last;
887 while (q) {
888 ql = q->next;
889 dev_kfree_skb(q->skb,FREE_WRITE);
890 kfree(q);
891 q = ql;
892 }
893 }
894
895 #ifdef CONFIG_ISDN_MPP
896
897 static int isdn_ppp_bundle(int minor, int unit)
898 {
899 char ifn[IFNAMSIZ + 1];
900 long flags;
901 isdn_net_dev *p;
902 isdn_net_local *lp,*nlp;
903
904 sprintf(ifn, "ippp%d", unit);
905 p = isdn_net_findif(ifn);
906 if (!p)
907 return -1;
908
909 isdn_timer_ctrl(ISDN_TIMER_IPPP, 1);
910
911 save_flags(flags);
912 cli();
913
914 nlp = ippp_table[minor].lp;
915
916 lp = p->queue;
917 p->ib.bundled = 1;
918 nlp->last = lp->last;
919 lp->last->next = nlp;
920 lp->last = nlp;
921 nlp->next = lp;
922 p->queue = nlp;
923
924 nlp->netdev = lp->netdev;
925
926 ippp_table[nlp->ppp_minor].unit = ippp_table[lp->ppp_minor].unit;
927
928 ippp_table[nlp->ppp_minor].pppcfg |= ippp_table[lp->ppp_minor].pppcfg &
929 (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
930
931 ippp_table[nlp->ppp_minor].mpppcfg |= ippp_table[lp->ppp_minor].mpppcfg &
932 (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
933 #if 0
934 if (ippp_table[nlp->ppp_minor].mpppcfg != ippp_table[lp->ppp_minor].mpppcfg) {
935 printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n",
936 ippp_table[nlp->ppp_minor].mpppcfg, ippp_table[lp->ppp_minor].mpppcfg);
937 }
938 #endif
939
940 restore_flags(flags);
941 return 0;
942 }
943
944
945 static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
946 {
947 struct mpqueue *q = dev->mp_last;
948 while (q) {
949 q->sqno &= mask;
950 q = q->next;
951 }
952 }
953
954
955 static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, int *sqnop, int min_sqno)
956 {
957 struct mpqueue *qe, *q1, *q;
958 long cnt, flags;
959 int pktlen, sqno_end;
960 int sqno = *sqnop;
961
962 q1 = (struct mpqueue *) kmalloc(sizeof(struct mpqueue), GFP_KERNEL);
963 if (!q1) {
964 printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n");
965 save_flags(flags);
966 cli();
967 isdn_ppp_cleanup_queue(dev, min_sqno);
968 restore_flags(flags);
969 return -1;
970 }
971 q1->skb = *skb;
972 q1->sqno = sqno;
973 q1->BEbyte = BEbyte;
974 q1->time = jiffies;
975
976 save_flags(flags);
977 cli();
978
979 if (!(q = dev->mp_last)) {
980 dev->mp_last = q1;
981 q1->next = NULL;
982 q1->last = NULL;
983 isdn_ppp_cleanup_queue(dev, min_sqno);
984 restore_flags(flags);
985 return -1;
986 }
987 for (;;) {
988 if (sqno > q->sqno) {
989 if (q->next) {
990 q = q->next;
991 continue;
992 }
993 q->next = q1;
994 q1->next = NULL;
995 q1->last = q;
996 break;
997 }
998 if (sqno == q->sqno)
999 printk(KERN_WARNING "isdn_fill_mpqueue: illegal sqno received!!\n");
1000 q1->last = q->last;
1001 q1->next = q;
1002 if (q->last) {
1003 q->last->next = q1;
1004 } else
1005 dev->mp_last = q1;
1006 q->last = q1;
1007 break;
1008 }
1009
1010
1011 pktlen = -q1->skb->len;
1012 q = q1;
1013 cnt = q1->sqno;
1014 while (!(q->BEbyte & MP_END_FRAG)) {
1015 cnt++;
1016 if (!(q->next) || q->next->sqno != cnt) {
1017 isdn_ppp_cleanup_queue(dev, min_sqno);
1018 restore_flags(flags);
1019 return -1;
1020 }
1021 pktlen += q->skb->len;
1022 q = q->next;
1023 }
1024 pktlen += q->skb->len;
1025 qe = q;
1026
1027 q = q1;
1028 cnt = q1->sqno;
1029 while (!(q->BEbyte & MP_BEGIN_FRAG)) {
1030 cnt--;
1031 if (!(q->last) || q->last->sqno != cnt) {
1032 isdn_ppp_cleanup_queue(dev, min_sqno);
1033 restore_flags(flags);
1034 return -1;
1035 }
1036 pktlen += q->skb->len;
1037 q = q->last;
1038 }
1039 pktlen += q->skb->len;
1040
1041 if (q->last)
1042 q->last->next = qe->next;
1043 else
1044 dev->mp_last = qe->next;
1045
1046 if (qe->next)
1047 qe->next->last = q->last;
1048 qe->next = NULL;
1049 sqno_end = qe->sqno;
1050 *sqnop = q->sqno;
1051
1052 isdn_ppp_cleanup_queue(dev, min_sqno);
1053 restore_flags(flags);
1054
1055 *skb = dev_alloc_skb(pktlen + 40);
1056
1057 if (!(*skb)) {
1058 while (q) {
1059 struct mpqueue *ql = q->next;
1060 dev_kfree_skb(q->skb,FREE_WRITE);
1061 kfree(q);
1062 q = ql;
1063 }
1064 return -2;
1065 }
1066 cnt = 0;
1067 skb_put(*skb,pktlen);
1068 while (q) {
1069 struct mpqueue *ql = q->next;
1070 memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
1071 cnt += q->skb->len;
1072 dev_kfree_skb(q->skb,FREE_WRITE);
1073 kfree(q);
1074 q = ql;
1075 }
1076
1077 return sqno_end;
1078 }
1079
1080
1081
1082
1083
1084 static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
1085 {
1086
1087
1088
1089
1090
1091
1092
1093 struct mpqueue *ql, *q = dev->mp_last;
1094 while (q) {
1095 if (q->sqno < min_sqno) {
1096 if (q->BEbyte & MP_END_FRAG) {
1097 printk(KERN_DEBUG "ippp: freeing stale packet!\n");
1098 if ((dev->mp_last = q->next))
1099 q->next->last = NULL;
1100 while (q) {
1101 ql = q->last;
1102 dev_kfree_skb(q->skb,FREE_WRITE);
1103 kfree(q);
1104 q = ql;
1105 }
1106 q = dev->mp_last;
1107 } else
1108 q = q->next;
1109 } else
1110 break;
1111 }
1112 }
1113
1114
1115
1116
1117
1118 #endif
1119
1120 void isdn_ppp_timer_timeout(void)
1121 {
1122 #ifdef CONFIG_ISDN_MPP
1123 isdn_net_dev *net_dev = dev->netdev;
1124 struct sqqueue *q, *ql = NULL, *qn;
1125
1126 while (net_dev) {
1127 isdn_net_local *lp = &net_dev->local;
1128 if (net_dev->ib.modify) {
1129 net_dev = net_dev->next;
1130 continue;
1131 }
1132
1133 q = net_dev->ib.sq;
1134 while (q) {
1135 if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) {
1136 ql = net_dev->ib.sq;
1137 net_dev->ib.sq = q->next;
1138 net_dev->ib.next_num = q->sqno_end + 1;
1139 q->next = NULL;
1140 for (; ql;) {
1141 isdn_ppp_push_higher(net_dev, lp, ql->skb, -1);
1142 qn = ql->next;
1143 kfree(ql);
1144 ql = qn;
1145 }
1146 q = net_dev->ib.sq;
1147 } else
1148 q = q->next;
1149 }
1150 net_dev = net_dev->next;
1151 }
1152 #endif
1153 }
1154
1155 int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
1156 {
1157 int error;
1158 char *r;
1159 int len;
1160 isdn_net_local *lp = (isdn_net_local *) dev->priv;
1161
1162 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
1163 return -EINVAL;
1164
1165 switch (cmd) {
1166 case SIOCGPPPVER:
1167 r = (char *) ifr->ifr_ifru.ifru_data;
1168 len = strlen(PPP_VERSION) + 1;
1169 error = verify_area(VERIFY_WRITE, r, len);
1170 if (!error)
1171 memcpy_tofs(r, PPP_VERSION, len);
1172 break;
1173 default:
1174 error = -EINVAL;
1175 }
1176 return error;
1177 }
1178
1179 static int isdn_ppp_if_get_unit(char **namebuf)
1180 {
1181 char *name = *namebuf;
1182 int len, i, unit = 0, deci;
1183
1184 len = strlen(name);
1185 for (i = 0, deci = 1; i < len; i++, deci *= 10) {
1186 if (name[len - 1 - i] >= '0' && name[len - 1 - i] <= '9')
1187 unit += (name[len - 1 - i] - '0') * deci;
1188 else
1189 break;
1190 }
1191 if (!i)
1192 unit = -1;
1193
1194 *namebuf = name + len - 1 - i;
1195 return unit;
1196
1197 }
1198
1199
1200 int isdn_ppp_dial_slave(char *name)
1201 {
1202 #ifdef CONFIG_ISDN_MPP
1203 isdn_net_dev *ndev;
1204 isdn_net_local *lp;
1205 struct device *sdev;
1206
1207 if(!(ndev = isdn_net_findif(name)))
1208 return 1;
1209 lp = &ndev->local;
1210 if(!(lp->flags & ISDN_NET_CONNECTED))
1211 return 5;
1212
1213 sdev = lp->slave;
1214 while(sdev)
1215 {
1216 isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
1217 if(!(mlp->flags & ISDN_NET_CONNECTED))
1218 break;
1219 sdev = mlp->slave;
1220 }
1221 if(!sdev)
1222 return 2;
1223
1224 isdn_net_force_dial_lp((isdn_net_local *) sdev->priv);
1225 return 0;
1226 #else
1227 return -1;
1228 #endif
1229 }
1230
1231