Main Page | Class List | File List | Class Members | File Members

devinet.c File Reference

#include <linux/config.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <linux/notifier.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/kmod.h>
#include <net/ip.h>
#include <net/route.h>
#include <net/ip_fib.h>

Go to the source code of this file.

Functions

void rtmsg_ifa (int event, struct in_ifaddr *)
void inet_del_ifa (struct in_device *in_dev, struct in_ifaddr **ifap, int destroy)
in_ifaddrinet_alloc_ifa (void)
__inline__ void inet_free_ifa (struct in_ifaddr *ifa)
void in_dev_finish_destroy (struct in_device *idev)
in_deviceinetdev_init (struct net_device *dev)
void inetdev_destroy (struct in_device *in_dev)
int inet_addr_onlink (struct in_device *in_dev, u32 a, u32 b)
int inet_insert_ifa (struct in_ifaddr *ifa)
int inet_set_ifa (struct net_device *dev, struct in_ifaddr *ifa)
in_deviceinetdev_by_index (int ifindex)
in_ifaddrinet_ifa_byprefix (struct in_device *in_dev, u32 prefix, u32 mask)
int inet_rtm_deladdr (struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
int inet_rtm_newaddr (struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
__inline__ int inet_abc_len (u32 addr)
int devinet_ioctl (unsigned int cmd, void *arg)
int inet_gifconf (struct net_device *dev, char *buf, int len)
u32 inet_select_addr (const struct net_device *dev, u32 dst, int scope)
int register_inetaddr_notifier (struct notifier_block *nb)
int unregister_inetaddr_notifier (struct notifier_block *nb)
void inetdev_changename (struct net_device *dev, struct in_device *in_dev)
int inetdev_event (struct notifier_block *this, unsigned long event, void *ptr)
int inet_fill_ifaddr (struct sk_buff *skb, struct in_ifaddr *ifa, u32 pid, u32 seq, int event)
int inet_dump_ifaddr (struct sk_buff *skb, struct netlink_callback *cb)
void __init devinet_init (void)

Variables

ipv4_devconf ipv4_devconf = { 1, 1, 1, 1, 0, }
ipv4_devconf ipv4_devconf_dflt = { 1, 1, 1, 1, 1, }
notifier_block * inetaddr_chain
int inet_ifa_count
int inet_dev_count
rwlock_t inetdev_lock = RW_LOCK_UNLOCKED
notifier_block ip_netdev_notifier
rtnetlink_link inet_rtnetlink_table [RTM_MAX-RTM_BASE+1]


Function Documentation

void __init devinet_init void   ) 
 

Definition at line 1168 of file devinet.c.

References inet_gifconf(), inet_rtnetlink_table, ip_netdev_notifier, ipv4_devconf_dflt, register_gifconf(), register_netdevice_notifier(), and rtnetlink_links.

Referenced by ip_rt_init().

01169 { 01170 register_gifconf(PF_INET, inet_gifconf); 01171 register_netdevice_notifier(&ip_netdev_notifier); 01172 rtnetlink_links[PF_INET] = inet_rtnetlink_table; 01173 #ifdef CONFIG_SYSCTL 01174 devinet_sysctl.sysctl_header = 01175 register_sysctl_table(devinet_sysctl.devinet_root_dir, 0); 01176 devinet_sysctl_register(NULL, &ipv4_devconf_dflt); 01177 #endif 01178 }

int devinet_ioctl unsigned int  cmd,
void *  arg
 

Definition at line 459 of file devinet.c.

References __dev_get_by_name(), __in_dev_get(), bad_mask(), dev_change_flags(), dev_load(), inet_abc_len(), inet_alloc_ifa(), inet_del_ifa(), inet_insert_ifa(), inet_make_mask(), inet_mask_len(), inet_set_ifa(), rtnl_lock(), rtnl_unlock(), in_addr::s_addr, sockaddr_in::sin_addr, and sockaddr_in::sin_family.

Referenced by ic_dev_ioctl(), and inet_ioctl().

00460 { 00461 struct ifreq ifr; 00462 struct sockaddr_in sin_orig; 00463 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; 00464 struct in_device *in_dev; 00465 struct in_ifaddr **ifap = NULL; 00466 struct in_ifaddr *ifa = NULL; 00467 struct net_device *dev; 00468 char *colon; 00469 int ret = 0; 00470 int tryaddrmatch = 0; 00471 00472 /* 00473 * Fetch the caller's info block into kernel space 00474 */ 00475 00476 if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) 00477 return -EFAULT; 00478 ifr.ifr_name[IFNAMSIZ-1] = 0; 00479 00480 /* save original address for comparison */ 00481 memcpy(&sin_orig, sin, sizeof(*sin)); 00482 00483 colon = strchr(ifr.ifr_name, ':'); 00484 if (colon) 00485 *colon = 0; 00486 00487 #ifdef CONFIG_KMOD 00488 dev_load(ifr.ifr_name); 00489 #endif 00490 00491 switch(cmd) { 00492 case SIOCGIFADDR: /* Get interface address */ 00493 case SIOCGIFBRDADDR: /* Get the broadcast address */ 00494 case SIOCGIFDSTADDR: /* Get the destination address */ 00495 case SIOCGIFNETMASK: /* Get the netmask for the interface */ 00496 /* Note that these ioctls will not sleep, 00497 so that we do not impose a lock. 00498 One day we will be forced to put shlock here (I mean SMP) 00499 */ 00500 tryaddrmatch = (sin_orig.sin_family == AF_INET); 00501 memset(sin, 0, sizeof(*sin)); 00502 sin->sin_family = AF_INET; 00503 break; 00504 00505 case SIOCSIFFLAGS: 00506 if (!capable(CAP_NET_ADMIN)) 00507 return -EACCES; 00508 break; 00509 case SIOCSIFADDR: /* Set interface address (and family) */ 00510 case SIOCSIFBRDADDR: /* Set the broadcast address */ 00511 case SIOCSIFDSTADDR: /* Set the destination address */ 00512 case SIOCSIFNETMASK: /* Set the netmask for the interface */ 00513 if (!capable(CAP_NET_ADMIN)) 00514 return -EACCES; 00515 if (sin->sin_family != AF_INET) 00516 return -EINVAL; 00517 break; 00518 default: 00519 return -EINVAL; 00520 } 00521 00522 dev_probe_lock(); 00523 rtnl_lock(); 00524 00525 if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL) { 00526 ret = -ENODEV; 00527 goto done; 00528 } 00529 00530 if (colon) 00531 *colon = ':'; 00532 00533 if ((in_dev=__in_dev_get(dev)) != NULL) { 00534 if (tryaddrmatch) { 00535 /* Matthias Andree */ 00536 /* compare label and address (4.4BSD style) */ 00537 /* note: we only do this for a limited set of ioctls 00538 and only if the original address family was AF_INET. 00539 This is checked above. */ 00540 for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) { 00541 if ((strcmp(ifr.ifr_name, ifa->ifa_label) == 0) 00542 && (sin_orig.sin_addr.s_addr == ifa->ifa_address)) { 00543 break; /* found */ 00544 } 00545 } 00546 } 00547 /* we didn't get a match, maybe the application is 00548 4.3BSD-style and passed in junk so we fall back to 00549 comparing just the label */ 00550 if (ifa == NULL) { 00551 for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) 00552 if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0) 00553 break; 00554 } 00555 } 00556 00557 if (ifa == NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) { 00558 ret = -EADDRNOTAVAIL; 00559 goto done; 00560 } 00561 00562 switch(cmd) { 00563 case SIOCGIFADDR: /* Get interface address */ 00564 sin->sin_addr.s_addr = ifa->ifa_local; 00565 goto rarok; 00566 00567 case SIOCGIFBRDADDR: /* Get the broadcast address */ 00568 sin->sin_addr.s_addr = ifa->ifa_broadcast; 00569 goto rarok; 00570 00571 case SIOCGIFDSTADDR: /* Get the destination address */ 00572 sin->sin_addr.s_addr = ifa->ifa_address; 00573 goto rarok; 00574 00575 case SIOCGIFNETMASK: /* Get the netmask for the interface */ 00576 sin->sin_addr.s_addr = ifa->ifa_mask; 00577 goto rarok; 00578 00579 case SIOCSIFFLAGS: 00580 if (colon) { 00581 if (ifa == NULL) { 00582 ret = -EADDRNOTAVAIL; 00583 break; 00584 } 00585 if (!(ifr.ifr_flags&IFF_UP)) 00586 inet_del_ifa(in_dev, ifap, 1); 00587 break; 00588 } 00589 ret = dev_change_flags(dev, ifr.ifr_flags); 00590 break; 00591 00592 case SIOCSIFADDR: /* Set interface address (and family) */ 00593 if (inet_abc_len(sin->sin_addr.s_addr) < 0) { 00594 ret = -EINVAL; 00595 break; 00596 } 00597 00598 if (!ifa) { 00599 if ((ifa = inet_alloc_ifa()) == NULL) { 00600 ret = -ENOBUFS; 00601 break; 00602 } 00603 if (colon) 00604 memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); 00605 else 00606 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 00607 } else { 00608 ret = 0; 00609 if (ifa->ifa_local == sin->sin_addr.s_addr) 00610 break; 00611 inet_del_ifa(in_dev, ifap, 0); 00612 ifa->ifa_broadcast = 0; 00613 ifa->ifa_anycast = 0; 00614 } 00615 00616 ifa->ifa_address = 00617 ifa->ifa_local = sin->sin_addr.s_addr; 00618 00619 if (!(dev->flags&IFF_POINTOPOINT)) { 00620 ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address); 00621 ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen); 00622 if ((dev->flags&IFF_BROADCAST) && ifa->ifa_prefixlen < 31) 00623 ifa->ifa_broadcast = ifa->ifa_address|~ifa->ifa_mask; 00624 } else { 00625 ifa->ifa_prefixlen = 32; 00626 ifa->ifa_mask = inet_make_mask(32); 00627 } 00628 ret = inet_set_ifa(dev, ifa); 00629 break; 00630 00631 case SIOCSIFBRDADDR: /* Set the broadcast address */ 00632 if (ifa->ifa_broadcast != sin->sin_addr.s_addr) { 00633 inet_del_ifa(in_dev, ifap, 0); 00634 ifa->ifa_broadcast = sin->sin_addr.s_addr; 00635 inet_insert_ifa(ifa); 00636 } 00637 break; 00638 00639 case SIOCSIFDSTADDR: /* Set the destination address */ 00640 if (ifa->ifa_address != sin->sin_addr.s_addr) { 00641 if (inet_abc_len(sin->sin_addr.s_addr) < 0) { 00642 ret = -EINVAL; 00643 break; 00644 } 00645 inet_del_ifa(in_dev, ifap, 0); 00646 ifa->ifa_address = sin->sin_addr.s_addr; 00647 inet_insert_ifa(ifa); 00648 } 00649 break; 00650 00651 case SIOCSIFNETMASK: /* Set the netmask for the interface */ 00652 00653 /* 00654 * The mask we set must be legal. 00655 */ 00656 if (bad_mask(sin->sin_addr.s_addr, 0)) { 00657 ret = -EINVAL; 00658 break; 00659 } 00660 00661 if (ifa->ifa_mask != sin->sin_addr.s_addr) { 00662 inet_del_ifa(in_dev, ifap, 0); 00663 ifa->ifa_mask = sin->sin_addr.s_addr; 00664 ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); 00665 inet_insert_ifa(ifa); 00666 } 00667 break; 00668 } 00669 done: 00670 rtnl_unlock(); 00671 dev_probe_unlock(); 00672 return ret; 00673 00674 rarok: 00675 rtnl_unlock(); 00676 dev_probe_unlock(); 00677 if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) 00678 return -EFAULT; 00679 return 0; 00680 }

void in_dev_finish_destroy struct in_device idev  ) 
 

Definition at line 104 of file devinet.c.

References in_device::dead, in_device::dev, dev_put(), in_device::ifa_list, inet_dev_count, and in_device::mc_list.

Referenced by in_dev_put().

00105 { 00106 struct net_device *dev = idev->dev; 00107 00108 BUG_TRAP(idev->ifa_list==NULL); 00109 BUG_TRAP(idev->mc_list==NULL); 00110 #ifdef NET_REFCNT_DEBUG 00111 printk(KERN_DEBUG "in_dev_finish_destroy: %p=%s\n", idev, dev ? dev->name : "NIL"); 00112 #endif 00113 dev_put(dev); 00114 if (!idev->dead) { 00115 printk("Freeing alive in_device %p\n", idev); 00116 return; 00117 } 00118 inet_dev_count--; 00119 kfree(idev); 00120 }

__inline__ int inet_abc_len u32  addr  )  [static]
 

Definition at line 438 of file devinet.c.

References IN_CLASSA, IN_CLASSB, IN_CLASSC, and ZERONET.

Referenced by devinet_ioctl().

00439 { 00440 if (ZERONET(addr)) 00441 return 0; 00442 00443 addr = ntohl(addr); 00444 if (IN_CLASSA(addr)) 00445 return 8; 00446 if (IN_CLASSB(addr)) 00447 return 16; 00448 if (IN_CLASSC(addr)) 00449 return 24; 00450 00451 /* 00452 * Something else, probably a multicast. 00453 */ 00454 00455 return -1; 00456 }

int inet_addr_onlink struct in_device in_dev,
u32  a,
u32  b
 

Definition at line 187 of file devinet.c.

References endfor_ifa, for_primary_ifa, inet_ifa_match(), and in_device::lock.

Referenced by ip_route_input_slow(), and ip_rt_redirect().

00188 { 00189 read_lock(&in_dev->lock); 00190 for_primary_ifa(in_dev) { 00191 if (inet_ifa_match(a, ifa)) { 00192 if (!b || inet_ifa_match(b, ifa)) { 00193 read_unlock(&in_dev->lock); 00194 return 1; 00195 } 00196 } 00197 } endfor_ifa(in_dev); 00198 read_unlock(&in_dev->lock); 00199 return 0; 00200 }

struct in_ifaddr* inet_alloc_ifa void   )  [static]
 

Definition at line 83 of file devinet.c.

References inet_ifa_count.

Referenced by devinet_ioctl(), inet_rtm_newaddr(), and inetdev_event().

00084 { 00085 struct in_ifaddr *ifa; 00086 00087 ifa = kmalloc(sizeof(*ifa), GFP_KERNEL); 00088 if (ifa) { 00089 memset(ifa, 0, sizeof(*ifa)); 00090 inet_ifa_count++; 00091 } 00092 00093 return ifa; 00094 }

void inet_del_ifa struct in_device in_dev,
struct in_ifaddr **  ifap,
int  destroy
[static]
 

Definition at line 203 of file devinet.c.

References in_device::ifa_list, inet_free_ifa(), inet_ifa_match(), inetaddr_chain, inetdev_destroy(), in_device::lock, and rtmsg_ifa().

Referenced by devinet_ioctl(), inet_rtm_deladdr(), and inetdev_destroy().

00204 { 00205 struct in_ifaddr *ifa1 = *ifap; 00206 00207 ASSERT_RTNL(); 00208 00209 /* 1. Deleting primary ifaddr forces deletion all secondaries */ 00210 00211 if (!(ifa1->ifa_flags&IFA_F_SECONDARY)) { 00212 struct in_ifaddr *ifa; 00213 struct in_ifaddr **ifap1 = &ifa1->ifa_next; 00214 00215 while ((ifa=*ifap1) != NULL) { 00216 if (!(ifa->ifa_flags&IFA_F_SECONDARY) || 00217 ifa1->ifa_mask != ifa->ifa_mask || 00218 !inet_ifa_match(ifa1->ifa_address, ifa)) { 00219 ifap1 = &ifa->ifa_next; 00220 continue; 00221 } 00222 write_lock_bh(&in_dev->lock); 00223 *ifap1 = ifa->ifa_next; 00224 write_unlock_bh(&in_dev->lock); 00225 00226 rtmsg_ifa(RTM_DELADDR, ifa); 00227 notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); 00228 inet_free_ifa(ifa); 00229 } 00230 } 00231 00232 /* 2. Unlink it */ 00233 00234 write_lock_bh(&in_dev->lock); 00235 *ifap = ifa1->ifa_next; 00236 write_unlock_bh(&in_dev->lock); 00237 00238 /* 3. Announce address deletion */ 00239 00240 /* Send message first, then call notifier. 00241 At first sight, FIB update triggered by notifier 00242 will refer to already deleted ifaddr, that could confuse 00243 netlink listeners. It is not true: look, gated sees 00244 that route deleted and if it still thinks that ifaddr 00245 is valid, it will try to restore deleted routes... Grr. 00246 So that, this order is correct. 00247 */ 00248 rtmsg_ifa(RTM_DELADDR, ifa1); 00249 notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); 00250 if (destroy) { 00251 inet_free_ifa(ifa1); 00252 00253 if (in_dev->ifa_list == NULL) 00254 inetdev_destroy(in_dev); 00255 } 00256 }

int inet_dump_ifaddr struct sk_buff skb,
struct netlink_callback cb
[static]
 

Definition at line 912 of file devinet.c.

References __in_dev_get(), netlink_callback::args, dev_base, dev_base_lock, inet_fill_ifaddr(), inetdev_lock, sk_buff::len, NETLINK_CB, net_device::next, netlink_callback::nlh, nlmsghdr::nlmsg_seq, and netlink_callback::skb.

00913 { 00914 int idx, ip_idx; 00915 int s_idx, s_ip_idx; 00916 struct net_device *dev; 00917 struct in_device *in_dev; 00918 struct in_ifaddr *ifa; 00919 00920 s_idx = cb->args[0]; 00921 s_ip_idx = ip_idx = cb->args[1]; 00922 read_lock(&dev_base_lock); 00923 for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { 00924 if (idx < s_idx) 00925 continue; 00926 if (idx > s_idx) 00927 s_ip_idx = 0; 00928 read_lock(&inetdev_lock); 00929 if ((in_dev = __in_dev_get(dev)) == NULL) { 00930 read_unlock(&inetdev_lock); 00931 continue; 00932 } 00933 read_lock(&in_dev->lock); 00934 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; 00935 ifa = ifa->ifa_next, ip_idx++) { 00936 if (ip_idx < s_ip_idx) 00937 continue; 00938 if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, 00939 cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0) { 00940 read_unlock(&in_dev->lock); 00941 read_unlock(&inetdev_lock); 00942 goto done; 00943 } 00944 } 00945 read_unlock(&in_dev->lock); 00946 read_unlock(&inetdev_lock); 00947 } 00948 00949 done: 00950 read_unlock(&dev_base_lock); 00951 cb->args[0] = idx; 00952 cb->args[1] = ip_idx; 00953 00954 return skb->len; 00955 }

int inet_fill_ifaddr struct sk_buff skb,
struct in_ifaddr ifa,
u32  pid,
u32  seq,
int  event
[static]
 

Definition at line 878 of file devinet.c.

References sk_buff::data, in_device::dev, in_ifaddr::ifa_address, in_ifaddr::ifa_anycast, in_ifaddr::ifa_broadcast, in_ifaddr::ifa_dev, in_ifaddr::ifa_flags, in_ifaddr::ifa_label, in_ifaddr::ifa_local, in_ifaddr::ifa_prefixlen, in_ifaddr::ifa_scope, net_device::ifindex, sk_buff::len, NLM_F_MULTI, NLMSG_DATA, NLMSG_PUT, skb_trim(), and sk_buff::tail.

Referenced by inet_dump_ifaddr(), and rtmsg_ifa().

00880 { 00881 struct ifaddrmsg *ifm; 00882 struct nlmsghdr *nlh; 00883 unsigned char *b = skb->tail; 00884 00885 nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm)); 00886 if (pid) nlh->nlmsg_flags |= NLM_F_MULTI; 00887 ifm = NLMSG_DATA(nlh); 00888 ifm->ifa_family = AF_INET; 00889 ifm->ifa_prefixlen = ifa->ifa_prefixlen; 00890 ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT; 00891 ifm->ifa_scope = ifa->ifa_scope; 00892 ifm->ifa_index = ifa->ifa_dev->dev->ifindex; 00893 if (ifa->ifa_address) 00894 RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address); 00895 if (ifa->ifa_local) 00896 RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local); 00897 if (ifa->ifa_broadcast) 00898 RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast); 00899 if (ifa->ifa_anycast) 00900 RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast); 00901 if (ifa->ifa_label[0]) 00902 RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); 00903 nlh->nlmsg_len = skb->tail - b; 00904 return skb->len; 00905 00906 nlmsg_failure: 00907 rtattr_failure: 00908 skb_trim(skb, b - skb->data); 00909 return -1; 00910 }

__inline__ void inet_free_ifa struct in_ifaddr ifa  )  [static]
 

Definition at line 96 of file devinet.c.

References __in_dev_put, in_ifaddr::ifa_dev, and inet_ifa_count.

Referenced by inet_del_ifa(), inet_insert_ifa(), inet_set_ifa(), and inetdev_destroy().

00097 { 00098 if (ifa->ifa_dev) 00099 __in_dev_put(ifa->ifa_dev); 00100 kfree(ifa); 00101 inet_ifa_count--; 00102 }

int inet_gifconf struct net_device dev,
char *  buf,
int  len
[static]
 

Definition at line 683 of file devinet.c.

References __in_dev_get(), and net_device::name.

Referenced by devinet_init().

00684 { 00685 struct in_device *in_dev = __in_dev_get(dev); 00686 struct in_ifaddr *ifa; 00687 struct ifreq ifr; 00688 int done=0; 00689 00690 if (in_dev==NULL || (ifa=in_dev->ifa_list)==NULL) 00691 return 0; 00692 00693 for ( ; ifa; ifa = ifa->ifa_next) { 00694 if (!buf) { 00695 done += sizeof(ifr); 00696 continue; 00697 } 00698 if (len < (int) sizeof(ifr)) 00699 return done; 00700 memset(&ifr, 0, sizeof(struct ifreq)); 00701 if (ifa->ifa_label) 00702 strcpy(ifr.ifr_name, ifa->ifa_label); 00703 else 00704 strcpy(ifr.ifr_name, dev->name); 00705 00706 (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET; 00707 (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local; 00708 00709 if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) 00710 return -EFAULT; 00711 buf += sizeof(struct ifreq); 00712 len -= sizeof(struct ifreq); 00713 done += sizeof(struct ifreq); 00714 } 00715 return done; 00716 }

struct in_ifaddr* inet_ifa_byprefix struct in_device in_dev,
u32  prefix,
u32  mask
 

Definition at line 347 of file devinet.c.

References endfor_ifa, for_primary_ifa, and inet_ifa_match().

Referenced by fib_add_ifaddr(), and fib_del_ifaddr().

00348 { 00349 ASSERT_RTNL(); 00350 00351 for_primary_ifa(in_dev) { 00352 if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa)) 00353 return ifa; 00354 } endfor_ifa(in_dev); 00355 return NULL; 00356 }

int inet_insert_ifa struct in_ifaddr ifa  )  [static]
 

Definition at line 259 of file devinet.c.

References in_ifaddr::ifa_dev, in_ifaddr::ifa_flags, in_ifaddr::ifa_local, in_ifaddr::ifa_mask, in_ifaddr::ifa_next, in_ifaddr::ifa_scope, inet_free_ifa(), inet_ifa_match(), inetaddr_chain, net_srandom(), and rtmsg_ifa().

Referenced by devinet_ioctl(), inet_rtm_newaddr(), inet_set_ifa(), and inetdev_event().

00260 { 00261 struct in_device *in_dev = ifa->ifa_dev; 00262 struct in_ifaddr *ifa1, **ifap, **last_primary; 00263 00264 ASSERT_RTNL(); 00265 00266 if (ifa->ifa_local == 0) { 00267 inet_free_ifa(ifa); 00268 return 0; 00269 } 00270 00271 ifa->ifa_flags &= ~IFA_F_SECONDARY; 00272 last_primary = &in_dev->ifa_list; 00273 00274 for (ifap=&in_dev->ifa_list; (ifa1=*ifap)!=NULL; ifap=&ifa1->ifa_next) { 00275 if (!(ifa1->ifa_flags&IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope) 00276 last_primary = &ifa1->ifa_next; 00277 if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) { 00278 if (ifa1->ifa_local == ifa->ifa_local) { 00279 inet_free_ifa(ifa); 00280 return -EEXIST; 00281 } 00282 if (ifa1->ifa_scope != ifa->ifa_scope) { 00283 inet_free_ifa(ifa); 00284 return -EINVAL; 00285 } 00286 ifa->ifa_flags |= IFA_F_SECONDARY; 00287 } 00288 } 00289 00290 if (!(ifa->ifa_flags&IFA_F_SECONDARY)) { 00291 net_srandom(ifa->ifa_local); 00292 ifap = last_primary; 00293 } 00294 00295 ifa->ifa_next = *ifap; 00296 write_lock_bh(&in_dev->lock); 00297 *ifap = ifa; 00298 write_unlock_bh(&in_dev->lock); 00299 00300 /* Send message first, then call notifier. 00301 Notifier will trigger FIB update, so that 00302 listeners of netlink will know about new ifaddr */ 00303 rtmsg_ifa(RTM_NEWADDR, ifa); 00304 notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); 00305 00306 return 0; 00307 }

int inet_rtm_deladdr struct sk_buff skb,
struct nlmsghdr nlh,
void *  arg
 

Definition at line 359 of file devinet.c.

References __in_dev_put, inet_del_ifa(), inet_ifa_match(), inetdev_by_index(), and NLMSG_DATA.

00360 { 00361 struct rtattr **rta = arg; 00362 struct in_device *in_dev; 00363 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 00364 struct in_ifaddr *ifa, **ifap; 00365 00366 ASSERT_RTNL(); 00367 00368 if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) 00369 return -EADDRNOTAVAIL; 00370 __in_dev_put(in_dev); 00371 00372 for (ifap=&in_dev->ifa_list; (ifa=*ifap)!=NULL; ifap=&ifa->ifa_next) { 00373 if ((rta[IFA_LOCAL-1] && memcmp(RTA_DATA(rta[IFA_LOCAL-1]), &ifa->ifa_local, 4)) || 00374 (rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)) || 00375 (rta[IFA_ADDRESS-1] && 00376 (ifm->ifa_prefixlen != ifa->ifa_prefixlen || 00377 !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS-1]), ifa)))) 00378 continue; 00379 inet_del_ifa(in_dev, ifap, 1); 00380 return 0; 00381 } 00382 00383 return -EADDRNOTAVAIL; 00384 }

int inet_rtm_newaddr struct sk_buff skb,
struct nlmsghdr nlh,
void *  arg
 

Definition at line 387 of file devinet.c.

References __dev_get_by_index(), __in_dev_get(), in_dev_hold, inet_alloc_ifa(), inet_insert_ifa(), inet_make_mask(), inetdev_init(), and NLMSG_DATA.

00388 { 00389 struct rtattr **rta = arg; 00390 struct net_device *dev; 00391 struct in_device *in_dev; 00392 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 00393 struct in_ifaddr *ifa; 00394 00395 ASSERT_RTNL(); 00396 00397 if (ifm->ifa_prefixlen > 32 || rta[IFA_LOCAL-1] == NULL) 00398 return -EINVAL; 00399 00400 if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) 00401 return -ENODEV; 00402 00403 if ((in_dev = __in_dev_get(dev)) == NULL) { 00404 in_dev = inetdev_init(dev); 00405 if (!in_dev) 00406 return -ENOBUFS; 00407 } 00408 00409 if ((ifa = inet_alloc_ifa()) == NULL) 00410 return -ENOBUFS; 00411 00412 if (rta[IFA_ADDRESS-1] == NULL) 00413 rta[IFA_ADDRESS-1] = rta[IFA_LOCAL-1]; 00414 memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 4); 00415 memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 4); 00416 ifa->ifa_prefixlen = ifm->ifa_prefixlen; 00417 ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); 00418 if (rta[IFA_BROADCAST-1]) 00419 memcpy(&ifa->ifa_broadcast, RTA_DATA(rta[IFA_BROADCAST-1]), 4); 00420 if (rta[IFA_ANYCAST-1]) 00421 memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST-1]), 4); 00422 ifa->ifa_flags = ifm->ifa_flags; 00423 ifa->ifa_scope = ifm->ifa_scope; 00424 in_dev_hold(in_dev); 00425 ifa->ifa_dev = in_dev; 00426 if (rta[IFA_LABEL-1]) 00427 memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ); 00428 else 00429 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 00430 00431 return inet_insert_ifa(ifa); 00432 }

u32 inet_select_addr const struct net_device dev,
u32  dst,
int  scope
 

Definition at line 718 of file devinet.c.

References __in_dev_get(), dev_base, dev_base_lock, endfor_ifa, for_primary_ifa, inet_ifa_match(), inetdev_lock, net_device::next, and scope.

Referenced by __fib_res_prefsrc(), arp_solicit(), bind_mcastif_addr(), do_masquerade(), fib_validate_source(), ip_route_input_mc(), ip_route_input_slow(), ip_route_output_slow(), and ip_rt_get_source().

00719 { 00720 u32 addr = 0; 00721 struct in_device *in_dev; 00722 00723 read_lock(&inetdev_lock); 00724 in_dev = __in_dev_get(dev); 00725 if (in_dev == NULL) { 00726 read_unlock(&inetdev_lock); 00727 return 0; 00728 } 00729 00730 read_lock(&in_dev->lock); 00731 for_primary_ifa(in_dev) { 00732 if (ifa->ifa_scope > scope) 00733 continue; 00734 if (!dst || inet_ifa_match(dst, ifa)) { 00735 addr = ifa->ifa_local; 00736 break; 00737 } 00738 if (!addr) 00739 addr = ifa->ifa_local; 00740 } endfor_ifa(in_dev); 00741 read_unlock(&in_dev->lock); 00742 read_unlock(&inetdev_lock); 00743 00744 if (addr) 00745 return addr; 00746 00747 /* Not loopback addresses on loopback should be preferred 00748 in this case. It is importnat that lo is the first interface 00749 in dev_base list. 00750 */ 00751 read_lock(&dev_base_lock); 00752 read_lock(&inetdev_lock); 00753 for (dev=dev_base; dev; dev=dev->next) { 00754 if ((in_dev=__in_dev_get(dev)) == NULL) 00755 continue; 00756 00757 read_lock(&in_dev->lock); 00758 for_primary_ifa(in_dev) { 00759 if (ifa->ifa_scope != RT_SCOPE_LINK && 00760 ifa->ifa_scope <= scope) { 00761 read_unlock(&in_dev->lock); 00762 read_unlock(&inetdev_lock); 00763 read_unlock(&dev_base_lock); 00764 return ifa->ifa_local; 00765 } 00766 } endfor_ifa(in_dev); 00767 read_unlock(&in_dev->lock); 00768 } 00769 read_unlock(&inetdev_lock); 00770 read_unlock(&dev_base_lock); 00771 00772 return 0; 00773 }

int inet_set_ifa struct net_device dev,
struct in_ifaddr ifa
[static]
 

Definition at line 310 of file devinet.c.

References __in_dev_get(), in_ifaddr::ifa_dev, in_ifaddr::ifa_local, in_ifaddr::ifa_scope, in_dev_hold, inet_free_ifa(), inet_insert_ifa(), inetdev_init(), and LOOPBACK.

Referenced by devinet_ioctl().

00311 { 00312 struct in_device *in_dev = __in_dev_get(dev); 00313 00314 ASSERT_RTNL(); 00315 00316 if (in_dev == NULL) { 00317 in_dev = inetdev_init(dev); 00318 if (in_dev == NULL) { 00319 inet_free_ifa(ifa); 00320 return -ENOBUFS; 00321 } 00322 } 00323 if (ifa->ifa_dev != in_dev) { 00324 BUG_TRAP(ifa->ifa_dev==NULL); 00325 in_dev_hold(in_dev); 00326 ifa->ifa_dev=in_dev; 00327 } 00328 if (LOOPBACK(ifa->ifa_local)) 00329 ifa->ifa_scope = RT_SCOPE_HOST; 00330 return inet_insert_ifa(ifa); 00331 }

struct in_device* inetdev_by_index int  ifindex  ) 
 

Definition at line 333 of file devinet.c.

References __dev_get_by_index(), dev_base_lock, and in_dev_get().

Referenced by fib_check_nh(), inet_rtm_deladdr(), ip_mc_drop_socket(), ip_mc_find_dev(), and ip_mc_leave_group().

00334 { 00335 struct net_device *dev; 00336 struct in_device *in_dev = NULL; 00337 read_lock(&dev_base_lock); 00338 dev = __dev_get_by_index(ifindex); 00339 if (dev) 00340 in_dev = in_dev_get(dev); 00341 read_unlock(&dev_base_lock); 00342 return in_dev; 00343 }

void inetdev_changename struct net_device dev,
struct in_device in_dev
[static]
 

Definition at line 792 of file devinet.c.

References in_device::ifa_list, in_ifaddr::ifa_next, and net_device::name.

Referenced by inetdev_event().

00793 { 00794 struct in_ifaddr *ifa; 00795 int named = 0; 00796 00797 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { 00798 char old[IFNAMSIZ], *dot; 00799 00800 memcpy(old, ifa->ifa_label, IFNAMSIZ); 00801 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 00802 if (named++ == 0) 00803 continue; 00804 dot = strchr(ifa->ifa_label, ':'); 00805 if (dot == NULL) { 00806 sprintf(old, ":%d", named); 00807 dot = old; 00808 } 00809 if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) { 00810 strcat(ifa->ifa_label, dot); 00811 } else { 00812 strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); 00813 } 00814 } 00815 }

void inetdev_destroy struct in_device in_dev  )  [static]
 

Definition at line 159 of file devinet.c.

References in_device::arp_parms, arp_tbl, in_device::cnf, in_device::dead, in_device::dev, in_device::ifa_list, in_dev_put(), inet_del_ifa(), inet_free_ifa(), inetdev_lock, ip_mc_destroy_dev(), net_device::ip_ptr, and neigh_parms_release().

Referenced by inet_del_ifa(), and inetdev_event().

00160 { 00161 struct in_ifaddr *ifa; 00162 00163 ASSERT_RTNL(); 00164 00165 in_dev->dead = 1; 00166 00167 ip_mc_destroy_dev(in_dev); 00168 00169 while ((ifa = in_dev->ifa_list) != NULL) { 00170 inet_del_ifa(in_dev, &in_dev->ifa_list, 0); 00171 inet_free_ifa(ifa); 00172 } 00173 00174 #ifdef CONFIG_SYSCTL 00175 devinet_sysctl_unregister(&in_dev->cnf); 00176 #endif 00177 write_lock_bh(&inetdev_lock); 00178 in_dev->dev->ip_ptr = NULL; 00179 /* in_dev_put following below will kill the in_device */ 00180 write_unlock_bh(&inetdev_lock); 00181 00182 00183 neigh_parms_release(&arp_tbl, in_dev->arp_parms); 00184 in_dev_put(in_dev); 00185 }

int inetdev_event struct notifier_block *  this,
unsigned long  event,
void *  ptr
[static]
 

Definition at line 819 of file devinet.c.

References __in_dev_get(), in_dev_hold, INADDR_LOOPBACK, inet_alloc_ifa(), inet_insert_ifa(), inet_make_mask(), inetdev_changename(), inetdev_destroy(), ip_mc_down(), ip_mc_up(), and loopback_dev.

00820 { 00821 struct net_device *dev = ptr; 00822 struct in_device *in_dev = __in_dev_get(dev); 00823 00824 ASSERT_RTNL(); 00825 00826 if (in_dev == NULL) 00827 return NOTIFY_DONE; 00828 00829 switch (event) { 00830 case NETDEV_REGISTER: 00831 printk(KERN_DEBUG "inetdev_event: bug\n"); 00832 dev->ip_ptr = NULL; 00833 break; 00834 case NETDEV_UP: 00835 if (dev->mtu < 68) 00836 break; 00837 if (dev == &loopback_dev) { 00838 struct in_ifaddr *ifa; 00839 if ((ifa = inet_alloc_ifa()) != NULL) { 00840 ifa->ifa_local = 00841 ifa->ifa_address = htonl(INADDR_LOOPBACK); 00842 ifa->ifa_prefixlen = 8; 00843 ifa->ifa_mask = inet_make_mask(8); 00844 in_dev_hold(in_dev); 00845 ifa->ifa_dev = in_dev; 00846 ifa->ifa_scope = RT_SCOPE_HOST; 00847 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 00848 inet_insert_ifa(ifa); 00849 } 00850 } 00851 ip_mc_up(in_dev); 00852 break; 00853 case NETDEV_DOWN: 00854 ip_mc_down(in_dev); 00855 break; 00856 case NETDEV_CHANGEMTU: 00857 if (dev->mtu >= 68) 00858 break; 00859 /* MTU falled under 68, disable IP */ 00860 case NETDEV_UNREGISTER: 00861 inetdev_destroy(in_dev); 00862 break; 00863 case NETDEV_CHANGENAME: 00864 /* Do not notify about label change, this event is 00865 * not interesting to applications using netlink. 00866 */ 00867 inetdev_changename(dev, in_dev); 00868 break; 00869 } 00870 00871 return NOTIFY_DONE; 00872 }

struct in_device* inetdev_init struct net_device dev  ) 
 

Definition at line 122 of file devinet.c.

References arp_tbl, dev_hold, net_device::flags, in_dev_hold, inet_dev_count, inetdev_lock, ip_mc_up(), net_device::ip_ptr, ipv4_devconf_dflt, neigh_parms_alloc(), and neigh_sysctl_register().

Referenced by inet_rtm_newaddr(), inet_set_ifa(), and ipmr_new_tunnel().

00123 { 00124 struct in_device *in_dev; 00125 00126 ASSERT_RTNL(); 00127 00128 in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL); 00129 if (!in_dev) 00130 return NULL; 00131 memset(in_dev, 0, sizeof(*in_dev)); 00132 in_dev->lock = RW_LOCK_UNLOCKED; 00133 memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf)); 00134 in_dev->cnf.sysctl = NULL; 00135 in_dev->dev = dev; 00136 if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) { 00137 kfree(in_dev); 00138 return NULL; 00139 } 00140 inet_dev_count++; 00141 /* Reference in_dev->dev */ 00142 dev_hold(dev); 00143 #ifdef CONFIG_SYSCTL 00144 neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4"); 00145 #endif 00146 write_lock_bh(&inetdev_lock); 00147 dev->ip_ptr = in_dev; 00148 /* Account for reference dev->ip_ptr */ 00149 in_dev_hold(in_dev); 00150 write_unlock_bh(&inetdev_lock); 00151 #ifdef CONFIG_SYSCTL 00152 devinet_sysctl_register(in_dev, &in_dev->cnf); 00153 #endif 00154 if (dev->flags&IFF_UP) 00155 ip_mc_up(in_dev); 00156 return in_dev; 00157 }

int register_inetaddr_notifier struct notifier_block *  nb  ) 
 

Definition at line 779 of file devinet.c.

References inetaddr_chain.

Referenced by init(), and ip_fib_init().

00780 { 00781 return notifier_chain_register(&inetaddr_chain, nb); 00782 }

void rtmsg_ifa int  event,
struct in_ifaddr
[static]
 

Definition at line 957 of file devinet.c.

References alloc_skb(), inet_fill_ifaddr(), kfree_skb(), netlink_broadcast(), NETLINK_CB, netlink_set_err(), NLMSG_SPACE, and rtnl.

Referenced by inet_del_ifa(), and inet_insert_ifa().

00958 { 00959 struct sk_buff *skb; 00960 int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128); 00961 00962 skb = alloc_skb(size, GFP_KERNEL); 00963 if (!skb) { 00964 netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS); 00965 return; 00966 } 00967 if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) { 00968 kfree_skb(skb); 00969 netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL); 00970 return; 00971 } 00972 NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_IFADDR; 00973 netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV4_IFADDR, GFP_KERNEL); 00974 }

int unregister_inetaddr_notifier struct notifier_block *  nb  ) 
 

Definition at line 784 of file devinet.c.

References inetaddr_chain.

Referenced by fini().

00785 { 00786 return notifier_chain_unregister(&inetaddr_chain,nb); 00787 }


Variable Documentation

int inet_dev_count
 

Definition at line 76 of file devinet.c.

Referenced by in_dev_finish_destroy(), and inetdev_init().

int inet_ifa_count
 

Definition at line 75 of file devinet.c.

Referenced by inet_alloc_ifa(), and inet_free_ifa().

struct rtnetlink_link inet_rtnetlink_table[RTM_MAX-RTM_BASE+1] [static]
 

Definition at line 977 of file devinet.c.

Referenced by devinet_init().

struct notifier_block* inetaddr_chain [static]
 

Definition at line 68 of file devinet.c.

Referenced by inet_del_ifa(), inet_insert_ifa(), register_inetaddr_notifier(), and unregister_inetaddr_notifier().

rwlock_t inetdev_lock = RW_LOCK_UNLOCKED
 

Definition at line 80 of file devinet.c.

Referenced by fib_validate_source(), in_dev_get(), inet_dump_ifaddr(), inet_select_addr(), inetdev_destroy(), inetdev_init(), ip_route_input(), and ip_route_output_slow().

struct notifier_block ip_netdev_notifier
 

Initial value:

{ notifier_call: inetdev_event, }
Definition at line 874 of file devinet.c.

Referenced by devinet_init().

struct ipv4_devconf ipv4_devconf = { 1, 1, 1, 1, 0, }
 

Definition at line 63 of file devinet.c.

struct ipv4_devconf ipv4_devconf_dflt = { 1, 1, 1, 1, 1, } [static]
 

Definition at line 64 of file devinet.c.

Referenced by devinet_init(), and inetdev_init().


Generated on Wed Dec 1 21:25:34 2004 for Linux 2.4.23 Networking by doxygen 1.3.8