This source file includes following definitions.
- nat_getbytype
- nat_addr32
- HASH
- nat_hash_key
- nat_attach_chg
- nat_bind
- nat_unbind
- nat_dev_addr_chk_1
- net_alias_devinit
- net_alias_hard_start_xmit
- net_alias_devsetup
- net_alias_slow_findp
- net_alias_dev_create
- net_alias_dev_delete
- net_alias_free
- net_alias_dev_get
- net_alias_dev_rehash
- net_alias_types_getinfo
- net_alias_getinfo
- net_alias_device_event
- nat_addr_chk
- nat_addr_chk32
- net_alias_dev_chk
- net_alias_dev_chk32
- net_alias_dev_rcv_sel
- net_alias_dev_rcv_sel32
- net_alias_init
- register_net_alias_type
- unregister_net_alias_type
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <linux/types.h>
34 #include <linux/errno.h>
35 #include <linux/netdevice.h>
36 #include <linux/notifier.h>
37 #include <linux/if.h>
38 #include <linux/inet.h>
39 #include <linux/in.h>
40 #include <linux/proc_fs.h>
41 #include <linux/stat.h>
42
43 #ifdef ALIAS_USER_LAND_DEBUG
44 #include "net_alias.h"
45 #include "user_stubs.h"
46 #endif
47
48 #include <linux/net_alias.h>
49
50
51
52
53
54 #define NET_ALIAS_IFF_MASK (IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_NOARP|IFF_LOOPBACK|IFF_POINTOPOINT)
55
56 static struct net_alias_type * nat_getbytype(int type);
57 static int nat_attach_chg(struct net_alias_type *nat, int delta);
58 static int nat_bind(struct net_alias_type *nat,struct net_alias *alias, struct sockaddr *sa);
59 static int nat_unbind(struct net_alias_type *nat, struct net_alias *alias);
60
61
62 static int net_alias_devinit(struct device *dev);
63 static int net_alias_hard_start_xmit(struct sk_buff *skb, struct device *dev);
64 static int net_alias_devsetup(struct net_alias *alias, struct net_alias_type *nat, struct sockaddr *sa);
65 static struct net_alias **net_alias_slow_findp(struct net_alias_info *alias_info, struct net_alias *alias);
66 static struct device *net_alias_dev_create(struct device *main_dev, int slot, int *err, struct sockaddr *sa, void *data);
67 static struct device *net_alias_dev_delete(struct device *main_dev, int slot, int *err);
68 static void net_alias_free(struct device *dev);
69
70
71
72
73
74 struct net_alias_type *nat_base[16];
75
76
77
78
79
80
81 static __inline__ struct net_alias_type *
82 nat_getbytype(int type)
83 {
84 struct net_alias_type *nat;
85 for(nat = nat_base[type & 0x0f]; nat ; nat = nat->next)
86 {
87 if (nat->type == type) return nat;
88 }
89 return NULL;
90 }
91
92
93
94
95
96
97
98 static __inline__ __u32
99 nat_addr32(struct net_alias_type *nat, struct sockaddr *sa)
100 {
101 if (nat->get_addr32)
102 return nat->get_addr32(nat, sa);
103 else
104 return (*(struct sockaddr_in *)sa).sin_addr.s_addr;
105 }
106
107
108
109
110
111
112
113 static __inline__ unsigned
114 HASH(__u32 addr, int af)
115 {
116 unsigned tmp = addr ^ (addr>>16);
117 tmp ^= (tmp>>8);
118 return (tmp^(tmp>>4)^af) & 0x0f;
119 }
120
121
122
123
124
125
126
127
128
129 static __inline__ int
130 nat_hash_key(struct net_alias_type *nat, struct sockaddr *sa)
131 {
132 return HASH(nat_addr32(nat,sa), sa->sa_family);
133 }
134
135
136
137
138
139
140 static int
141 nat_attach_chg(struct net_alias_type *nat, int delta)
142 {
143 unsigned long flags;
144 int n_at;
145 if (!nat) return -1;
146 save_flags(flags);
147 cli();
148 n_at = nat->n_attach + delta;
149 if (n_at < 0)
150 {
151 restore_flags(flags);
152 printk("net_alias: tried to set n_attach < 0 for (family==%d) nat object.\n",
153 nat->type);
154 return -1;
155 }
156 nat->n_attach = n_at;
157 restore_flags(flags);
158 return 0;
159 }
160
161
162
163
164
165
166 static __inline__ int
167 nat_bind(struct net_alias_type *nat,struct net_alias *alias, struct sockaddr *sa)
168 {
169 if (nat->alias_init_1) nat->alias_init_1(nat, alias, sa);
170 return nat_attach_chg(nat, +1);
171 }
172
173
174
175
176
177
178 static __inline__ int
179 nat_unbind(struct net_alias_type *nat, struct net_alias *alias)
180 {
181 if (nat->alias_done_1) nat->alias_done_1(nat, alias);
182 return nat_attach_chg(nat, -1);
183 }
184
185
186
187
188
189
190
191 static __inline__ int nat_dev_addr_chk_1(struct net_alias_type *nat,
192 struct device *dev, struct sockaddr *sa)
193 {
194 if (nat->dev_addr_chk)
195 return nat->dev_addr_chk(nat, dev, sa);
196 else
197 return (dev->pa_addr == (*(struct sockaddr_in *)sa).sin_addr.s_addr);
198 }
199
200
201
202
203
204
205
206 static int
207 net_alias_devinit(struct device *dev)
208 {
209 #ifdef ALIAS_USER_LAND_DEBUG
210 printk("net_alias_devinit(%s) called.\n", dev->name);
211 #endif
212 return 0;
213 }
214
215
216
217
218
219
220
221 static int
222 net_alias_hard_start_xmit(struct sk_buff *skb, struct device *dev)
223 {
224 printk("net_alias: net_alias_hard_start_xmit() for %s called (ignored)!!\n", dev->name);
225 dev_kfree_skb(skb, FREE_WRITE);
226 return 0;
227 }
228
229
230
231
232
233
234 static int
235 net_alias_devsetup(struct net_alias *alias, struct net_alias_type *nat,
236 struct sockaddr *sa)
237 {
238 struct device *main_dev;
239 struct device *dev;
240 int family;
241 int i;
242
243
244
245
246
247
248
249
250 main_dev = alias->main_dev;
251 dev = &alias->dev;
252 memset(dev, '\0', sizeof(struct device));
253 family = (sa)? sa->sa_family : main_dev->family;
254
255 dev->alias_info = NULL;
256 dev->my_alias = alias;
257 dev->name = alias->name;
258 dev->type = main_dev->type;
259 dev->hard_header_len = main_dev->hard_header_len;
260 memcpy(dev->broadcast, main_dev->broadcast, MAX_ADDR_LEN);
261 memcpy(dev->dev_addr, main_dev->dev_addr, MAX_ADDR_LEN);
262 dev->addr_len = main_dev->addr_len;
263 dev->init = net_alias_devinit;
264 dev->hard_start_xmit = net_alias_hard_start_xmit;
265 dev->flags = main_dev->flags & NET_ALIAS_IFF_MASK & ~IFF_UP;
266
267
268
269
270
271 if (family == main_dev->family)
272 {
273 dev->metric = main_dev->metric;
274 dev->mtu = main_dev->mtu;
275 dev->pa_alen = main_dev->pa_alen;
276 dev->hard_header = main_dev->hard_header;
277 dev->rebuild_header = main_dev->rebuild_header;
278 }
279
280
281
282
283
284
285 for (i = 0; i < DEV_NUMBUFFS; i++)
286 skb_queue_head_init(&dev->buffs[i]);
287
288 dev->family = family;
289 return 0;
290 }
291
292
293
294
295
296
297
298 static struct net_alias **
299 net_alias_slow_findp(struct net_alias_info *alias_info, struct net_alias *alias)
300 {
301 unsigned idx, n_aliases;
302 struct net_alias **aliasp;
303
304
305
306
307
308 n_aliases = alias_info->n_aliases;
309 for (idx=0; idx < 16 ; idx++)
310 for (aliasp = &alias_info->hash_tab[idx];*aliasp;aliasp = &(*aliasp)->next)
311 if (*aliasp == alias)
312 return aliasp;
313 else
314 if (--n_aliases == 0) break;
315 return NULL;
316 }
317
318
319
320
321
322
323
324 static struct device *
325 net_alias_dev_create(struct device *main_dev, int slot, int *err, struct sockaddr *sa, void *data)
326 {
327 struct net_alias_info *alias_info;
328 struct net_alias *alias, **aliasp;
329 struct net_alias_type *nat;
330 struct device *dev;
331 unsigned long flags;
332 int family;
333 __u32 addr32;
334
335
336 alias_info = main_dev->alias_info;
337
338
339
340
341
342 family = (sa)? sa->sa_family : main_dev->family;
343
344
345
346
347
348 nat = nat_getbytype(family);
349 if (!nat)
350 {
351 printk("net_alias_dev_create(%s:%d): unregistered family==%d\n",
352 main_dev->name, slot, family);
353
354 *err = -EINVAL;
355 return NULL;
356 }
357
358
359
360
361
362 *err = -EIO;
363
364 if (! (main_dev->flags & IFF_UP) )
365 return NULL;
366
367
368
369
370
371 *err = -ENOMEM;
372
373 if (!alias_info)
374 {
375 alias_info = kmalloc(sizeof(struct net_alias_info), GFP_KERNEL);
376 if (!alias_info) return NULL;
377 memset(alias_info, 0, sizeof(struct net_alias_info));
378 }
379
380 if (!(alias = kmalloc(sizeof(struct net_alias), GFP_KERNEL)))
381 return NULL;
382
383
384
385
386
387 memset(alias, 0, sizeof(struct net_alias));
388 alias->slot = slot;
389 alias->main_dev = main_dev;
390 alias->nat = nat;
391 alias->next = NULL;
392 alias->data = data;
393 sprintf(alias->name, "%s:%d", main_dev->name, slot);
394
395
396
397
398
399 net_alias_devsetup(alias, nat, sa);
400
401 dev = &alias->dev;
402
403 save_flags(flags);
404 cli();
405
406
407
408
409
410
411 nat_bind(nat, alias, sa);
412
413
414
415
416
417
418 addr32 = (sa)? nat_addr32(nat, sa) : alias->dev.pa_addr;
419
420
421
422
423
424 alias->hash = HASH(addr32, family);
425
426
427
428
429
430 aliasp = &alias_info->hash_tab[alias->hash];
431 alias->next = *aliasp;
432 *aliasp = alias;
433
434
435
436
437
438 if (!alias_info->n_aliases++)
439 {
440 alias_info->taildev = main_dev;
441 main_dev->alias_info = alias_info;
442 }
443
444
445
446
447
448 dev->next = alias_info->taildev->next;
449 alias_info->taildev->next = dev;
450 alias_info->taildev = dev;
451 restore_flags(flags);
452 return dev;
453 }
454
455
456
457
458
459
460 static struct device *
461 net_alias_dev_delete(struct device *main_dev, int slot, int *err)
462 {
463 struct net_alias_info *alias_info;
464 struct net_alias *alias, **aliasp;
465 struct device *dev;
466 unsigned n_aliases;
467 unsigned long flags;
468 struct net_alias_type *nat;
469 struct device *prevdev;
470
471
472 *err = -ENODEV;
473
474 if (main_dev == NULL) return NULL;
475
476
477
478
479
480 alias_info = main_dev->alias_info;
481 if (!alias_info) return NULL;
482
483 n_aliases = alias_info->n_aliases;
484
485
486
487
488
489
490 for (prevdev=main_dev, alias = NULL;prevdev->next && n_aliases; prevdev = prevdev->next)
491 {
492 if (!(alias = prevdev->next->my_alias))
493 {
494 printk("ERROR: net_alias_dev_delete(): incorrect non-alias device after maindev\n");
495 continue;
496 }
497 if (alias->slot == slot) break;
498 alias = NULL;
499 n_aliases--;
500 }
501
502 if (!alias) return NULL;
503
504 dev = &alias->dev;
505
506
507
508
509
510 for(aliasp = &alias_info->hash_tab[alias->hash]; *aliasp; aliasp = &(*aliasp)->next)
511 if(*aliasp == alias) break;
512
513
514
515
516
517 if (*aliasp != alias)
518 if ((aliasp = net_alias_slow_findp(alias_info, alias)))
519 printk("net_alias_dev_delete(%s): bad hashing recovered\n", alias->name);
520 else
521 {
522 printk("ERROR: net_alias_dev_delete(%s): unhashed alias!\n",alias->name);
523 return NULL;
524 }
525
526 nat = alias->nat;
527
528 save_flags(flags);
529 cli();
530
531
532
533
534
535 nat_unbind(nat, alias);
536
537
538
539
540
541 if ( dev == alias_info->taildev )
542 alias_info->taildev = prevdev;
543
544
545
546
547 prevdev->next = dev->next;
548 dev_close(dev);
549
550
551
552
553
554 *aliasp = (*aliasp)->next;
555
556 if (--alias_info->n_aliases == 0)
557 main_dev->alias_info = NULL;
558 restore_flags(flags);
559
560
561
562
563
564 kfree_s(alias, sizeof(struct net_alias));
565 if (main_dev->alias_info == NULL)
566 kfree_s(alias_info, sizeof(struct net_alias_info));
567
568
569
570
571
572 *err = 0;
573 return NULL;
574 }
575
576
577
578
579
580
581 static void
582 net_alias_free(struct device *main_dev)
583 {
584 struct net_alias_info *alias_info;
585 struct net_alias *alias;
586 struct net_alias_type *nat;
587 struct device *dev;
588 unsigned long flags;
589
590
591
592
593
594 if (!(alias_info = main_dev->alias_info)) return;
595
596
597
598
599
600
601 save_flags(flags);
602 cli();
603
604 dev = main_dev->next;
605 main_dev->next = alias_info->taildev->next;
606 main_dev->alias_info = NULL;
607 alias_info->taildev->next = NULL;
608
609 restore_flags(flags);
610
611
612
613
614
615 while (dev)
616 {
617 if (net_alias_is(dev))
618 {
619 alias = dev->my_alias;
620 if (alias->main_dev == main_dev)
621 {
622
623
624
625
626 nat = alias->nat;
627 if (nat)
628 {
629 nat_unbind(nat, alias);
630 }
631
632 dev_close(dev);
633 dev = dev->next;
634
635 kfree_s(alias, sizeof(struct net_alias));
636 continue;
637 }
638 else
639 printk("net_alias_free(%s): '%s' is not my alias\n",
640 main_dev->name, alias->name);
641 }
642 else
643 printk("net_alias_free(%s): found a non-alias after device!\n",
644 main_dev->name);
645 dev = dev->next;
646 }
647
648 kfree_s(alias_info, sizeof(alias_info));
649 return;
650 }
651
652
653
654
655
656 struct device *
657 net_alias_dev_get(char *dev_name, int aliasing_ok, int *err,
658 struct sockaddr *sa, void *data)
659 {
660 struct device *dev;
661 char *sptr,*eptr;
662 int slot = 0;
663 int delete = 0;
664
665 *err = -ENODEV;
666 if ((dev=dev_get(dev_name)))
667 return dev;
668
669
670
671
672
673 if (!aliasing_ok) return NULL;
674
675 if (!dev_name || !*dev_name)
676 return NULL;
677
678
679
680
681
682 for (sptr=dev_name ; *sptr ; sptr++) if(*sptr==':') break;
683 if (!*sptr || !*(sptr+1))
684 return NULL;
685
686
687
688
689
690 *sptr='\0';
691 if (!(dev=dev_get(dev_name)))
692 return NULL;
693 *sptr++=':';
694
695
696
697
698
699 slot = simple_strtoul(sptr,&eptr,10);
700 if (slot >= NET_ALIAS_MAX_SLOT)
701 return NULL;
702
703
704
705
706
707 if (eptr[0] == '-' && !eptr[1] ) delete++;
708 else if (eptr[0])
709 return NULL;
710
711
712
713
714
715 if (delete)
716 return net_alias_dev_delete(dev, slot, err);
717 else
718 return net_alias_dev_create(dev, slot, err, sa, data);
719 }
720
721
722
723
724
725
726 int
727 net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
728 {
729 struct net_alias_info *alias_info;
730 struct net_alias *alias, **aliasp;
731 struct device *main_dev;
732 unsigned long flags;
733 struct net_alias_type *o_nat, *n_nat;
734 unsigned n_hash;
735
736
737
738
739
740 if (dev == NULL) return -1;
741 if ( (alias = dev->my_alias) == NULL ) return -1;
742
743 if (!sa)
744 {
745 printk("ERROR: net_alias_rehash(): NULL sockaddr passed\n");
746 return -1;
747 }
748
749
750
751
752
753 if ( (main_dev = alias->main_dev) == NULL )
754 {
755 printk("ERROR: net_alias_rehash for %s: NULL maindev\n", alias->name);
756 return -1;
757 }
758
759
760
761
762
763 if (!(alias_info=main_dev->alias_info))
764 {
765 printk("ERROR: net_alias_rehash for %s: NULL alias_info\n", alias->name);
766 return -1;
767 }
768
769
770
771
772
773 o_nat = alias->nat;
774 if (!o_nat)
775 {
776 printk("ERROR: net_alias_rehash(%s): unbound alias.\n", alias->name);
777 return -1;
778 }
779
780
781
782
783
784 if (o_nat->type == sa->sa_family)
785 n_nat = o_nat;
786 else
787 {
788 n_nat = nat_getbytype(sa->sa_family);
789 if (!n_nat)
790 {
791 printk("ERROR: net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family);
792 return -1;
793 }
794 }
795
796
797
798
799
800 n_hash = nat_hash_key(n_nat, sa);
801 if (n_hash == alias->hash && o_nat == n_nat )
802 return 0;
803
804
805
806
807
808 for (aliasp = &alias_info->hash_tab[alias->hash]; *aliasp; aliasp = &(*aliasp)->next)
809 if (*aliasp == alias) break;
810
811
812
813
814
815 if(!*aliasp)
816 if ((aliasp = net_alias_slow_findp(alias_info, alias)))
817 printk("net_alias_rehash(%s): bad hashing recovered\n", alias->name);
818 else
819 {
820 printk("ERROR: net_alias_rehash(%s): unhashed alias!\n", alias->name);
821 return -1;
822 }
823
824 save_flags(flags);
825 cli();
826
827
828
829
830
831
832 if (o_nat != n_nat)
833 nat_unbind(o_nat, alias);
834
835
836
837
838
839 if (n_hash != alias->hash)
840 {
841 *aliasp = (*aliasp)->next;
842 alias->hash = n_hash;
843 aliasp = &alias_info->hash_tab[n_hash];
844 alias->next = *aliasp;
845 *aliasp = alias;
846 }
847
848
849
850
851
852
853 if (o_nat != n_nat)
854 nat_bind(n_nat, alias, sa);
855
856 restore_flags(flags);
857 return 0;
858 }
859
860
861
862
863
864
865
866
867
868 int net_alias_types_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
869 {
870 off_t pos=0, begin=0;
871 int len=0;
872 struct net_alias_type *nat;
873 unsigned idx;
874 len=sprintf(buffer,"type name n_attach\n");
875 for (idx=0 ; idx < 16 ; idx++)
876 for (nat = nat_base[idx]; nat ; nat = nat->next)
877 {
878 len += sprintf(buffer+len, "%-7d %-15s %-7d\n",
879 nat->type, nat->name,nat->n_attach);
880 pos=begin+len;
881 if(pos<offset)
882 {
883 len=0;
884 begin=pos;
885 }
886 if(pos>offset+length)
887 break;
888 }
889 *start=buffer+(offset-begin);
890 len-=(offset-begin);
891 if(len>length)
892 len=length;
893 return len;
894 }
895
896
897
898
899
900
901
902
903
904 #define NET_ALIASES_RECSIZ 64
905 int net_alias_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
906 {
907 off_t pos=0, begin=0;
908 int len=0;
909 int dlen;
910 struct net_alias_type *nat;
911 struct net_alias *alias;
912 struct device *dev;
913
914 len=sprintf(buffer,"%-*s\n",NET_ALIASES_RECSIZ-1,"device family address");
915 for (dev = dev_base; dev ; dev = dev->next)
916 if (net_alias_is(dev))
917 {
918 alias = dev->my_alias;
919 nat = alias->nat;
920 dlen=sprintf(buffer+len, "%-16s %-6d ", alias->name, alias->dev.family);
921
922
923
924
925
926 if (nat->alias_print_1)
927 dlen += nat->alias_print_1(nat, alias, buffer+len+dlen, NET_ALIASES_RECSIZ - dlen);
928 else
929 dlen += sprintf(buffer+len+dlen, "-");
930
931
932
933
934
935 if (dlen < NET_ALIASES_RECSIZ) memset(buffer+len+dlen, ' ', NET_ALIASES_RECSIZ - dlen);
936
937
938
939
940 len += NET_ALIASES_RECSIZ;
941 buffer[len-1] = '\n';
942
943 pos=begin+len;
944 if(pos<offset)
945 {
946 len=0;
947 begin=pos;
948 }
949 if(pos>offset+length)
950 break;
951 }
952 *start=buffer+(offset-begin);
953 len-=(offset-begin);
954 if(len>length)
955 len=length;
956 return len;
957 }
958
959
960
961
962
963
964 int net_alias_device_event(struct notifier_block *this, unsigned long event, void *ptr)
965 {
966 struct device *dev = ptr;
967
968 if (event == NETDEV_DOWN)
969 {
970 #ifdef ALIAS_USER_LAND_DEBUG
971 printk("net_alias: NETDEV_DOWN for %s received\n", dev->name);
972 #endif
973 if (net_alias_has(dev))
974 net_alias_free(dev);
975 }
976
977 if (event == NETDEV_UP)
978 {
979 #ifdef ALIAS_USER_LAND_DEBUG
980 printk("net_alias: NETDEV_UP for %s received\n", dev->name);
981 #endif
982 dev->alias_info = 0;
983 }
984
985 return NOTIFY_DONE;
986 }
987
988
989
990
991
992
993
994 static __inline__ struct device *
995 nat_addr_chk(struct net_alias_type *nat, struct net_alias_info *alias_info, struct sockaddr *sa, int flags_on, int flags_off)
996 {
997 struct net_alias *alias;
998 for(alias = alias_info->hash_tab[nat_hash_key(nat,sa)];
999 alias; alias = alias->next)
1000 {
1001 if (alias->dev.family != sa->sa_family) continue;
1002
1003
1004
1005
1006
1007 if (alias->dev.flags & flags_on && !(alias->dev.flags & flags_off) &&
1008 nat_dev_addr_chk_1(nat,&alias->dev,sa))
1009 return &alias->dev;
1010 }
1011 return NULL;
1012 }
1013
1014
1015
1016
1017
1018
1019 static __inline__ struct device *
1020 nat_addr_chk32(struct net_alias_type *nat, struct net_alias_info *alias_info, int family, __u32 addr32, int flags_on, int flags_off)
1021 {
1022 struct net_alias *alias;
1023 for (alias=alias_info->hash_tab[HASH(addr32,family)];
1024 alias; alias=alias->next)
1025 {
1026 if (alias->dev.family != family) continue;
1027
1028
1029
1030
1031
1032 if (alias->dev.flags & flags_on && !(alias->dev.flags & flags_off) &&
1033 addr32 == alias->dev.pa_addr)
1034 return &alias->dev;
1035 }
1036 return NULL;
1037 }
1038
1039
1040
1041
1042
1043
1044
1045 struct device *
1046 net_alias_dev_chk(struct device *main_dev, struct sockaddr *sa,int flags_on, int flags_off)
1047 {
1048 struct net_alias_info *alias_info = main_dev->alias_info;
1049 struct net_alias_type *nat;
1050
1051
1052
1053
1054
1055 if (!alias_info) return NULL;
1056
1057
1058
1059
1060
1061 nat = nat_getbytype(sa->sa_family);
1062 if (!nat)
1063 return NULL;
1064
1065 return nat_addr_chk(nat, alias_info, sa, flags_on, flags_off);
1066 }
1067
1068
1069
1070
1071
1072
1073 struct device *
1074 net_alias_dev_chk32(struct device *main_dev, int family, __u32 addr32,
1075 int flags_on, int flags_off)
1076 {
1077 struct net_alias_info *alias_info = main_dev->alias_info;
1078
1079
1080
1081
1082
1083 if (!alias_info) return NULL;
1084
1085 return nat_addr_chk32(NULL, alias_info, family, addr32, flags_on, flags_off);
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096 struct device *
1097 net_alias_dev_rcv_sel(struct device *main_dev, struct sockaddr *sa_src, struct sockaddr *sa_dst)
1098 {
1099 int family;
1100 struct net_alias_type *nat;
1101 struct net_alias_info *alias_info;
1102 struct device *dev;
1103
1104 if (main_dev == NULL) return NULL;
1105
1106
1107
1108
1109
1110 if ((alias_info = main_dev->alias_info) == NULL)
1111 return main_dev;
1112
1113
1114
1115
1116
1117 family = (sa_src)? sa_src->sa_family : ((sa_dst)? sa_dst->sa_family : AF_UNSPEC);
1118 if (family == AF_UNSPEC) return main_dev;
1119
1120
1121
1122
1123
1124 if ( (nat = nat_getbytype(family)) == NULL ) return main_dev;
1125
1126
1127
1128
1129
1130 if (sa_dst)
1131 {
1132 if (nat_dev_addr_chk_1(nat, main_dev,sa_dst))
1133 return main_dev;
1134
1135 dev = nat_addr_chk(nat, alias_info, sa_dst, IFF_UP, 0);
1136
1137 if (dev != NULL) return dev;
1138 }
1139
1140
1141
1142
1143
1144 if ( sa_src == NULL || nat->dev_select == NULL) return main_dev;
1145 dev = nat->dev_select(nat, main_dev, sa_src);
1146
1147 if (dev == NULL || dev->family != family) return main_dev;
1148
1149
1150
1151
1152
1153 dev = net_alias_is(dev)?
1154 ( (dev->my_alias->main_dev == main_dev)? dev : NULL) : NULL;
1155
1156
1157
1158
1159
1160 return (dev)? dev : main_dev;
1161
1162 }
1163
1164
1165
1166
1167
1168 struct device *
1169 net_alias_dev_rcv_sel32(struct device *main_dev, int family, __u32 src, __u32 dst)
1170 {
1171 struct net_alias_type *nat;
1172 struct net_alias_info *alias_info;
1173 struct sockaddr_in sin_src;
1174 struct device *dev;
1175
1176 if (main_dev == NULL) return NULL;
1177
1178
1179
1180
1181
1182 if ((alias_info = main_dev->alias_info) == NULL)
1183 return main_dev;
1184
1185
1186
1187
1188
1189 if (dst == main_dev->pa_addr)
1190 return main_dev;
1191
1192 if (family == AF_UNSPEC) return main_dev;
1193
1194
1195
1196
1197
1198 if ( (nat = nat_getbytype(family)) == NULL ) return main_dev;
1199
1200
1201
1202
1203
1204 if (dst)
1205 {
1206 dev = nat_addr_chk32(nat, alias_info, family, dst, IFF_UP, 0);
1207 if (dev) return dev;
1208 }
1209
1210
1211
1212
1213
1214 if ( src == 0 || nat->dev_select == NULL) return main_dev;
1215
1216 sin_src.sin_family = family;
1217 sin_src.sin_addr.s_addr = src;
1218
1219 dev = nat->dev_select(nat, main_dev, (struct sockaddr *)&sin_src);
1220
1221 if (dev == NULL || dev->family != family) return main_dev;
1222
1223
1224
1225
1226
1227 dev = net_alias_is(dev)?
1228 ( (dev->my_alias->main_dev == main_dev)? dev : NULL) : NULL;
1229
1230
1231
1232
1233
1234 return (dev)? dev : main_dev;
1235
1236 }
1237
1238
1239
1240
1241
1242
1243 static struct notifier_block net_alias_dev_notifier = {
1244 net_alias_device_event,
1245 NULL,
1246 0
1247 };
1248
1249
1250
1251
1252
1253
1254
1255 void net_alias_init(void)
1256 {
1257
1258
1259
1260
1261
1262 register_netdevice_notifier(&net_alias_dev_notifier);
1263
1264
1265
1266
1267
1268 #ifndef ALIAS_USER_LAND_DEBUG
1269 proc_net_register(&(struct proc_dir_entry) {
1270 PROC_NET_ALIAS_TYPES, 11, "alias_types",
1271 S_IFREG | S_IRUGO, 1, 0, 0,
1272 0, &proc_net_inode_operations,
1273 net_alias_types_getinfo
1274 });
1275 proc_net_register(&(struct proc_dir_entry) {
1276 PROC_NET_ALIASES, 7, "aliases",
1277 S_IFREG | S_IRUGO, 1, 0, 0,
1278 0, &proc_net_inode_operations,
1279 net_alias_getinfo
1280 });
1281 #endif
1282
1283 }
1284
1285
1286
1287
1288 int register_net_alias_type(struct net_alias_type *nat, int type)
1289 {
1290 unsigned hash;
1291 unsigned long flags;
1292 if (!nat)
1293 {
1294 printk("register_net_alias_type(): NULL arg\n");
1295 return -EINVAL;
1296 }
1297 nat->type = type;
1298 nat->n_attach = 0;
1299 hash = nat->type & 0x0f;
1300 save_flags(flags);
1301 cli();
1302 nat->next = nat_base[hash];
1303 nat_base[hash] = nat;
1304 restore_flags(flags);
1305 return 0;
1306 }
1307
1308
1309
1310
1311 int unregister_net_alias_type(struct net_alias_type *nat)
1312 {
1313 struct net_alias_type **natp;
1314 unsigned hash;
1315 unsigned long flags;
1316
1317 if (!nat)
1318 {
1319 printk("unregister_net_alias_type(): NULL arg\n");
1320 return -EINVAL;
1321 }
1322
1323
1324
1325
1326 if (nat->n_attach)
1327 {
1328 printk("unregister_net_alias_type(): has %d attachments. failed\n",
1329 nat->n_attach);
1330 return -EINVAL;
1331 }
1332 hash = nat->type & 0x0f;
1333 save_flags(flags);
1334 cli();
1335 for (natp = &nat_base[hash]; *natp ; natp = &(*natp)->next)
1336 {
1337 if (nat==(*natp))
1338 {
1339 *natp = nat->next;
1340 restore_flags(flags);
1341 return 0;
1342 }
1343 }
1344 restore_flags(flags);
1345 printk("unregister_net_alias_type(type=%d): not found!\n", nat->type);
1346 return -EINVAL;
1347 }
1348