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