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 struct ippp_struct *ipts = ippp_table[lp->netdev->local.ppp_minor];
806
807
808
809
810
811 if (*((unsigned long *)skb->data) != 0)
812 return (isdn_net_send_skb(dev , lp , skb));
813
814
815
816
817
818 #if 0
819 printk(KERN_DEBUG "xmit, skb %d\n",skb->len);
820 #endif
821
822 #ifdef CONFIG_ISDN_PPP_VJ
823 if (ipt->pppcfg & SC_COMP_TCP) {
824 u_char *buf = skb->data;
825 int pktlen;
826 int len = 4;
827 #ifdef CONFIG_ISDN_MPP
828 if (ipt->mpppcfg & SC_MP_PROT)
829 if (ipt->mpppcfg & SC_OUT_SHORT_SEQ)
830 len += 3;
831 else
832 len += 5;
833 #endif
834 buf += len;
835 pktlen = slhc_compress(ipts->slcomp, buf, skb->len-len, ipts->cbuf,
836 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
837 skb_trim(skb,pktlen+len);
838 if(buf != skb->data+len) {
839 memcpy(skb->data+len,buf,pktlen);
840 }
841 if (skb->data[len] & SL_TYPE_COMPRESSED_TCP) {
842 proto = PPP_VJC_COMP;
843 skb->data[len] ^= SL_TYPE_COMPRESSED_TCP;
844 } else {
845 if (skb->data[len] >= SL_TYPE_UNCOMPRESSED_TCP)
846 proto = PPP_VJC_UNCOMP;
847 skb->data[len] = (skb->data[len] & 0x0f) | 0x40;
848 }
849 }
850 #endif
851
852 #if 0
853 printk(KERN_DEBUG "xmit, skb %d %04x\n",skb->len,proto);
854 #endif
855
856 #ifdef CONFIG_ISDN_MPP
857 if (ipt->mpppcfg & SC_MP_PROT) {
858
859 long mp_seqno = ipts->mp_seqno;
860 ipts->mp_seqno++;
861 nd->queue = nd->queue->next;
862 if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
863
864 mp_seqno &= 0xfff;
865 skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8);
866 skb->data[5] = mp_seqno & 0xff;
867 skb->data[6] = proto;
868 } else {
869
870 skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG;
871 skb->data[5] = (mp_seqno >> 16) & 0xff;
872 skb->data[6] = (mp_seqno >> 8) & 0xff;
873 skb->data[7] = (mp_seqno >> 0) & 0xff;
874 skb->data[8] = proto;
875 }
876 proto = PPP_MP;
877 }
878 #endif
879 skb->data[0] = 0xff;
880 skb->data[1] = 0x03;
881 skb->data[2] = proto >> 8;
882 skb->data[3] = proto & 0xff;
883
884 lp->huptimer = 0;
885 if (!(ipt->pppcfg & SC_ENABLE_IP)) {
886 printk(KERN_INFO "isdn, xmit: Packet blocked: %d %d\n", lp->isdn_device, lp->isdn_channel);
887 return 1;
888 }
889
890 return (isdn_net_send_skb(dev , lp , skb));
891 }
892
893 void isdn_ppp_free_mpqueue(isdn_net_dev * p)
894 {
895 struct mpqueue *ql, *q = p->mp_last;
896 while (q) {
897 ql = q->next;
898 dev_kfree_skb(q->skb,FREE_WRITE);
899 kfree(q);
900 q = ql;
901 }
902 }
903
904 #ifdef CONFIG_ISDN_MPP
905
906 static int isdn_ppp_bundle(int minor, int unit)
907 {
908 char ifn[IFNAMSIZ + 1];
909 long flags;
910 isdn_net_dev *p;
911 isdn_net_local *lp,*nlp;
912
913 sprintf(ifn, "ippp%d", unit);
914 p = isdn_net_findif(ifn);
915 if (!p)
916 return -1;
917
918 isdn_timer_ctrl(ISDN_TIMER_IPPP, 1);
919
920 save_flags(flags);
921 cli();
922
923 nlp = ippp_table[minor]->lp;
924
925 lp = p->queue;
926 p->ib.bundled = 1;
927 nlp->last = lp->last;
928 lp->last->next = nlp;
929 lp->last = nlp;
930 nlp->next = lp;
931 p->queue = nlp;
932
933 nlp->netdev = lp->netdev;
934
935 ippp_table[nlp->ppp_minor]->unit = ippp_table[lp->ppp_minor]->unit;
936
937 ippp_table[nlp->ppp_minor]->pppcfg |= ippp_table[lp->ppp_minor]->pppcfg &
938 (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
939
940 ippp_table[nlp->ppp_minor]->mpppcfg |= ippp_table[lp->ppp_minor]->mpppcfg &
941 (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
942 #if 0
943 if (ippp_table[nlp->ppp_minor]->mpppcfg != ippp_table[lp->ppp_minor]->mpppcfg) {
944 printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n",
945 ippp_table[nlp->ppp_minor]->mpppcfg, ippp_table[lp->ppp_minor]->mpppcfg);
946 }
947 #endif
948
949 restore_flags(flags);
950 return 0;
951 }
952
953
954 static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
955 {
956 struct mpqueue *q = dev->mp_last;
957 while (q) {
958 q->sqno &= mask;
959 q = q->next;
960 }
961 }
962
963
964 static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, int *sqnop, int min_sqno)
965 {
966 struct mpqueue *qe, *q1, *q;
967 long cnt, flags;
968 int pktlen, sqno_end;
969 int sqno = *sqnop;
970
971 q1 = (struct mpqueue *) kmalloc(sizeof(struct mpqueue), GFP_KERNEL);
972 if (!q1) {
973 printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n");
974 save_flags(flags);
975 cli();
976 isdn_ppp_cleanup_queue(dev, min_sqno);
977 restore_flags(flags);
978 return -1;
979 }
980 q1->skb = *skb;
981 q1->sqno = sqno;
982 q1->BEbyte = BEbyte;
983 q1->time = jiffies;
984
985 save_flags(flags);
986 cli();
987
988 if (!(q = dev->mp_last)) {
989 dev->mp_last = q1;
990 q1->next = NULL;
991 q1->last = NULL;
992 isdn_ppp_cleanup_queue(dev, min_sqno);
993 restore_flags(flags);
994 return -1;
995 }
996 for (;;) {
997 if (sqno > q->sqno) {
998 if (q->next) {
999 q = q->next;
1000 continue;
1001 }
1002 q->next = q1;
1003 q1->next = NULL;
1004 q1->last = q;
1005 break;
1006 }
1007 if (sqno == q->sqno)
1008 printk(KERN_WARNING "isdn_fill_mpqueue: illegal sqno received!!\n");
1009 q1->last = q->last;
1010 q1->next = q;
1011 if (q->last) {
1012 q->last->next = q1;
1013 } else
1014 dev->mp_last = q1;
1015 q->last = q1;
1016 break;
1017 }
1018
1019
1020 pktlen = -q1->skb->len;
1021 q = q1;
1022 cnt = q1->sqno;
1023 while (!(q->BEbyte & MP_END_FRAG)) {
1024 cnt++;
1025 if (!(q->next) || q->next->sqno != cnt) {
1026 isdn_ppp_cleanup_queue(dev, min_sqno);
1027 restore_flags(flags);
1028 return -1;
1029 }
1030 pktlen += q->skb->len;
1031 q = q->next;
1032 }
1033 pktlen += q->skb->len;
1034 qe = q;
1035
1036 q = q1;
1037 cnt = q1->sqno;
1038 while (!(q->BEbyte & MP_BEGIN_FRAG)) {
1039 cnt--;
1040 if (!(q->last) || q->last->sqno != cnt) {
1041 isdn_ppp_cleanup_queue(dev, min_sqno);
1042 restore_flags(flags);
1043 return -1;
1044 }
1045 pktlen += q->skb->len;
1046 q = q->last;
1047 }
1048 pktlen += q->skb->len;
1049
1050 if (q->last)
1051 q->last->next = qe->next;
1052 else
1053 dev->mp_last = qe->next;
1054
1055 if (qe->next)
1056 qe->next->last = q->last;
1057 qe->next = NULL;
1058 sqno_end = qe->sqno;
1059 *sqnop = q->sqno;
1060
1061 isdn_ppp_cleanup_queue(dev, min_sqno);
1062 restore_flags(flags);
1063
1064 *skb = dev_alloc_skb(pktlen + 40);
1065
1066 if (!(*skb)) {
1067 while (q) {
1068 struct mpqueue *ql = q->next;
1069 dev_kfree_skb(q->skb,FREE_WRITE);
1070 kfree(q);
1071 q = ql;
1072 }
1073 return -2;
1074 }
1075 cnt = 0;
1076 skb_put(*skb,pktlen);
1077 while (q) {
1078 struct mpqueue *ql = q->next;
1079 memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
1080 cnt += q->skb->len;
1081 dev_kfree_skb(q->skb,FREE_WRITE);
1082 kfree(q);
1083 q = ql;
1084 }
1085
1086 return sqno_end;
1087 }
1088
1089
1090
1091
1092
1093 static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
1094 {
1095
1096
1097
1098
1099
1100
1101
1102 struct mpqueue *ql, *q = dev->mp_last;
1103 while (q) {
1104 if (q->sqno < min_sqno) {
1105 if (q->BEbyte & MP_END_FRAG) {
1106 printk(KERN_DEBUG "ippp: freeing stale packet!\n");
1107 if ((dev->mp_last = q->next))
1108 q->next->last = NULL;
1109 while (q) {
1110 ql = q->last;
1111 dev_kfree_skb(q->skb,FREE_WRITE);
1112 kfree(q);
1113 q = ql;
1114 }
1115 q = dev->mp_last;
1116 } else
1117 q = q->next;
1118 } else
1119 break;
1120 }
1121 }
1122
1123
1124
1125
1126
1127 #endif
1128
1129 void isdn_ppp_timer_timeout(void)
1130 {
1131 #ifdef CONFIG_ISDN_MPP
1132 isdn_net_dev *net_dev = dev->netdev;
1133 struct sqqueue *q, *ql = NULL, *qn;
1134
1135 while (net_dev) {
1136 isdn_net_local *lp = &net_dev->local;
1137 if (net_dev->ib.modify) {
1138 net_dev = net_dev->next;
1139 continue;
1140 }
1141
1142 q = net_dev->ib.sq;
1143 while (q) {
1144 if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) {
1145 ql = net_dev->ib.sq;
1146 net_dev->ib.sq = q->next;
1147 net_dev->ib.next_num = q->sqno_end + 1;
1148 q->next = NULL;
1149 for (; ql;) {
1150 isdn_ppp_push_higher(net_dev, lp, ql->skb, -1);
1151 qn = ql->next;
1152 kfree(ql);
1153 ql = qn;
1154 }
1155 q = net_dev->ib.sq;
1156 } else
1157 q = q->next;
1158 }
1159 net_dev = net_dev->next;
1160 }
1161 #endif
1162 }
1163
1164 int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
1165 {
1166 int error;
1167 char *r;
1168 int len;
1169 isdn_net_local *lp = (isdn_net_local *) dev->priv;
1170
1171 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
1172 return -EINVAL;
1173
1174 switch (cmd) {
1175 case SIOCGPPPVER:
1176 r = (char *) ifr->ifr_ifru.ifru_data;
1177 len = strlen(PPP_VERSION) + 1;
1178 error = verify_area(VERIFY_WRITE, r, len);
1179 if (!error)
1180 memcpy_tofs(r, PPP_VERSION, len);
1181 break;
1182 default:
1183 error = -EINVAL;
1184 }
1185 return error;
1186 }
1187
1188 static int isdn_ppp_if_get_unit(char **namebuf)
1189 {
1190 char *name = *namebuf;
1191 int len, i, unit = 0, deci;
1192
1193 len = strlen(name);
1194 for (i = 0, deci = 1; i < len; i++, deci *= 10) {
1195 if (name[len - 1 - i] >= '0' && name[len - 1 - i] <= '9')
1196 unit += (name[len - 1 - i] - '0') * deci;
1197 else
1198 break;
1199 }
1200 if (!i)
1201 unit = -1;
1202
1203 *namebuf = name + len - 1 - i;
1204 return unit;
1205
1206 }
1207
1208
1209 int isdn_ppp_dial_slave(char *name)
1210 {
1211 #ifdef CONFIG_ISDN_MPP
1212 isdn_net_dev *ndev;
1213 isdn_net_local *lp;
1214 struct device *sdev;
1215
1216 if(!(ndev = isdn_net_findif(name)))
1217 return 1;
1218 lp = &ndev->local;
1219 if(!(lp->flags & ISDN_NET_CONNECTED))
1220 return 5;
1221
1222 sdev = lp->slave;
1223 while(sdev)
1224 {
1225 isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
1226 if(!(mlp->flags & ISDN_NET_CONNECTED))
1227 break;
1228 sdev = mlp->slave;
1229 }
1230 if(!sdev)
1231 return 2;
1232
1233 isdn_net_force_dial_lp((isdn_net_local *) sdev->priv);
1234 return 0;
1235 #else
1236 return -1;
1237 #endif
1238 }
1239
1240