root/net/core/net_alias.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nat_getbytype
  2. nat_addr32
  3. HASH
  4. nat_hash_key
  5. nat_attach_chg
  6. nat_bind
  7. nat_unbind
  8. nat_dev_addr_chk_1
  9. net_alias_devinit
  10. net_alias_hard_start_xmit
  11. net_alias_devsetup
  12. net_alias_slow_findp
  13. net_alias_dev_create
  14. net_alias_dev_delete
  15. net_alias_free
  16. net_alias_dev_get
  17. net_alias_dev_rehash
  18. net_alias_types_getinfo
  19. net_alias_getinfo
  20. net_alias_device_event
  21. nat_addr_chk
  22. nat_addr_chk32
  23. net_alias_dev_chk
  24. net_alias_dev_chk32
  25. net_alias_dev_rcv_sel
  26. net_alias_dev_rcv_sel32
  27. net_alias_init
  28. register_net_alias_type
  29. unregister_net_alias_type

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

/* [previous][next][first][last][top][bottom][index][help] */