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