This source file includes following definitions.
- nat_getbytype
- nat_addr32
- HASH
- nat_hash_key
- nat_attach_chg
- nat_bind
- nat_unbind
- nat_addr_chk
- 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_dev_get
- net_alias_rehash
- net_alias_free
- net_alias_types_getinfo
- net_alias_getinfo
- net_alias_device_event
- net_alias_chk
- net_alias_chk32
- 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
34 #include <linux/types.h>
35 #include <linux/errno.h>
36 #include <linux/netdevice.h>
37 #include <linux/notifier.h>
38 #include <linux/if.h>
39 #include <linux/inet.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(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(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(alias);
182 return nat_attach_chg(nat, -1);
183 }
184
185
186
187
188
189
190
191 static __inline__ int nat_addr_chk(struct net_alias_type *nat,
192 struct device *dev, struct sockaddr *sa)
193 {
194 if (nat->addr_chk)
195 return nat->addr_chk(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 struct device *
582 net_alias_dev_get(char *dev_name, int aliasing_ok, int *err,
583 struct sockaddr *sa, void *data)
584 {
585 struct device *dev;
586 char *sptr,*eptr;
587 int slot = 0;
588 int delete = 0;
589
590 *err = -ENODEV;
591 if ((dev=dev_get(dev_name)))
592 return dev;
593
594
595
596
597
598 if (!aliasing_ok) return NULL;
599
600 if (!dev_name || !*dev_name)
601 return NULL;
602
603
604
605
606
607 for (sptr=dev_name ; *sptr ; sptr++) if(*sptr==':') break;
608 if (!*sptr || !*(sptr+1))
609 return NULL;
610
611
612
613
614
615 *sptr='\0';
616 if (!(dev=dev_get(dev_name)))
617 return NULL;
618 *sptr++=':';
619
620
621
622
623
624 slot = simple_strtoul(sptr,&eptr,10);
625 if (slot >= NET_ALIAS_MAX_SLOT)
626 return NULL;
627
628
629
630
631
632 if (eptr[0] == '-' && !eptr[1] ) delete++;
633 else if (eptr[0])
634 return NULL;
635
636
637
638
639
640 if (delete)
641 return net_alias_dev_delete(dev, slot, err);
642 else
643 return net_alias_dev_create(dev, slot, err, sa, data);
644 }
645
646
647
648
649
650
651 int
652 net_alias_rehash(struct net_alias *alias, struct sockaddr *sa)
653 {
654 struct net_alias_info *alias_info;
655 struct net_alias **aliasp;
656 struct device *dev;
657 unsigned long flags;
658 struct net_alias_type *o_nat, *n_nat;
659 unsigned n_hash;
660
661
662
663
664
665 if (!sa)
666 {
667 printk("ERROR: net_alias_rehash(): NULL sockaddr passed\n");
668 return -1;
669 }
670
671
672
673
674
675 if (!(dev = alias->main_dev))
676 {
677 printk("ERROR: net_alias_rehash for %s: NULL maindev\n", alias->name);
678 return -1;
679 }
680
681
682
683
684
685 if (!(alias_info=dev->alias_info))
686 {
687 printk("ERROR: net_alias_rehash for %s: NULL alias_info\n", alias->name);
688 return -1;
689 }
690
691
692
693
694
695 o_nat = alias->nat;
696 if (!o_nat)
697 {
698 printk("ERROR: net_alias_rehash(%s): unbound alias.\n", alias->name);
699 return -1;
700 }
701
702
703
704
705
706 if (o_nat->type == sa->sa_family)
707 n_nat = o_nat;
708 else
709 {
710 n_nat = nat_getbytype(sa->sa_family);
711 if (!n_nat)
712 {
713 printk("ERROR: net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family);
714 return -1;
715 }
716 }
717
718
719
720
721
722 n_hash = nat_hash_key(n_nat, sa);
723 if (n_hash == alias->hash && o_nat == n_nat )
724 return 0;
725
726
727
728
729
730 for (aliasp = &alias_info->hash_tab[alias->hash]; *aliasp; aliasp = &(*aliasp)->next)
731 if (*aliasp == alias) break;
732
733
734
735
736
737 if(!*aliasp)
738 if ((aliasp = net_alias_slow_findp(alias_info, alias)))
739 printk("net_alias_rehash(%s): bad hashing recovered\n", alias->name);
740 else
741 {
742 printk("ERROR: net_alias_rehash(%s): unhashed alias!\n", alias->name);
743 return -1;
744 }
745
746 save_flags(flags);
747 cli();
748
749
750
751
752
753
754 if (o_nat != n_nat)
755 nat_unbind(o_nat, alias);
756
757
758
759
760
761 if (n_hash != alias->hash)
762 {
763 *aliasp = (*aliasp)->next;
764 alias->hash = n_hash;
765 aliasp = &alias_info->hash_tab[n_hash];
766 alias->next = *aliasp;
767 *aliasp = alias;
768 }
769
770
771
772
773
774
775 if (o_nat != n_nat)
776 nat_bind(n_nat, alias, sa);
777
778 restore_flags(flags);
779 return 0;
780 }
781
782
783
784
785
786
787
788 static void
789 net_alias_free(struct device *main_dev)
790 {
791 struct net_alias_info *alias_info;
792 struct net_alias *alias;
793 struct net_alias_type *nat;
794 struct device *dev;
795 unsigned long flags;
796
797
798
799
800
801 if (!(alias_info = main_dev->alias_info)) return;
802
803
804
805
806
807
808 save_flags(flags);
809 cli();
810
811 dev = main_dev->next;
812 main_dev->next = alias_info->taildev->next;
813 main_dev->alias_info = NULL;
814 alias_info->taildev->next = NULL;
815
816 restore_flags(flags);
817
818
819
820
821
822 while (dev)
823 {
824 if (net_alias_is(dev))
825 {
826 alias = dev->my_alias;
827 if (alias->main_dev == main_dev)
828 {
829
830
831
832
833 nat = alias->nat;
834 if (nat)
835 {
836 nat_unbind(nat, alias);
837 }
838
839 dev_close(dev);
840 dev = dev->next;
841
842 kfree_s(alias, sizeof(struct net_alias));
843 continue;
844 }
845 else
846 printk("net_alias_free(%s): '%s' is not my alias\n",
847 main_dev->name, alias->name);
848 }
849 else
850 printk("net_alias_free(%s): found a non-alias after device!\n",
851 main_dev->name);
852 dev = dev->next;
853 }
854
855 kfree_s(alias_info, sizeof(alias_info));
856 return;
857 }
858
859
860
861
862
863
864
865 int net_alias_types_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
866 {
867 off_t pos=0, begin=0;
868 int len=0;
869 struct net_alias_type *nat;
870 unsigned idx;
871 len=sprintf(buffer,"type name n_attach\n");
872 for (idx=0 ; idx < 16 ; idx++)
873 for (nat = nat_base[idx]; nat ; nat = nat->next)
874 {
875 len += sprintf(buffer+len, "%-7d %-15s %-7d\n",
876 nat->type, nat->name,nat->n_attach);
877 pos=begin+len;
878 if(pos<offset)
879 {
880 len=0;
881 begin=pos;
882 }
883 if(pos>offset+length)
884 break;
885 }
886 *start=buffer+(offset-begin);
887 len-=(offset-begin);
888 if(len>length)
889 len=length;
890 return len;
891 }
892
893
894
895
896
897
898
899
900
901 #define NAT_REC_SIZE 64
902 int net_alias_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
903 {
904 off_t pos=0, begin=0;
905 int len=0;
906 int dlen;
907 struct net_alias_type *nat;
908 struct net_alias *alias;
909 struct device *dev;
910
911 len=sprintf(buffer,"%-*s\n",NAT_REC_SIZE-1,"device family address");
912 for (dev = dev_base; dev ; dev = dev->next)
913 if (net_alias_is(dev))
914 {
915 alias = dev->my_alias;
916 nat = alias->nat;
917 dlen=sprintf(buffer+len, "%-16s %-6d ", alias->name, alias->dev.family);
918
919
920
921
922
923 if (nat->alias_print_1)
924 dlen += nat->alias_print_1(buffer+len+dlen, NAT_REC_SIZE - dlen, alias);
925 else
926 dlen += sprintf(buffer+len+dlen, "-");
927
928
929
930
931
932 if (dlen < NAT_REC_SIZE) memset(buffer+len+dlen, ' ', NAT_REC_SIZE - dlen);
933
934
935
936
937 len += NAT_REC_SIZE;
938 buffer[len-1] = '\n';
939
940 pos=begin+len;
941 if(pos<offset)
942 {
943 len=0;
944 begin=pos;
945 }
946 if(pos>offset+length)
947 break;
948 }
949 *start=buffer+(offset-begin);
950 len-=(offset-begin);
951 if(len>length)
952 len=length;
953 return len;
954 }
955
956
957
958
959
960
961 int net_alias_device_event(struct notifier_block *this, unsigned long event, void *ptr)
962 {
963 struct device *dev = ptr;
964
965 if (event == NETDEV_DOWN)
966 {
967 #ifdef ALIAS_USER_LAND_DEBUG
968 printk("net_alias: NETDEV_DOWN for %s received\n", dev->name);
969 #endif
970 if (net_alias_has(dev))
971 net_alias_free(dev);
972 }
973
974 if (event == NETDEV_UP)
975 {
976 #ifdef ALIAS_USER_LAND_DEBUG
977 printk("net_alias: NETDEV_UP for %s received\n", dev->name);
978 #endif
979 dev->alias_info = 0;
980 }
981
982 return NOTIFY_DONE;
983 }
984
985
986
987
988
989
990
991
992
993 struct device *
994 net_alias_chk(struct device *dev, struct sockaddr *sa,int flags_1, int flags_0)
995 {
996 struct net_alias_info *alias_info = dev->alias_info;
997 struct net_alias_type *nat;
998 struct net_alias *alias;
999
1000 if (!alias_info) return NULL;
1001
1002
1003
1004
1005
1006 nat = nat_getbytype(sa->sa_family);
1007 if (!nat)
1008 return 0;
1009
1010 for(alias = alias_info->hash_tab[nat_hash_key(nat,sa)];
1011 alias; alias = alias->next)
1012 {
1013 if (alias->dev.family != sa->sa_family) continue;
1014
1015
1016
1017
1018
1019 if (alias->dev.flags & flags_1 && !(alias->dev.flags & flags_0) &&
1020 nat_addr_chk(nat,&alias->dev,sa))
1021 return &alias->dev;
1022 }
1023 return NULL;
1024 }
1025
1026
1027
1028
1029
1030 struct device *
1031 net_alias_chk32(struct device *dev, int family, __u32 addr32,
1032 int flags_1, int flags_0)
1033 {
1034 struct net_alias_info *alias_info = dev->alias_info;
1035 struct net_alias *alias;
1036
1037 if (!alias_info) return NULL;
1038
1039 for (alias=alias_info->hash_tab[HASH(addr32,family)];
1040 alias; alias=alias->next)
1041 {
1042 if (alias->dev.family != family) continue;
1043
1044
1045
1046
1047
1048 if (alias->dev.flags & flags_1 && !(alias->dev.flags & flags_0) &&
1049 addr32 == alias->dev.pa_addr)
1050 return &alias->dev;
1051 }
1052 return NULL;
1053 }
1054
1055
1056
1057
1058
1059
1060 static struct notifier_block net_alias_dev_notifier = {
1061 net_alias_device_event,
1062 NULL,
1063 0
1064 };
1065
1066
1067
1068
1069
1070
1071
1072 void net_alias_init(void)
1073 {
1074
1075
1076
1077
1078
1079 register_netdevice_notifier(&net_alias_dev_notifier);
1080
1081
1082
1083
1084
1085 #ifndef ALIAS_USER_LAND_DEBUG
1086 proc_net_register(&(struct proc_dir_entry) {
1087 PROC_NET_ALIAS_TYPES, 11, "alias_types",
1088 S_IFREG | S_IRUGO, 1, 0, 0,
1089 0, &proc_net_inode_operations,
1090 net_alias_types_getinfo
1091 });
1092 proc_net_register(&(struct proc_dir_entry) {
1093 PROC_NET_ALIASES, 7, "aliases",
1094 S_IFREG | S_IRUGO, 1, 0, 0,
1095 0, &proc_net_inode_operations,
1096 net_alias_getinfo
1097 });
1098 #endif
1099
1100 }
1101
1102
1103
1104
1105 int register_net_alias_type(struct net_alias_type *nat, int type)
1106 {
1107 unsigned hash;
1108 unsigned long flags;
1109 if (!nat)
1110 {
1111 printk("register_net_alias_type(): NULL arg\n");
1112 return -EINVAL;
1113 }
1114 nat->type = type;
1115 nat->n_attach = 0;
1116 hash = nat->type & 0x0f;
1117 save_flags(flags);
1118 cli();
1119 nat->next = nat_base[hash];
1120 nat_base[hash] = nat;
1121 restore_flags(flags);
1122 return 0;
1123 }
1124
1125
1126
1127
1128 int unregister_net_alias_type(struct net_alias_type *nat)
1129 {
1130 struct net_alias_type **natp;
1131 unsigned hash;
1132 unsigned long flags;
1133
1134 if (!nat)
1135 {
1136 printk("unregister_net_alias_type(): NULL arg\n");
1137 return -EINVAL;
1138 }
1139
1140
1141
1142
1143 if (nat->n_attach)
1144 {
1145 printk("unregister_net_alias_type(): has %d attachments. failed\n",
1146 nat->n_attach);
1147 return -EINVAL;
1148 }
1149 hash = nat->type & 0x0f;
1150 save_flags(flags);
1151 cli();
1152 for (natp = &nat_base[hash]; *natp ; natp = &(*natp)->next)
1153 {
1154 if (nat==(*natp))
1155 {
1156 *natp = nat->next;
1157 restore_flags(flags);
1158 return 0;
1159 }
1160 }
1161 restore_flags(flags);
1162 printk("unregister_net_alias_type(type=%d): not found!\n", nat->type);
1163 return -EINVAL;
1164 }