1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/poll.h>
26#include <linux/errno.h>
27#include <linux/if_arp.h>
28#include <linux/init.h>
29#include <linux/skbuff.h>
30#include <linux/pkt_sched.h>
31#include <linux/random.h>
32#include <linux/inetdevice.h>
33#include <linux/lapb.h>
34#include <linux/rtnetlink.h>
35#include <linux/etherdevice.h>
36#include <linux/hdlc.h>
37
38#undef DEBUG_PKT
39#undef DEBUG_ECN
40
41#define MAXLEN_LMISTAT 20
42
43#define PVC_STATE_NEW 0x01
44#define PVC_STATE_ACTIVE 0x02
45#define PVC_STATE_FECN 0x08
46#define PVC_STATE_BECN 0x10
47
48
49#define FR_UI 0x03
50#define FR_PAD 0x00
51
52#define NLPID_IP 0xCC
53#define NLPID_IPV6 0x8E
54#define NLPID_SNAP 0x80
55#define NLPID_PAD 0x00
56#define NLPID_Q933 0x08
57
58
59#define LMI_DLCI 0
60#define LMI_PROTO 0x08
61#define LMI_CALLREF 0x00
62#define LMI_ANSI_LOCKSHIFT 0x95
63#define LMI_REPTYPE 1
64#define LMI_CCITT_REPTYPE 0x51
65#define LMI_ALIVE 3
66#define LMI_CCITT_ALIVE 0x53
67#define LMI_PVCSTAT 7
68#define LMI_CCITT_PVCSTAT 0x57
69#define LMI_FULLREP 0
70#define LMI_INTEGRITY 1
71#define LMI_SINGLE 2
72#define LMI_STATUS_ENQUIRY 0x75
73#define LMI_STATUS 0x7D
74
75#define LMI_REPT_LEN 1
76#define LMI_INTEG_LEN 2
77
78#define LMI_LENGTH 13
79#define LMI_ANSI_LENGTH 14
80
81
82typedef struct {
83#if defined(__LITTLE_ENDIAN_BITFIELD)
84 unsigned ea1: 1;
85 unsigned cr: 1;
86 unsigned dlcih: 6;
87
88 unsigned ea2: 1;
89 unsigned de: 1;
90 unsigned becn: 1;
91 unsigned fecn: 1;
92 unsigned dlcil: 4;
93#else
94 unsigned dlcih: 6;
95 unsigned cr: 1;
96 unsigned ea1: 1;
97
98 unsigned dlcil: 4;
99 unsigned fecn: 1;
100 unsigned becn: 1;
101 unsigned de: 1;
102 unsigned ea2: 1;
103#endif
104}__attribute__ ((packed)) fr_hdr;
105
106
107static inline u16 q922_to_dlci(u8 *hdr)
108{
109 return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4);
110}
111
112
113
114static inline void dlci_to_q922(u8 *hdr, u16 dlci)
115{
116 hdr[0] = (dlci >> 2) & 0xFC;
117 hdr[1] = ((dlci << 4) & 0xF0) | 0x01;
118}
119
120
121
122static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
123{
124 pvc_device *pvc = hdlc->state.fr.first_pvc;
125
126 while (pvc) {
127 if (pvc->dlci == dlci)
128 return pvc;
129 if (pvc->dlci > dlci)
130 return NULL;
131 pvc = pvc->next;
132 }
133
134 return NULL;
135}
136
137
138static inline pvc_device* add_pvc(hdlc_device *hdlc, u16 dlci)
139{
140 pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc;
141
142 while (*pvc_p) {
143 if ((*pvc_p)->dlci == dlci)
144 return *pvc_p;
145 if ((*pvc_p)->dlci > dlci)
146 break;
147 pvc_p = &(*pvc_p)->next;
148 }
149
150 pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC);
151 if (!pvc)
152 return NULL;
153
154 memset(pvc, 0, sizeof(pvc_device));
155 pvc->dlci = dlci;
156 pvc->master = hdlc;
157 pvc->next = *pvc_p;
158 *pvc_p = pvc;
159 return pvc;
160}
161
162
163static inline int pvc_is_used(pvc_device *pvc)
164{
165 return pvc->main != NULL || pvc->ether != NULL;
166}
167
168
169static inline void delete_unused_pvcs(hdlc_device *hdlc)
170{
171 pvc_device **pvc_p = &hdlc->state.fr.first_pvc;
172
173 while (*pvc_p) {
174 if (!pvc_is_used(*pvc_p)) {
175 pvc_device *pvc = *pvc_p;
176 *pvc_p = pvc->next;
177 kfree(pvc);
178 continue;
179 }
180 pvc_p = &(*pvc_p)->next;
181 }
182}
183
184
185static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
186{
187 if (type == ARPHRD_ETHER)
188 return &pvc->ether;
189 else
190 return &pvc->main;
191}
192
193
194static inline u16 status_to_dlci(u8 *status, int *active, int *new)
195{
196 *new = (status[2] & 0x08) ? 1 : 0;
197 *active = (status[2] & 0x02) ? 1 : 0;
198
199 return ((status[0] & 0x3F) << 4) | ((status[1] & 0x78) >> 3);
200}
201
202
203static inline void dlci_to_status(u16 dlci, u8 *status, int active, int new)
204{
205 status[0] = (dlci >> 4) & 0x3F;
206 status[1] = ((dlci << 3) & 0x78) | 0x80;
207 status[2] = 0x80;
208
209 if (new)
210 status[2] |= 0x08;
211 else if (active)
212 status[2] |= 0x02;
213}
214
215
216
217static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
218{
219 u16 head_len;
220 struct sk_buff *skb = *skb_p;
221
222 switch (skb->protocol) {
223 case __constant_ntohs(ETH_P_IP):
224 head_len = 4;
225 skb_push(skb, head_len);
226 skb->data[3] = NLPID_IP;
227 break;
228
229 case __constant_ntohs(ETH_P_IPV6):
230 head_len = 4;
231 skb_push(skb, head_len);
232 skb->data[3] = NLPID_IPV6;
233 break;
234
235 case __constant_ntohs(LMI_PROTO):
236 head_len = 4;
237 skb_push(skb, head_len);
238 skb->data[3] = LMI_PROTO;
239 break;
240
241 case __constant_ntohs(ETH_P_802_3):
242 head_len = 10;
243 if (skb_headroom(skb) < head_len) {
244 struct sk_buff *skb2 = skb_realloc_headroom(skb,
245 head_len);
246 if (!skb2)
247 return -ENOBUFS;
248 dev_kfree_skb(skb);
249 skb = *skb_p = skb2;
250 }
251 skb_push(skb, head_len);
252 skb->data[3] = FR_PAD;
253 skb->data[4] = NLPID_SNAP;
254 skb->data[5] = FR_PAD;
255 skb->data[6] = 0x80;
256 skb->data[7] = 0xC2;
257 skb->data[8] = 0x00;
258 skb->data[9] = 0x07;
259 break;
260
261 default:
262 head_len = 10;
263 skb_push(skb, head_len);
264 skb->data[3] = FR_PAD;
265 skb->data[4] = NLPID_SNAP;
266 skb->data[5] = FR_PAD;
267 skb->data[6] = FR_PAD;
268 skb->data[7] = FR_PAD;
269 *(u16*)(skb->data + 8) = skb->protocol;
270 }
271
272 dlci_to_q922(skb->data, dlci);
273 skb->data[2] = FR_UI;
274 return 0;
275}
276
277
278
279static int pvc_open(struct net_device *dev)
280{
281 pvc_device *pvc = dev_to_pvc(dev);
282
283 if ((hdlc_to_dev(pvc->master)->flags & IFF_UP) == 0)
284 return -EIO;
285
286 if (pvc->open_count++ == 0) {
287 if (pvc->master->state.fr.settings.lmi == LMI_NONE)
288 pvc->state.active = 1;
289
290 pvc->master->state.fr.dce_changed = 1;
291 }
292 return 0;
293}
294
295
296
297static int pvc_close(struct net_device *dev)
298{
299 pvc_device *pvc = dev_to_pvc(dev);
300
301 if (--pvc->open_count == 0) {
302 if (pvc->master->state.fr.settings.lmi == LMI_NONE)
303 pvc->state.active = 0;
304
305 if (pvc->master->state.fr.settings.dce) {
306 pvc->master->state.fr.dce_changed = 1;
307 pvc->state.active = 0;
308 }
309 }
310 return 0;
311}
312
313
314
315int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
316{
317 pvc_device *pvc = dev_to_pvc(dev);
318 fr_proto_pvc_info info;
319
320 if (ifr->ifr_settings.type == IF_GET_PROTO) {
321 if (dev->type == ARPHRD_ETHER)
322 ifr->ifr_settings.type = IF_PROTO_FR_ETH_PVC;
323 else
324 ifr->ifr_settings.type = IF_PROTO_FR_PVC;
325
326 if (ifr->ifr_settings.size < sizeof(info)) {
327
328 ifr->ifr_settings.size = sizeof(info);
329 return -ENOBUFS;
330 }
331
332 info.dlci = pvc->dlci;
333 memcpy(info.master, hdlc_to_name(pvc->master), IFNAMSIZ);
334 if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
335 &info, sizeof(info)))
336 return -EFAULT;
337 return 0;
338 }
339
340 return -EINVAL;
341}
342
343
344static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
345{
346 return (struct net_device_stats *)
347 ((char *)dev + sizeof(struct net_device));
348}
349
350
351
352static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
353{
354 pvc_device *pvc = dev_to_pvc(dev);
355 struct net_device_stats *stats = pvc_get_stats(dev);
356
357 if (pvc->state.active) {
358 if (dev->type == ARPHRD_ETHER) {
359 int pad = ETH_ZLEN - skb->len;
360 if (pad > 0) {
361 int len = skb->len;
362 if (skb_tailroom(skb) < pad)
363 if (pskb_expand_head(skb, 0, pad,
364 GFP_ATOMIC)) {
365 stats->tx_dropped++;
366 dev_kfree_skb(skb);
367 return 0;
368 }
369 skb_put(skb, pad);
370 memset(skb->data + len, 0, pad);
371 }
372 skb->protocol = __constant_htons(ETH_P_802_3);
373 }
374 if (!fr_hard_header(&skb, pvc->dlci)) {
375 stats->tx_bytes += skb->len;
376 stats->tx_packets++;
377 if (pvc->state.fecn)
378 stats->tx_compressed++;
379 skb->dev = hdlc_to_dev(pvc->master);
380 dev_queue_xmit(skb);
381 return 0;
382 }
383 }
384
385 stats->tx_dropped++;
386 dev_kfree_skb(skb);
387 return 0;
388}
389
390
391
392static int pvc_change_mtu(struct net_device *dev, int new_mtu)
393{
394 if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
395 return -EINVAL;
396 dev->mtu = new_mtu;
397 return 0;
398}
399
400
401
402static inline void fr_log_dlci_active(pvc_device *pvc)
403{
404 printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
405 hdlc_to_name(pvc->master),
406 pvc->dlci,
407 pvc->main ? pvc->main->name : "",
408 pvc->main && pvc->ether ? " " : "",
409 pvc->ether ? pvc->ether->name : "",
410 pvc->state.new ? " new" : "",
411 !pvc->state.exist ? "deleted" :
412 pvc->state.active ? "active" : "inactive");
413}
414
415
416
417static inline u8 fr_lmi_nextseq(u8 x)
418{
419 x++;
420 return x ? x : 1;
421}
422
423
424
425static void fr_lmi_send(hdlc_device *hdlc, int fullrep)
426{
427 struct sk_buff *skb;
428 pvc_device *pvc = hdlc->state.fr.first_pvc;
429 int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH
430 : LMI_LENGTH;
431 int stat_len = 3;
432 u8 *data;
433 int i = 0;
434
435 if (hdlc->state.fr.settings.dce && fullrep) {
436 len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
437 if (len > HDLC_MAX_MRU) {
438 printk(KERN_WARNING "%s: Too many PVCs while sending "
439 "LMI full report\n", hdlc_to_name(hdlc));
440 return;
441 }
442 }
443
444 skb = dev_alloc_skb(len);
445 if (!skb) {
446 printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
447 hdlc_to_name(hdlc));
448 return;
449 }
450 memset(skb->data, 0, len);
451 skb_reserve(skb, 4);
452 skb->protocol = __constant_htons(LMI_PROTO);
453 fr_hard_header(&skb, LMI_DLCI);
454 data = skb->tail;
455 data[i++] = LMI_CALLREF;
456 data[i++] = hdlc->state.fr.settings.dce
457 ? LMI_STATUS : LMI_STATUS_ENQUIRY;
458 if (hdlc->state.fr.settings.lmi == LMI_ANSI)
459 data[i++] = LMI_ANSI_LOCKSHIFT;
460 data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
461 ? LMI_CCITT_REPTYPE : LMI_REPTYPE;
462 data[i++] = LMI_REPT_LEN;
463 data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
464
465 data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
466 ? LMI_CCITT_ALIVE : LMI_ALIVE;
467 data[i++] = LMI_INTEG_LEN;
468 data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
469 data[i++] = hdlc->state.fr.rxseq;
470
471 if (hdlc->state.fr.settings.dce && fullrep) {
472 while (pvc) {
473 data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
474 ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT;
475 data[i++] = stat_len;
476
477
478 if (hdlc->state.fr.reliable && !pvc->state.exist) {
479 pvc->state.exist = pvc->state.new = 1;
480 fr_log_dlci_active(pvc);
481 }
482
483
484 if (pvc->open_count && !pvc->state.active &&
485 pvc->state.exist && !pvc->state.new) {
486 pvc->state.active = 1;
487 fr_log_dlci_active(pvc);
488 }
489
490 dlci_to_status(pvc->dlci, data + i,
491 pvc->state.active, pvc->state.new);
492 i += stat_len;
493 pvc = pvc->next;
494 }
495 }
496
497 skb_put(skb, i);
498 skb->priority = TC_PRIO_CONTROL;
499 skb->dev = hdlc_to_dev(hdlc);
500 skb->nh.raw = skb->data;
501
502 dev_queue_xmit(skb);
503}
504
505
506
507static void fr_timer(unsigned long arg)
508{
509 hdlc_device *hdlc = (hdlc_device*)arg;
510 int i, cnt = 0, reliable;
511 u32 list;
512
513 if (hdlc->state.fr.settings.dce)
514 reliable = (jiffies - hdlc->state.fr.last_poll <
515 hdlc->state.fr.settings.t392 * HZ);
516 else {
517 hdlc->state.fr.last_errors <<= 1;
518 if (hdlc->state.fr.request) {
519 if (hdlc->state.fr.reliable)
520 printk(KERN_INFO "%s: No LMI status reply "
521 "received\n", hdlc_to_name(hdlc));
522 hdlc->state.fr.last_errors |= 1;
523 }
524
525 list = hdlc->state.fr.last_errors;
526 for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1)
527 cnt += (list & 1);
528
529 reliable = (cnt < hdlc->state.fr.settings.n392);
530 }
531
532 if (hdlc->state.fr.reliable != reliable) {
533 pvc_device *pvc = hdlc->state.fr.first_pvc;
534
535 hdlc->state.fr.reliable = reliable;
536 printk(KERN_INFO "%s: Link %sreliable\n", hdlc_to_name(hdlc),
537 reliable ? "" : "un");
538
539 if (reliable) {
540 hdlc->state.fr.n391cnt = 0;
541 hdlc->state.fr.dce_changed = 1;
542 } else {
543 while (pvc) {
544 pvc->state.exist = 0;
545 pvc->state.active = pvc->state.new = 0;
546 pvc = pvc->next;
547 }
548 }
549 }
550
551 if (hdlc->state.fr.settings.dce)
552 hdlc->state.fr.timer.expires = jiffies +
553 hdlc->state.fr.settings.t392 * HZ;
554 else {
555 if (hdlc->state.fr.n391cnt)
556 hdlc->state.fr.n391cnt--;
557
558 fr_lmi_send(hdlc, hdlc->state.fr.n391cnt == 0);
559
560 hdlc->state.fr.request = 1;
561 hdlc->state.fr.timer.expires = jiffies +
562 hdlc->state.fr.settings.t391 * HZ;
563 }
564
565 hdlc->state.fr.timer.function = fr_timer;
566 hdlc->state.fr.timer.data = arg;
567 add_timer(&hdlc->state.fr.timer);
568}
569
570
571
572static int fr_lmi_recv(hdlc_device *hdlc, struct sk_buff *skb)
573{
574 int stat_len;
575 pvc_device *pvc;
576 int reptype = -1, error, no_ram;
577 u8 rxseq, txseq;
578 int i;
579
580 if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI)
581 ? LMI_ANSI_LENGTH : LMI_LENGTH)) {
582 printk(KERN_INFO "%s: Short LMI frame\n", hdlc_to_name(hdlc));
583 return 1;
584 }
585
586 if (skb->data[5] != (!hdlc->state.fr.settings.dce ?
587 LMI_STATUS : LMI_STATUS_ENQUIRY)) {
588 printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n",
589 hdlc_to_name(hdlc), skb->data[2],
590 hdlc->state.fr.settings.dce ? "enquiry" : "reply");
591 return 1;
592 }
593
594 i = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? 7 : 6;
595
596 if (skb->data[i] !=
597 ((hdlc->state.fr.settings.lmi == LMI_CCITT)
598 ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) {
599 printk(KERN_INFO "%s: Not a report type=%x\n",
600 hdlc_to_name(hdlc), skb->data[i]);
601 return 1;
602 }
603 i++;
604
605 i++;
606
607 reptype = skb->data[i++];
608
609 if (skb->data[i]!=
610 ((hdlc->state.fr.settings.lmi == LMI_CCITT)
611 ? LMI_CCITT_ALIVE : LMI_ALIVE)) {
612 printk(KERN_INFO "%s: Unsupported status element=%x\n",
613 hdlc_to_name(hdlc), skb->data[i]);
614 return 1;
615 }
616 i++;
617
618 i++;
619
620 hdlc->state.fr.rxseq = skb->data[i++];
621 rxseq = skb->data[i++];
622
623 txseq = hdlc->state.fr.txseq;
624
625 if (hdlc->state.fr.settings.dce) {
626 if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
627 printk(KERN_INFO "%s: Unsupported report type=%x\n",
628 hdlc_to_name(hdlc), reptype);
629 return 1;
630 }
631 }
632
633 error = 0;
634 if (!hdlc->state.fr.reliable)
635 error = 1;
636
637 if (rxseq == 0 || rxseq != txseq) {
638 hdlc->state.fr.n391cnt = 0;
639 error = 1;
640 }
641
642 if (hdlc->state.fr.settings.dce) {
643 if (hdlc->state.fr.fullrep_sent && !error) {
644
645 hdlc->state.fr.fullrep_sent = 0;
646 pvc = hdlc->state.fr.first_pvc;
647 while (pvc) {
648 if (pvc->state.new) {
649 pvc->state.new = 0;
650
651
652 hdlc->state.fr.dce_changed = 1;
653 }
654 pvc = pvc->next;
655 }
656 }
657
658 if (hdlc->state.fr.dce_changed) {
659 reptype = LMI_FULLREP;
660 hdlc->state.fr.fullrep_sent = 1;
661 hdlc->state.fr.dce_changed = 0;
662 }
663
664 fr_lmi_send(hdlc, reptype == LMI_FULLREP ? 1 : 0);
665 return 0;
666 }
667
668
669
670 if (reptype != LMI_FULLREP || error)
671 return 0;
672
673 stat_len = 3;
674 pvc = hdlc->state.fr.first_pvc;
675
676 while (pvc) {
677 pvc->state.deleted = 1;
678 pvc = pvc->next;
679 }
680
681 no_ram = 0;
682 while (skb->len >= i + 2 + stat_len) {
683 u16 dlci;
684 unsigned int active, new;
685
686 if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT)
687 ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) {
688 printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n",
689 hdlc_to_name(hdlc), skb->data[i]);
690 return 1;
691 }
692 i++;
693
694 if (skb->data[i] != stat_len) {
695 printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n",
696 hdlc_to_name(hdlc), skb->data[i]);
697 return 1;
698 }
699 i++;
700
701 dlci = status_to_dlci(skb->data + i, &active, &new);
702
703 pvc = add_pvc(hdlc, dlci);
704
705 if (!pvc && !no_ram) {
706 printk(KERN_WARNING
707 "%s: Memory squeeze on fr_lmi_recv()\n",
708 hdlc_to_name(hdlc));
709 no_ram = 1;
710 }
711
712 if (pvc) {
713 pvc->state.exist = 1;
714 pvc->state.deleted = 0;
715 if (active != pvc->state.active ||
716 new != pvc->state.new) {
717 pvc->state.new = new;
718 pvc->state.active = active;
719 fr_log_dlci_active(pvc);
720 }
721 }
722
723 i += stat_len;
724 }
725
726 pvc = hdlc->state.fr.first_pvc;
727
728 while (pvc) {
729 if (pvc->state.deleted && pvc->state.exist) {
730 pvc->state.active = pvc->state.new = 0;
731 pvc->state.exist = 0;
732 fr_log_dlci_active(pvc);
733 }
734 pvc = pvc->next;
735 }
736
737
738 hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391;
739
740 return 0;
741}
742
743
744
745static void fr_rx(struct sk_buff *skb)
746{
747 hdlc_device *hdlc = dev_to_hdlc(skb->dev);
748 fr_hdr *fh = (fr_hdr*)skb->data;
749 u8 *data = skb->data;
750 u16 dlci;
751 pvc_device *pvc;
752 struct net_device *dev = NULL;
753
754 if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI)
755 goto rx_error;
756
757 dlci = q922_to_dlci(skb->data);
758
759 if (dlci == LMI_DLCI) {
760 if (hdlc->state.fr.settings.lmi == LMI_NONE)
761 goto rx_error;
762
763 if (data[3] == LMI_PROTO) {
764 if (fr_lmi_recv(hdlc, skb))
765 goto rx_error;
766 else {
767
768 hdlc->state.fr.request = 0;
769 hdlc->state.fr.last_poll = jiffies;
770 dev_kfree_skb_any(skb);
771 return;
772 }
773 }
774
775 printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
776 hdlc_to_name(hdlc));
777 goto rx_error;
778 }
779
780 pvc = find_pvc(hdlc, dlci);
781 if (!pvc) {
782#ifdef DEBUG_PKT
783 printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
784 hdlc_to_name(hdlc), dlci);
785#endif
786 dev_kfree_skb_any(skb);
787 return;
788 }
789
790 if (pvc->state.fecn != fh->fecn) {
791#ifdef DEBUG_ECN
792 printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", hdlc_to_name(pvc),
793 dlci, fh->fecn ? "N" : "FF");
794#endif
795 pvc->state.fecn ^= 1;
796 }
797
798 if (pvc->state.becn != fh->becn) {
799#ifdef DEBUG_ECN
800 printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", hdlc_to_name(pvc),
801 dlci, fh->becn ? "N" : "FF");
802#endif
803 pvc->state.becn ^= 1;
804 }
805
806
807 if (data[3] == NLPID_IP) {
808 skb_pull(skb, 4);
809 dev = pvc->main;
810 skb->protocol = htons(ETH_P_IP);
811
812 } else if (data[3] == NLPID_IPV6) {
813 skb_pull(skb, 4);
814 dev = pvc->main;
815 skb->protocol = htons(ETH_P_IPV6);
816
817 } else if (skb->len > 10 && data[3] == FR_PAD &&
818 data[4] == NLPID_SNAP && data[5] == FR_PAD) {
819 u16 oui = ntohs(*(u16*)(data + 6));
820 u16 pid = ntohs(*(u16*)(data + 8));
821 skb_pull(skb, 10);
822
823 switch ((((u32)oui) << 16) | pid) {
824 case ETH_P_ARP:
825 case ETH_P_IPX:
826 case ETH_P_IP:
827 case ETH_P_IPV6:
828 dev = pvc->main;
829 skb->protocol = htons(pid);
830 break;
831
832 case 0x80C20007:
833 if ((dev = pvc->ether) != NULL)
834 skb->protocol = eth_type_trans(skb, dev);
835 break;
836
837 default:
838 printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
839 "PID=%x\n", hdlc_to_name(hdlc), oui, pid);
840 dev_kfree_skb_any(skb);
841 return;
842 }
843 } else {
844 printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
845 "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len);
846 dev_kfree_skb_any(skb);
847 return;
848 }
849
850 if (dev) {
851 struct net_device_stats *stats = pvc_get_stats(dev);
852 stats->rx_packets++;
853 stats->rx_bytes += skb->len;
854 if (pvc->state.becn)
855 stats->rx_compressed++;
856 skb->dev = dev;
857 netif_rx(skb);
858 } else
859 dev_kfree_skb_any(skb);
860
861 return;
862
863 rx_error:
864 hdlc->stats.rx_errors++;
865 dev_kfree_skb_any(skb);
866}
867
868
869
870static int fr_open(hdlc_device *hdlc)
871{
872 if (hdlc->state.fr.settings.lmi != LMI_NONE) {
873 hdlc->state.fr.last_poll = 0;
874 hdlc->state.fr.reliable = 0;
875 hdlc->state.fr.dce_changed = 1;
876 hdlc->state.fr.request = 0;
877 hdlc->state.fr.fullrep_sent = 0;
878 hdlc->state.fr.last_errors = 0xFFFFFFFF;
879 hdlc->state.fr.n391cnt = 0;
880 hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0;
881
882 init_timer(&hdlc->state.fr.timer);
883
884 hdlc->state.fr.timer.expires = jiffies + HZ;
885 hdlc->state.fr.timer.function = fr_timer;
886 hdlc->state.fr.timer.data = (unsigned long)hdlc;
887 add_timer(&hdlc->state.fr.timer);
888 } else
889 hdlc->state.fr.reliable = 1;
890
891 return 0;
892}
893
894
895
896static void fr_close(hdlc_device *hdlc)
897{
898 pvc_device *pvc = hdlc->state.fr.first_pvc;
899
900 if (hdlc->state.fr.settings.lmi != LMI_NONE)
901 del_timer_sync(&hdlc->state.fr.timer);
902
903 while (pvc) {
904 if (pvc->main)
905 dev_close(pvc->main);
906 if (pvc->ether)
907 dev_close(pvc->ether);
908 pvc->state.active = pvc->state.new = pvc->state.fecn =
909 pvc->state.becn = 0;
910 pvc->state.exist = 0;
911 pvc = pvc->next;
912 }
913}
914
915
916static int fr_add_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
917{
918 pvc_device *pvc = NULL;
919 struct net_device *dev;
920 int result, used;
921 char * prefix = "pvc%d";
922
923 if (type == ARPHRD_ETHER)
924 prefix = "pvceth%d";
925
926 if ((pvc = add_pvc(hdlc, dlci)) == NULL) {
927 printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
928 hdlc_to_name(hdlc));
929 return -ENOBUFS;
930 }
931
932 if (*get_dev_p(pvc, type))
933 return -EEXIST;
934
935 used = pvc_is_used(pvc);
936
937 dev = kmalloc(sizeof(struct net_device) +
938 sizeof(struct net_device_stats), GFP_KERNEL);
939 if (!dev) {
940 printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
941 hdlc_to_name(hdlc));
942 delete_unused_pvcs(hdlc);
943 return -ENOBUFS;
944 }
945 memset(dev, 0, sizeof(struct net_device) +
946 sizeof(struct net_device_stats));
947
948 if (type == ARPHRD_ETHER) {
949 ether_setup(dev);
950 memcpy(dev->dev_addr, "\x00\x01", 2);
951 get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
952 } else {
953 dev->type = ARPHRD_DLCI;
954 dev->flags = IFF_POINTOPOINT;
955 dev->hard_header_len = 10;
956 dev->addr_len = 2;
957 *(u16*)dev->dev_addr = htons(dlci);
958 dlci_to_q922(dev->broadcast, dlci);
959 }
960 dev->hard_start_xmit = pvc_xmit;
961 dev->get_stats = pvc_get_stats;
962 dev->open = pvc_open;
963 dev->stop = pvc_close;
964 dev->do_ioctl = pvc_ioctl;
965 dev->change_mtu = pvc_change_mtu;
966 dev->mtu = HDLC_MAX_MTU;
967 dev->tx_queue_len = 0;
968 dev->priv = pvc;
969
970 result = dev_alloc_name(dev, prefix);
971 if (result < 0) {
972 kfree(dev);
973 delete_unused_pvcs(hdlc);
974 return result;
975 }
976
977 if (register_netdevice(dev) != 0) {
978 kfree(dev);
979 delete_unused_pvcs(hdlc);
980 return -EIO;
981 }
982
983 *get_dev_p(pvc, type) = dev;
984 if (!used) {
985 hdlc->state.fr.dce_changed = 1;
986 hdlc->state.fr.dce_pvc_count++;
987 }
988 return 0;
989}
990
991
992
993static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
994{
995 pvc_device *pvc;
996 struct net_device *dev;
997
998 if ((pvc = find_pvc(hdlc, dlci)) == NULL)
999 return -ENOENT;
1000
1001 if ((dev = *get_dev_p(pvc, type)) == NULL)
1002 return -ENOENT;
1003
1004 if (dev->flags & IFF_UP)
1005 return -EBUSY;
1006
1007 unregister_netdevice(dev);
1008 kfree(dev);
1009 *get_dev_p(pvc, type) = NULL;
1010
1011 if (!pvc_is_used(pvc)) {
1012 hdlc->state.fr.dce_pvc_count--;
1013 hdlc->state.fr.dce_changed = 1;
1014 }
1015 delete_unused_pvcs(hdlc);
1016 return 0;
1017}
1018
1019
1020
1021static void fr_destroy(hdlc_device *hdlc)
1022{
1023 pvc_device *pvc = hdlc->state.fr.first_pvc;
1024 while (pvc) {
1025 pvc_device *next = pvc->next;
1026 if (pvc->main) {
1027 unregister_netdevice(pvc->main);
1028 kfree(pvc->main);
1029 }
1030 if (pvc->ether) {
1031 unregister_netdevice(pvc->ether);
1032 kfree(pvc->ether);
1033 }
1034 kfree(pvc);
1035 pvc = next;
1036 }
1037
1038 hdlc->state.fr.first_pvc = NULL;
1039 hdlc->state.fr.dce_pvc_count = 0;
1040 hdlc->state.fr.dce_changed = 1;
1041}
1042
1043
1044
1045int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
1046{
1047 fr_proto *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
1048 const size_t size = sizeof(fr_proto);
1049 fr_proto new_settings;
1050 struct net_device *dev = hdlc_to_dev(hdlc);
1051 fr_proto_pvc pvc;
1052 int result;
1053
1054 switch (ifr->ifr_settings.type) {
1055 case IF_GET_PROTO:
1056 ifr->ifr_settings.type = IF_PROTO_FR;
1057 if (ifr->ifr_settings.size < size) {
1058 ifr->ifr_settings.size = size;
1059 return -ENOBUFS;
1060 }
1061 if (copy_to_user(fr_s, &hdlc->state.fr.settings, size))
1062 return -EFAULT;
1063 return 0;
1064
1065 case IF_PROTO_FR:
1066 if(!capable(CAP_NET_ADMIN))
1067 return -EPERM;
1068
1069 if(dev->flags & IFF_UP)
1070 return -EBUSY;
1071
1072 if (copy_from_user(&new_settings, fr_s, size))
1073 return -EFAULT;
1074
1075 if (new_settings.lmi == LMI_DEFAULT)
1076 new_settings.lmi = LMI_ANSI;
1077
1078 if ((new_settings.lmi != LMI_NONE &&
1079 new_settings.lmi != LMI_ANSI &&
1080 new_settings.lmi != LMI_CCITT) ||
1081 new_settings.t391 < 1 ||
1082 new_settings.t392 < 2 ||
1083 new_settings.n391 < 1 ||
1084 new_settings.n392 < 1 ||
1085 new_settings.n393 < new_settings.n392 ||
1086 new_settings.n393 > 32 ||
1087 (new_settings.dce != 0 &&
1088 new_settings.dce != 1))
1089 return -EINVAL;
1090
1091 result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
1092 if (result)
1093 return result;
1094
1095 if (hdlc->proto != IF_PROTO_FR) {
1096 hdlc_proto_detach(hdlc);
1097 hdlc->state.fr.first_pvc = NULL;
1098 hdlc->state.fr.dce_pvc_count = 0;
1099 }
1100 memcpy(&hdlc->state.fr.settings, &new_settings, size);
1101
1102 hdlc->open = fr_open;
1103 hdlc->stop = fr_close;
1104 hdlc->netif_rx = fr_rx;
1105 hdlc->type_trans = NULL;
1106 hdlc->proto_detach = fr_destroy;
1107 hdlc->proto = IF_PROTO_FR;
1108 dev->hard_start_xmit = hdlc->xmit;
1109 dev->hard_header = NULL;
1110 dev->type = ARPHRD_FRAD;
1111 dev->flags = IFF_POINTOPOINT | IFF_NOARP;
1112 dev->addr_len = 0;
1113 return 0;
1114
1115 case IF_PROTO_FR_ADD_PVC:
1116 case IF_PROTO_FR_DEL_PVC:
1117 case IF_PROTO_FR_ADD_ETH_PVC:
1118 case IF_PROTO_FR_DEL_ETH_PVC:
1119 if(!capable(CAP_NET_ADMIN))
1120 return -EPERM;
1121
1122 if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc,
1123 sizeof(fr_proto_pvc)))
1124 return -EFAULT;
1125
1126 if (pvc.dlci <= 0 || pvc.dlci >= 1024)
1127 return -EINVAL;
1128
1129 if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC ||
1130 ifr->ifr_settings.type == IF_PROTO_FR_DEL_ETH_PVC)
1131 result = ARPHRD_ETHER;
1132 else
1133 result = ARPHRD_DLCI;
1134
1135 if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC ||
1136 ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC)
1137 return fr_add_pvc(hdlc, pvc.dlci, result);
1138 else
1139 return fr_del_pvc(hdlc, pvc.dlci, result);
1140 }
1141
1142 return -EINVAL;
1143}
1144