home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / net / inet / dev_mcast.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-23  |  4.0 KB  |  170 lines

  1. /*
  2.  *    Linux NET3:    Multicast List maintenance. 
  3.  *
  4.  *    Authors:
  5.  *        Tim Kordas <tjk@nostromo.eeap.cwru.edu> 
  6.  *        Richard Underwood <richard@wuzz.demon.co.uk>
  7.  *
  8.  *    Stir fried together from the IP multicast and CAP patches above
  9.  *        Alan Cox <Alan.Cox@linux.org>    
  10.  *
  11.  *    Fixes:
  12.  *        Alan Cox    :    Update the device on a real delete
  13.  *                    rather than any time but...
  14.  *
  15.  *    This program is free software; you can redistribute it and/or
  16.  *    modify it under the terms of the GNU General Public License
  17.  *    as published by the Free Software Foundation; either version
  18.  *    2 of the License, or (at your option) any later version.
  19.  */
  20.  
  21. #include <asm/segment.h>
  22. #include <asm/system.h>
  23. #include <asm/bitops.h>
  24. #include <linux/types.h>
  25. #include <linux/kernel.h>
  26. #include <linux/sched.h>
  27. #include <linux/string.h>
  28. #include <linux/mm.h>
  29. #include <linux/socket.h>
  30. #include <linux/sockios.h>
  31. #include <linux/in.h>
  32. #include <linux/errno.h>
  33. #include <linux/interrupt.h>
  34. #include <linux/if_ether.h>
  35. #include <linux/inet.h>
  36. #include <linux/netdevice.h>
  37. #include <linux/etherdevice.h>
  38. #include "ip.h"
  39. #include "route.h"
  40. #include <linux/skbuff.h>
  41. #include "sock.h"
  42. #include "arp.h"
  43.  
  44.  
  45. /*
  46.  *    Device multicast list maintenance. This knows about such little matters as promiscuous mode and
  47.  *    converting from the list to the array the drivers use. At least until I fix the drivers up.
  48.  *
  49.  *    This is used both by IP and by the user level maintenance functions. Unlike BSD we maintain a usage count
  50.  *    on a given multicast address so that a casual user application can add/delete multicasts used by protocols
  51.  *    without doing damage to the protocols when it deletes the entries. It also helps IP as it tracks overlapping
  52.  *    maps.
  53.  */
  54.  
  55.  
  56. /*
  57.  *    Update the multicast list into the physical NIC controller.
  58.  */
  59.  
  60. void dev_mc_upload(struct device *dev)
  61. {
  62.     struct dev_mc_list *dmi;
  63.     char *data, *tmp;
  64.  
  65.     /* Don't do anything till we up the interface
  66.        [dev_open will call this function so the list will
  67.         stay sane] */
  68.         
  69.     if(!(dev->flags&IFF_UP))
  70.         return;
  71.         
  72.         
  73.     /* Devices with no set multicast don't get set */
  74.     if(dev->set_multicast_list==NULL)
  75.         return;
  76.     /* Promiscuous is promiscuous - so no filter needed */
  77.     if(dev->flags&IFF_PROMISC)
  78.     {
  79.         dev->set_multicast_list(dev, -1, NULL);
  80.         return;
  81.     }
  82.     
  83.     if(dev->mc_count==0)
  84.     {
  85.         dev->set_multicast_list(dev,0,NULL);
  86.         return;
  87.     }
  88.     
  89.     data=kmalloc(dev->mc_count*dev->addr_len, GFP_KERNEL);
  90.     if(data==NULL)
  91.     {
  92.         printk("Unable to get memory to set multicast list on %s\n",dev->name);
  93.         return;
  94.     }
  95.     for(tmp = data, dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
  96.     {
  97.         memcpy(tmp,dmi->dmi_addr, dmi->dmi_addrlen);
  98.         tmp+=dev->addr_len;
  99.     }
  100.     dev->set_multicast_list(dev,dev->mc_count,data);
  101.     kfree(data);
  102. }
  103.   
  104. /*
  105.  *    Delete a device level multicast
  106.  */
  107.  
  108. void dev_mc_delete(struct device *dev, void *addr, int alen, int all)
  109. {
  110.     struct dev_mc_list **dmi;
  111.     for(dmi=&dev->mc_list;*dmi!=NULL;dmi=&(*dmi)->next)
  112.     {
  113.         if(memcmp((*dmi)->dmi_addr,addr,(*dmi)->dmi_addrlen)==0 && alen==(*dmi)->dmi_addrlen)
  114.         {
  115.             struct dev_mc_list *tmp= *dmi;
  116.             if(--(*dmi)->dmi_users && !all)
  117.                 return;
  118.             *dmi=(*dmi)->next;
  119.             dev->mc_count--;
  120.             kfree_s(tmp,sizeof(*tmp));
  121.             dev_mc_upload(dev);
  122.             return;
  123.         }
  124.     }
  125. }
  126.  
  127. /*
  128.  *    Add a device level multicast
  129.  */
  130.  
  131. void dev_mc_add(struct device *dev, void *addr, int alen, int newonly)
  132. {
  133.     struct dev_mc_list *dmi;
  134.     for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
  135.     {
  136.         if(memcmp(dmi->dmi_addr,addr,dmi->dmi_addrlen)==0 && dmi->dmi_addrlen==alen)
  137.         {
  138.             if(!newonly)
  139.                 dmi->dmi_users++;
  140.             return;
  141.         }
  142.     }
  143.     dmi=(struct dev_mc_list *)kmalloc(sizeof(*dmi),GFP_KERNEL);
  144.     if(dmi==NULL)
  145.         return;    /* GFP_KERNEL so can't happen anyway */
  146.     memcpy(dmi->dmi_addr, addr, alen);
  147.     dmi->dmi_addrlen=alen;
  148.     dmi->next=dev->mc_list;
  149.     dmi->dmi_users=1;
  150.     dev->mc_list=dmi;
  151.     dev->mc_count++;
  152.     dev_mc_upload(dev);
  153. }
  154.  
  155. /*
  156.  *    Discard multicast list when a device is downed
  157.  */
  158.  
  159. void dev_mc_discard(struct device *dev)
  160. {
  161.     while(dev->mc_list!=NULL)
  162.     {
  163.         struct dev_mc_list *tmp=dev->mc_list;
  164.         dev->mc_list=dev->mc_list->next;
  165.         kfree_s(tmp,sizeof(*tmp));
  166.     }
  167.     dev->mc_count=0;
  168. }
  169.  
  170.