static int ipgre_open(struct net_device *dev) { struct ip_tunnel *t = netdev_priv(dev); if (ipv4_is_multicast(t->parms.iph.daddr)) { struct flowi4 fl4; struct rtable *rt; rt = ip_route_output_gre(t->net, &fl4, t->parms.iph.daddr, t->parms.iph.saddr, t->parms.o_key, RT_TOS(t->parms.iph.tos), t->parms.link); if (IS_ERR(rt)) return -EADDRNOTAVAIL; dev = rt->dst.dev; ip_rt_put(rt); if (__in_dev_get_rtnl(dev) == NULL) return -EADDRNOTAVAIL; t->mlink = dev->ifindex; ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); } return 0; }
static int arp_req_delete(struct arpreq *r, struct net_device * dev) { int err; u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; struct neighbour *neigh; if (r->arp_flags & ATF_PUBL) { u32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; if (mask == 0xFFFFFFFF) return pneigh_delete(&arp_tbl, &ip, dev); if (mask == 0) { if (dev == NULL) { ipv4_devconf.proxy_arp = 0; return 0; } if (__in_dev_get_rtnl(dev)) { __in_dev_get_rtnl(dev)->cnf.proxy_arp = 0; return 0; } return -ENXIO; } return -EINVAL; } if (dev == NULL) { #ifndef __TCS__ struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; #else struct rtable * rt; struct flowi fl; memset(&fl,0,sizeof(fl)); fl.nl_u.ip4_u.daddr=ip; fl.nl_u.ip4_u.tos=RTO_ONLINK; #endif if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); if (!dev) return -EINVAL; } err = -ENXIO; neigh = neigh_lookup(&arp_tbl, &ip, dev); if (neigh) { if (neigh->nud_state&~NUD_NOARP) err = neigh_update(neigh, NULL, NUD_FAILED, NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_ADMIN); neigh_release(neigh); } return err; }
static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on) { if (dev == NULL) { IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; return 0; } if (__in_dev_get_rtnl(dev)) { IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on); return 0; } return -ENXIO; }
static int arp_req_delete(struct arpreq *r, struct net_device * dev) { int err; __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; struct neighbour *neigh; if (r->arp_flags & ATF_PUBL) { __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; if (mask == htonl(0xFFFFFFFF)) return pneigh_delete(&arp_tbl, &ip, dev); if (mask == 0) { if (dev == NULL) { IPV4_DEVCONF_ALL(PROXY_ARP) = 0; return 0; } if (__in_dev_get_rtnl(dev)) { IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 0); return 0; } return -ENXIO; } return -EINVAL; } if (dev == NULL) { struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); if (!dev) return -EINVAL; } err = -ENXIO; neigh = neigh_lookup(&arp_tbl, &ip, dev); if (neigh) { if (neigh->nud_state&~NUD_NOARP) err = neigh_update(neigh, NULL, NUD_FAILED, NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_ADMIN); neigh_release(neigh); } return err; }
static struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v) { struct net_device *dev; dev = __dev_get_by_name(net, "tunl0"); if (dev) { const struct net_device_ops *ops = dev->netdev_ops; int err; struct ifreq ifr; struct ip_tunnel_parm p; struct in_device *in_dev; memset(&p, 0, sizeof(p)); p.iph.daddr = v->vifc_rmt_addr.s_addr; p.iph.saddr = v->vifc_lcl_addr.s_addr; p.iph.version = 4; p.iph.ihl = 5; p.iph.protocol = IPPROTO_IPIP; sprintf(p.name, "dvmrp%d", v->vifc_vifi); ifr.ifr_ifru.ifru_data = (__force void __user *)&p; if (ops->ndo_do_ioctl) { mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS); err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL); set_fs(oldfs); } else err = -EOPNOTSUPP; dev = NULL; if (err == 0 && (dev = __dev_get_by_name(net, p.name)) != NULL) { dev->flags |= IFF_MULTICAST; in_dev = __in_dev_get_rtnl(dev); if (in_dev == NULL) goto failure; ipv4_devconf_setall(in_dev); IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0; if (dev_open(dev)) goto failure; dev_hold(dev); } } return dev; failure: /* allow the register to be completed before unregistering. */ rtnl_unlock(); rtnl_lock(); unregister_netdevice(dev); return NULL; }
static int ipgre_open(struct net_device *dev) { struct ip_tunnel *t = netdev_priv(dev); if (ipv4_is_multicast(t->parms.iph.daddr)) { struct flowi fl = { .oif = t->parms.link, .nl_u = { .ip4_u = { .daddr = t->parms.iph.daddr, .saddr = t->parms.iph.saddr, .tos = RT_TOS(t->parms.iph.tos) } }, .proto = IPPROTO_GRE }; struct rtable *rt; if (ip_route_output_key(dev_net(dev), &rt, &fl)) return -EADDRNOTAVAIL; dev = rt->u.dst.dev; ip_rt_put(rt); if (__in_dev_get_rtnl(dev) == NULL) return -EADDRNOTAVAIL; t->mlink = dev->ifindex; ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); }
static int ipctl_set_proxyarp_by_ifindex(int ifIndex, int on) { struct net *net = &init_net; struct net_device *dev; struct in_device *in_dev; dev = dev_get_by_index(net, ifIndex); if (dev) { if (__in_dev_get_rtnl(dev)) { in_dev = __in_dev_get_rtnl(dev); IN_DEV_CONF_SET(in_dev, PROXY_ARP, on); } dev_put(dev); // Release reference. } return 0; }
static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct rtattr **rta = arg; struct net_device *dev; struct in_device *in_dev; struct ifaddrmsg *ifm = NLMSG_DATA(nlh); struct in_ifaddr *ifa; int rc = -EINVAL; ASSERT_RTNL(); if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1]) goto out; rc = -ENODEV; if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) goto out; rc = -ENOBUFS; if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) { in_dev = inetdev_init(dev); if (!in_dev) goto out; } if ((ifa = inet_alloc_ifa()) == NULL) goto out; if (!rta[IFA_ADDRESS - 1]) rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4); memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4); ifa->ifa_prefixlen = ifm->ifa_prefixlen; ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); if (rta[IFA_BROADCAST - 1]) memcpy(&ifa->ifa_broadcast, RTA_DATA(rta[IFA_BROADCAST - 1]), 4); if (rta[IFA_ANYCAST - 1]) memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4); ifa->ifa_flags = ifm->ifa_flags; ifa->ifa_scope = ifm->ifa_scope; in_dev_hold(in_dev); ifa->ifa_dev = in_dev; if (rta[IFA_LABEL - 1]) rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); rc = inet_insert_ifa(ifa); out: return rc; }
static struct net_device *ipmr_new_tunnel(struct vifctl *v) { struct net_device *dev; dev = __dev_get_by_name("tunl0"); if (dev) { int err; struct ifreq ifr; mm_segment_t oldfs; struct ip_tunnel_parm p; struct in_device *in_dev; memset(&p, 0, sizeof(p)); p.iph.daddr = v->vifc_rmt_addr.s_addr; p.iph.saddr = v->vifc_lcl_addr.s_addr; p.iph.version = 4; p.iph.ihl = 5; p.iph.protocol = IPPROTO_IPIP; sprintf(p.name, "dvmrp%d", v->vifc_vifi); ifr.ifr_ifru.ifru_data = (void*)&p; oldfs = get_fs(); set_fs(KERNEL_DS); err = dev->do_ioctl(dev, &ifr, SIOCADDTUNNEL); set_fs(oldfs); dev = NULL; if (err == 0 && (dev = __dev_get_by_name(p.name)) != NULL) { dev->flags |= IFF_MULTICAST; in_dev = __in_dev_get_rtnl(dev); if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL) goto failure; in_dev->cnf.rp_filter = 0; if (dev_open(dev)) goto failure; } } return dev; failure: /* allow the register to be completed before unregistering. */ rtnl_unlock(); rtnl_lock(); unregister_netdevice(dev); return NULL; }
static int vif_delete(struct net *net, int vifi, int notify, struct list_head *head) { struct vif_device *v; struct net_device *dev; struct in_device *in_dev; if (vifi < 0 || vifi >= net->ipv4.maxvif) return -EADDRNOTAVAIL; v = &net->ipv4.vif_table[vifi]; write_lock_bh(&mrt_lock); dev = v->dev; v->dev = NULL; if (!dev) { write_unlock_bh(&mrt_lock); return -EADDRNOTAVAIL; } #ifdef CONFIG_IP_PIMSM if (vifi == net->ipv4.mroute_reg_vif_num) net->ipv4.mroute_reg_vif_num = -1; #endif if (vifi+1 == net->ipv4.maxvif) { int tmp; for (tmp=vifi-1; tmp>=0; tmp--) { if (VIF_EXISTS(net, tmp)) break; } net->ipv4.maxvif = tmp+1; } write_unlock_bh(&mrt_lock); dev_set_allmulti(dev, -1); if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--; ip_rt_multicast_event(in_dev); } if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify) unregister_netdevice_queue(dev, head); dev_put(dev); return 0; }
static int vif_delete(int vifi) { struct vif_device *v; struct net_device *dev; struct in_device *in_dev; if (vifi < 0 || vifi >= maxvif) return -EADDRNOTAVAIL; v = &vif_table[vifi]; write_lock_bh(&mrt_lock); dev = v->dev; v->dev = NULL; if (!dev) { write_unlock_bh(&mrt_lock); return -EADDRNOTAVAIL; } #ifdef CONFIG_IP_PIMSM if (vifi == reg_vif_num) reg_vif_num = -1; #endif if (vifi+1 == maxvif) { int tmp; for (tmp=vifi-1; tmp>=0; tmp--) { if (VIF_EXISTS(tmp)) break; } maxvif = tmp+1; } write_unlock_bh(&mrt_lock); dev_set_allmulti(dev, -1); if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { in_dev->cnf.mc_forwarding--; ip_rt_multicast_event(in_dev); } if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER)) unregister_netdevice(dev); dev_put(dev); return 0; }
static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) { struct in_device *in_dev = __in_dev_get_rtnl(dev); ASSERT_RTNL(); if (!in_dev) { inet_free_ifa(ifa); return -ENOBUFS; } ipv4_devconf_setall(in_dev); if (ifa->ifa_dev != in_dev) { WARN_ON(ifa->ifa_dev); in_dev_hold(in_dev); ifa->ifa_dev = in_dev; } if (ipv4_is_loopback(ifa->ifa_local)) ifa->ifa_scope = RT_SCOPE_HOST; return inet_insert_ifa(ifa); }
static int inet_gifconf(struct net_device *dev, char __user *buf, int len) { struct in_device *in_dev = __in_dev_get_rtnl(dev); struct in_ifaddr *ifa; struct ifreq ifr; int done = 0; if (!in_dev || (ifa = in_dev->ifa_list) == NULL) goto out; for (; ifa; ifa = ifa->ifa_next) { if (!buf) { done += sizeof(ifr); continue; } if (len < (int) sizeof(ifr)) break; memset(&ifr, 0, sizeof(struct ifreq)); if (ifa->ifa_label) strcpy(ifr.ifr_name, ifa->ifa_label); else strcpy(ifr.ifr_name, dev->name); (*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET; (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local; HONEYPOT_HOOK1(in_inet_gifconf, &ifr); if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) { done = -EFAULT; break; } buf += sizeof(struct ifreq); len -= sizeof(struct ifreq); done += sizeof(struct ifreq); } out: return done; }
static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) { struct in_device *in_dev = __in_dev_get_rtnl(dev); ASSERT_RTNL(); if (!in_dev) { in_dev = inetdev_init(dev); if (!in_dev) { inet_free_ifa(ifa); return -ENOBUFS; } } if (ifa->ifa_dev != in_dev) { BUG_TRAP(!ifa->ifa_dev); in_dev_hold(in_dev); ifa->ifa_dev = in_dev; } if (LOOPBACK(ifa->ifa_local)) ifa->ifa_scope = RT_SCOPE_HOST; return inet_insert_ifa(ifa); }
static int vif_add(struct vifctl *vifc, int mrtsock) { int vifi = vifc->vifc_vifi; struct vif_device *v = &vif_table[vifi]; struct net_device *dev; struct in_device *in_dev; /* Is vif busy ? */ if (VIF_EXISTS(vifi)) return -EADDRINUSE; switch (vifc->vifc_flags) { #ifdef CONFIG_IP_PIMSM case VIFF_REGISTER: /* * Special Purpose VIF in PIM * All the packets will be sent to the daemon */ if (reg_vif_num >= 0) return -EADDRINUSE; dev = ipmr_reg_vif(); if (!dev) return -ENOBUFS; break; #endif case VIFF_TUNNEL: dev = ipmr_new_tunnel(vifc); if (!dev) return -ENOBUFS; break; case 0: dev=ip_dev_find(vifc->vifc_lcl_addr.s_addr); if (!dev) return -EADDRNOTAVAIL; __dev_put(dev); break; default: return -EINVAL; } if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) return -EADDRNOTAVAIL; in_dev->cnf.mc_forwarding++; dev_set_allmulti(dev, +1); ip_rt_multicast_event(in_dev); /* * Fill in the VIF structures */ v->rate_limit=vifc->vifc_rate_limit; v->local=vifc->vifc_lcl_addr.s_addr; v->remote=vifc->vifc_rmt_addr.s_addr; v->flags=vifc->vifc_flags; if (!mrtsock) v->flags |= VIFF_STATIC; v->threshold=vifc->vifc_threshold; v->bytes_in = 0; v->bytes_out = 0; v->pkt_in = 0; v->pkt_out = 0; v->link = dev->ifindex; if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER)) v->link = dev->iflink; /* And finish update writing critical data */ write_lock_bh(&mrt_lock); dev_hold(dev); v->dev=dev; #ifdef CONFIG_IP_PIMSM if (v->flags&VIFF_REGISTER) reg_vif_num = vifi; #endif if (vifi+1 > maxvif) maxvif = vifi+1; write_unlock_bh(&mrt_lock); return 0; }
int rst_restore_ifaddr(struct cpt_context *ctx) { struct net *net = get_exec_env()->ve_netns; int err; loff_t sec = ctx->sections[CPT_SECT_NET_IFADDR]; loff_t endsec; struct cpt_section_hdr h; struct cpt_ifaddr_image di; struct net_device *dev; if (sec == CPT_NULL) return 0; err = ctx->pread(&h, sizeof(h), ctx, sec); if (err) return err; if (h.cpt_section != CPT_SECT_NET_IFADDR || h.cpt_hdrlen < sizeof(h)) return -EINVAL; endsec = sec + h.cpt_next; sec += h.cpt_hdrlen; while (sec < endsec) { int cindex = -1; int err; err = rst_get_object(CPT_OBJ_NET_IFADDR, sec, &di, ctx); if (err) return err; cindex = di.cpt_index; rtnl_lock(); dev = __dev_get_by_index(net, cindex); if (dev && di.cpt_family == AF_INET) { struct in_device *in_dev; struct in_ifaddr *ifa; if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) in_dev = inetdev_init(dev); ifa = inet_alloc_ifa(); if (ifa) { ifa->ifa_local = di.cpt_address[0]; ifa->ifa_address = di.cpt_peer[0]; ifa->ifa_broadcast = di.cpt_broadcast[0]; ifa->ifa_prefixlen = di.cpt_masklen; ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen); ifa->ifa_flags = di.cpt_flags; ifa->ifa_scope = di.cpt_scope; memcpy(ifa->ifa_label, di.cpt_label, IFNAMSIZ); in_dev_hold(in_dev); ifa->ifa_dev = in_dev; err = inet_insert_ifa(ifa); if (err && err != -EEXIST) { rtnl_unlock(); eprintk_ctx("add ifaddr err %d for %d %s\n", err, di.cpt_index, di.cpt_label); return err; } } #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) } else if (dev && di.cpt_family == AF_INET6) { __u32 prefered_lft; __u32 valid_lft; struct net *net = get_exec_env()->ve_ns->net_ns; prefered_lft = (di.cpt_flags & IFA_F_DEPRECATED) ? 0 : di.cpt_prefered_lft; valid_lft = (di.cpt_flags & IFA_F_PERMANENT) ? 0xFFFFFFFF : di.cpt_valid_lft; err = inet6_addr_add(net, dev->ifindex, (struct in6_addr *)di.cpt_address, di.cpt_masklen, 0, prefered_lft, valid_lft); if (err && err != -EEXIST) { rtnl_unlock(); eprintk_ctx("add ifaddr err %d for %d %s\n", err, di.cpt_index, di.cpt_label); return err; } #endif } else { rtnl_unlock(); eprintk_ctx("unknown ifaddr 2 for %d\n", di.cpt_index); return -EINVAL; } rtnl_unlock(); sec += di.cpt_next; } return 0; }
static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) { int vifi = vifc->vifc_vifi; struct vif_device *v = &net->ipv4.vif_table[vifi]; struct net_device *dev; struct in_device *in_dev; int err; /* Is vif busy ? */ if (VIF_EXISTS(net, vifi)) return -EADDRINUSE; switch (vifc->vifc_flags) { #ifdef CONFIG_IP_PIMSM case VIFF_REGISTER: /* * Special Purpose VIF in PIM * All the packets will be sent to the daemon */ if (net->ipv4.mroute_reg_vif_num >= 0) return -EADDRINUSE; dev = ipmr_reg_vif(net); if (!dev) return -ENOBUFS; err = dev_set_allmulti(dev, 1); if (err) { unregister_netdevice(dev); dev_put(dev); return err; } break; #endif case VIFF_TUNNEL: dev = ipmr_new_tunnel(net, vifc); if (!dev) return -ENOBUFS; err = dev_set_allmulti(dev, 1); if (err) { ipmr_del_tunnel(dev, vifc); dev_put(dev); return err; } break; case VIFF_USE_IFINDEX: case 0: if (vifc->vifc_flags == VIFF_USE_IFINDEX) { dev = dev_get_by_index(net, vifc->vifc_lcl_ifindex); if (dev && dev->ip_ptr == NULL) { dev_put(dev); return -EADDRNOTAVAIL; } } else dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr); if (!dev) return -EADDRNOTAVAIL; err = dev_set_allmulti(dev, 1); if (err) { dev_put(dev); return err; } break; default: return -EINVAL; } if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) { dev_put(dev); return -EADDRNOTAVAIL; } IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++; ip_rt_multicast_event(in_dev); /* * Fill in the VIF structures */ v->rate_limit = vifc->vifc_rate_limit; v->local = vifc->vifc_lcl_addr.s_addr; v->remote = vifc->vifc_rmt_addr.s_addr; v->flags = vifc->vifc_flags; if (!mrtsock) v->flags |= VIFF_STATIC; v->threshold = vifc->vifc_threshold; v->bytes_in = 0; v->bytes_out = 0; v->pkt_in = 0; v->pkt_out = 0; v->link = dev->ifindex; if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER)) v->link = dev->iflink; /* And finish update writing critical data */ write_lock_bh(&mrt_lock); v->dev = dev; #ifdef CONFIG_IP_PIMSM if (v->flags&VIFF_REGISTER) net->ipv4.mroute_reg_vif_num = vifi; #endif if (vifi+1 > net->ipv4.maxvif) net->ipv4.maxvif = vifi+1; write_unlock_bh(&mrt_lock); return 0; }
fhgfs_bool __NIC_fillNicAddress(struct net_device* dev, NicAddrType_t nicType, NicAddress* outAddr) { struct ifreq ifr; struct in_device* in_dev; struct in_ifaddr *ifa; // name strcpy(outAddr->name, dev->name); // SIOCGIFFLAGS: // get interface flags ifr.ifr_flags = dev_get_flags(dev); if(ifr.ifr_flags & IFF_LOOPBACK) return fhgfs_false; // loopback interface => skip if(!dev->dev_addr) { // should probably never happen printk_fhgfs(KERN_NOTICE, "found interface without dev_addr: %s\n", dev->name); return fhgfs_false; } // SIOCGIFHWADDR: // get hardware address (MAC) if(!dev->addr_len || !dev->dev_addr) memset(ifr.ifr_hwaddr.sa_data, 0, sizeof(ifr.ifr_hwaddr.sa_data) ); else memcpy(ifr.ifr_hwaddr.sa_data, dev->dev_addr, min(sizeof(ifr.ifr_hwaddr.sa_data), (size_t) dev->addr_len) ); ifr.ifr_hwaddr.sa_family = dev->type; // select which hardware types to process // (on Linux see /usr/include/linux/if_arp.h for the whole list) switch(ifr.ifr_hwaddr.sa_family) { case ARPHRD_LOOPBACK: return fhgfs_false; default: { // make sure we allow SDP for IB only (because an SDP socket domain is valid for other // NIC types as well, but cannot connect between different NIC types if( (nicType == NICADDRTYPE_SDP) && (ifr.ifr_hwaddr.sa_family != ARPHRD_INFINIBAND) ) return fhgfs_false; } break; } // copy nicType outAddr->nicType = nicType; // copy hardware address memcpy(&outAddr->hwAddr, &ifr.ifr_addr.sa_data, IFHWADDRLEN); // ip address // note: based on inet_gifconf in /net/ipv4/devinet.c in_dev = __in_dev_get_rtnl(dev); if(!in_dev) { printk_fhgfs_debug(KERN_NOTICE, "found interface without in_dev: %s\n", dev->name); return fhgfs_false; } ifa = in_dev->ifa_list; if(!ifa) { printk_fhgfs_debug(KERN_NOTICE, "found interface without ifa_list: %s\n", dev->name); return fhgfs_false; } outAddr->ipAddr = ifa->ifa_local; // ip address outAddr->broadcastAddr = ifa->ifa_broadcast; // broadcast address // code to read multiple addresses /* for (; ifa; ifa = ifa->ifa_next) { (*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET; (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local; } */ // SIOCGIFMETRIC: // Get the metric of the interface (currently not supported by the kernel) ifr.ifr_metric = 0; outAddr->metric = ifr.ifr_metric; return fhgfs_true; }
static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh) { struct nlattr *tb[IFA_MAX+1]; struct in_ifaddr *ifa; struct ifaddrmsg *ifm; struct net_device *dev; struct in_device *in_dev; int err; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); if (err < 0) goto errout; ifm = nlmsg_data(nlh); err = -EINVAL; if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) goto errout; dev = __dev_get_by_index(net, ifm->ifa_index); err = -ENODEV; if (dev == NULL) goto errout; in_dev = __in_dev_get_rtnl(dev); err = -ENOBUFS; if (in_dev == NULL) goto errout; ifa = inet_alloc_ifa(); if (ifa == NULL) /* * A potential indev allocation can be left alive, it stays * assigned to its device and is destroy with it. */ goto errout; ipv4_devconf_setall(in_dev); in_dev_hold(in_dev); if (tb[IFA_ADDRESS] == NULL) tb[IFA_ADDRESS] = tb[IFA_LOCAL]; ifa->ifa_prefixlen = ifm->ifa_prefixlen; ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); ifa->ifa_flags = ifm->ifa_flags; ifa->ifa_scope = ifm->ifa_scope; ifa->ifa_dev = in_dev; ifa->ifa_local = nla_get_be32(tb[IFA_LOCAL]); ifa->ifa_address = nla_get_be32(tb[IFA_ADDRESS]); if (tb[IFA_BROADCAST]) ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]); if (tb[IFA_LABEL]) nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); return ifa; errout: return ERR_PTR(err); }
static int ieee80211_ifa_changed(struct notifier_block *nb, unsigned long data, void *arg) { struct in_ifaddr *ifa = arg; struct ieee80211_local *local = container_of(nb, struct ieee80211_local, ifa_notifier); struct net_device *ndev = ifa->ifa_dev->dev; struct wireless_dev *wdev = ndev->ieee80211_ptr; struct in_device *idev; struct ieee80211_sub_if_data *sdata; struct ieee80211_bss_conf *bss_conf; struct ieee80211_if_managed *ifmgd; int c = 0; /* Make sure it's our interface that got changed */ if (!wdev) return NOTIFY_DONE; if (wdev->wiphy != local->hw.wiphy) return NOTIFY_DONE; sdata = IEEE80211_DEV_TO_SUB_IF(ndev); bss_conf = &sdata->vif.bss_conf; if (!ieee80211_sdata_running(sdata)) return NOTIFY_DONE; /* ARP filtering is only supported in managed mode */ if (sdata->vif.type != NL80211_IFTYPE_STATION) return NOTIFY_DONE; idev = __in_dev_get_rtnl(sdata->dev); if (!idev) return NOTIFY_DONE; ifmgd = &sdata->u.mgd; mutex_lock(&ifmgd->mtx); /* Copy the addresses to the bss_conf list */ ifa = idev->ifa_list; while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) { bss_conf->arp_addr_list[c] = ifa->ifa_address; ifa = ifa->ifa_next; c++; } /* If not all addresses fit the list, disable filtering */ if (ifa) { sdata->arp_filter_state = false; c = 0; } else { sdata->arp_filter_state = true; } bss_conf->arp_addr_cnt = c; /* Configure driver only if associated */ if (ifmgd->associated) { bss_conf->arp_filter_enabled = sdata->arp_filter_state; ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_ARP_FILTER); } mutex_unlock(&ifmgd->mtx); return NOTIFY_DONE; }
static int netdev_callback(struct notifier_block *self, unsigned long event, void *ctx) { struct net_device *dev; struct net_device *dev_n = netdev_notifier_info_to_dev(ctx); struct in_device *in_dev; char *lo_if = "lo"; switch (event) { case NETDEV_UP: case NETDEV_CHANGE: case NETDEV_CHANGEADDR: case NETDEV_NOTIFY_PEERS: in_dev = __in_dev_get_rtnl(dev_n); if (!in_dev) { printk(KERN_INFO "not in dev, skip\n"); break; } if (dev_n->operstate == IF_OPER_UP) { msleep( garp_delay ); if (debug == 1) printk(KERN_INFO "send gratuitous arp from [%s]\n", dev_n->name); inetdev_send_gratuitous_arp(dev_n, in_dev); } if (send_all == 1) { if ( strcmp(dev_n->name, lo_if) == 0){ if (debug == 1) printk(KERN_INFO "notification from lo, skip\n"); break; } dev = first_net_device(&init_net); read_lock(&dev_base_lock); while (dev) { if (debug == 1) printk(KERN_INFO "found [%s], notification from [%s]\n", dev->name, dev_n->name); if (dev->operstate == IF_OPER_UP) { if (debug == 1) printk(KERN_INFO "[%s] type [%d] state [%d] is up\n", dev->name, dev->type, dev->operstate); } else { if (debug == 1) printk(KERN_INFO "[%s] type [%d] state [%d] unknown oper state\n", dev->name, dev->type, dev->operstate); } if (strcmp(dev->name, lo_if) == 0){ if (debug == 1) printk(KERN_INFO "skip lo\n"); dev = next_net_device(dev); continue; } in_dev = __in_dev_get_rtnl(dev); if (!in_dev) { if (debug == 1) printk(KERN_INFO "not in dev\n"); dev = next_net_device(dev); continue; } if (dev->operstate == IF_OPER_UP) { inetdev_send_gratuitous_arp(dev, in_dev); } dev = next_net_device(dev); } read_unlock(&dev_base_lock); } break; } if (debug == 1) { switch (event) { case NETDEV_UP: printk(KERN_INFO "got NETDEV_UP\n"); break; case NETDEV_DOWN: printk(KERN_INFO "got NETDEV_DOWN\n"); break; case NETDEV_REBOOT: printk(KERN_INFO "got NETDEV_REBOOT\n"); break; case NETDEV_CHANGE: printk(KERN_INFO "got NETDEV_CHANGE\n"); break; case NETDEV_REGISTER: printk(KERN_INFO "got NETDEV_REGISTER\n"); break; case NETDEV_UNREGISTER: printk(KERN_INFO "got NETDEV_UNREGISTER\n"); break; case NETDEV_CHANGEMTU: printk(KERN_INFO "got NETDEV_CHANGEMTU\n"); break; case NETDEV_CHANGEADDR: printk(KERN_INFO "got NETDEV_CHANGEADDR\n"); break; case NETDEV_GOING_DOWN: printk(KERN_INFO "got NETDEV_GOING_DOWN\n"); break; case NETDEV_CHANGENAME: printk(KERN_INFO "got NETDEV_CHANGENAME\n"); break; case NETDEV_FEAT_CHANGE: printk(KERN_INFO "got NETDEV_FEAT_CHANGE\n"); break; case NETDEV_BONDING_FAILOVER: printk(KERN_INFO "got NETDEV_BONDING_FAILOVER\n"); break; case NETDEV_PRE_UP: printk(KERN_INFO "got NETDEV_PRE_UP\n"); break; case NETDEV_PRE_TYPE_CHANGE: printk(KERN_INFO "got NETDEV_PRE_TYPE_CHANGE\n"); break; case NETDEV_POST_TYPE_CHANGE: printk(KERN_INFO "got NETDEV_POST_TYPE_CHANGE\n"); break; case NETDEV_POST_INIT: printk(KERN_INFO "got NETDEV_POST_INIT\n"); break; case NETDEV_UNREGISTER_FINAL: printk(KERN_INFO "got NETDEV_UNREGISTER_FINAL\n"); break; case NETDEV_RELEASE: printk(KERN_INFO "got NETDEV_RELEASE\n"); break; case NETDEV_NOTIFY_PEERS: printk(KERN_INFO "got NETDEV_NOTIFY_PEERS\n"); break; case NETDEV_JOIN: printk(KERN_INFO "got NETDEV_JOIN\n"); break; #ifdef NETDEV_PRECHANGEMTU case NETDEV_CHANGEUPPER: printk(KERN_INFO "got NETDEV_CHANGEUPPER\n"); break; case NETDEV_RESEND_IGMP: printk(KERN_INFO "got NETDEV_RESEND_IGMP\n"); break; case NETDEV_PRECHANGEMTU: printk(KERN_INFO "got NETDEV_PRECHANGEMTU\n"); break; #endif #ifdef NETDEV_CHANGEINFODATA case NETDEV_CHANGEINFODATA: printk(KERN_INFO "got NETDEV_CHANGEINFODATA\n"); break; #endif default: printk(KERN_INFO "got unknown NETDEV event\n"); } } return 0; }
static int arp_req_set(struct arpreq *r, struct net_device * dev) { u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; struct neighbour *neigh; int err; if (r->arp_flags&ATF_PUBL) { u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr; if (mask && mask != 0xFFFFFFFF) return -EINVAL; if (!dev && (r->arp_flags & ATF_COM)) { dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data); if (!dev) return -ENODEV; } if (mask) { if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL) return -ENOBUFS; return 0; } if (dev == NULL) { ipv4_devconf.proxy_arp = 1; return 0; } if (__in_dev_get_rtnl(dev)) { __in_dev_get_rtnl(dev)->cnf.proxy_arp = 1; return 0; } return -ENXIO; } if (r->arp_flags & ATF_PERM) r->arp_flags |= ATF_COM; if (dev == NULL) { struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); if (!dev) return -EINVAL; } switch (dev->type) { #ifdef CONFIG_FDDI case ARPHRD_FDDI: /* * According to RFC 1390, FDDI devices should accept ARP * hardware types of 1 (Ethernet). However, to be more * robust, we'll accept hardware types of either 1 (Ethernet) * or 6 (IEEE 802.2). */ if (r->arp_ha.sa_family != ARPHRD_FDDI && r->arp_ha.sa_family != ARPHRD_ETHER && r->arp_ha.sa_family != ARPHRD_IEEE802) return -EINVAL; break; #endif default: if (r->arp_ha.sa_family != dev->type) return -EINVAL; break; } neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev); err = PTR_ERR(neigh); if (!IS_ERR(neigh)) { unsigned state = NUD_STALE; if (r->arp_flags & ATF_PERM) state = NUD_PERMANENT; err = neigh_update(neigh, (r->arp_flags&ATF_COM) ? r->arp_ha.sa_data : NULL, state, NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_ADMIN); neigh_release(neigh); } return err; }
static void ar6000_wow_suspend(AR_SOFTC_T *ar) { #define WOW_LIST_ID 1 if (ar->arNetworkType != AP_NETWORK) { /* Setup WoW for unicast & Arp request for our own IP disable background scan. Set listen interval into 1000 TUs Enable keepliave for 110 seconds */ struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; struct in_device *in_dev; A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; A_STATUS status; WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } }; WMI_DEL_WOW_PATTERN_CMD delWowCmd; WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE}; WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = TRUE, .hostReqDelay = 500 };/*500 ms delay*/ if (ar->arWowState!= WLAN_WOW_STATE_NONE) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n")); return; } ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/ #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A_OK) { } #endif #if WOW_SET_SCAN_PARAMS status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0); #endif /* clear up our WoW pattern first */ delWowCmd.filter_list_id = WOW_LIST_ID; delWowCmd.filter_id = 0; wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd); /* setup unicast packet pattern for WoW */ if (ar->arNetDev->dev_addr[1]) { addWowCmd.filter_list_id = WOW_LIST_ID; addWowCmd.filter_size = 6; /* MAC address */ addWowCmd.filter_offset = 0; status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n")); } } /* setup ARP request for our own IP */ if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) { break; /* found */ } } } if (ifa && ifa->ifa_local) { WMI_SET_IP_CMD ipCmd; memset(&ipCmd, 0, sizeof(ipCmd)); ipCmd.ips[0] = ifa->ifa_local; status = wmi_set_ip_cmd(ar->arWmi, &ipCmd); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n")); } } #ifndef ATH6K_CONFIG_OTA_MODE wmi_powermode_cmd(ar->arWmi, REC_POWER); #endif status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n")); } ar6k_send_asleep_event_to_app(ar, TRUE); status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n")); } ar->arWowState = WLAN_WOW_STATE_SUSPENDING; if (ar->arTxPending[ar->arControlEp]) { A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent, ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); if (!timeleft || signal_pending(current)) { /* what can I do? wow resume at once */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp])); } } status = hifWaitForPendingRecv(ar->arHifDevice); ar->arWowState = WLAN_WOW_STATE_SUSPENDED; ar->arWlanPowerState = WLAN_POWER_STATE_WOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n")); } }
int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) { struct ifreq ifr; struct sockaddr_in sin_orig; struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; struct in_device *in_dev; struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; struct net_device *dev; char *colon; int ret = -EFAULT; int tryaddrmatch = 0; /* * Fetch the caller's info block into kernel space */ if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) goto out; ifr.ifr_name[IFNAMSIZ - 1] = 0; /* save original address for comparison */ memcpy(&sin_orig, sin, sizeof(*sin)); colon = strchr(ifr.ifr_name, ':'); if (colon) *colon = 0; dev_load(net, ifr.ifr_name); switch (cmd) { case SIOCGIFADDR: /* Get interface address */ case SIOCGIFBRDADDR: /* Get the broadcast address */ case SIOCGIFDSTADDR: /* Get the destination address */ case SIOCGIFNETMASK: /* Get the netmask for the interface */ /* Note that these ioctls will not sleep, so that we do not impose a lock. One day we will be forced to put shlock here (I mean SMP) */ tryaddrmatch = (sin_orig.sin_family == AF_INET); memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; break; case SIOCSIFFLAGS: ret = -EACCES; if (!capable(CAP_NET_ADMIN)) goto out; break; case SIOCSIFADDR: /* Set interface address (and family) */ case SIOCSIFBRDADDR: /* Set the broadcast address */ case SIOCSIFDSTADDR: /* Set the destination address */ case SIOCSIFNETMASK: /* Set the netmask for the interface */ case SIOCKILLADDR: /* Nuke all sockets on this address */ ret = -EACCES; if (!capable(CAP_NET_ADMIN)) goto out; ret = -EINVAL; if (sin->sin_family != AF_INET) goto out; break; default: ret = -EINVAL; goto out; } rtnl_lock(); ret = -ENODEV; dev = __dev_get_by_name(net, ifr.ifr_name); if (!dev) goto done; if (colon) *colon = ':'; in_dev = __in_dev_get_rtnl(dev); if (in_dev) { if (tryaddrmatch) { /* Matthias Andree */ /* compare label and address (4.4BSD style) */ /* note: we only do this for a limited set of ioctls and only if the original address family was AF_INET. This is checked above. */ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(ifr.ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == ifa->ifa_address) { break; /* found */ } } } /* we didn't get a match, maybe the application is 4.3BSD-style and passed in junk so we fall back to comparing just the label */ if (!ifa) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) if (!strcmp(ifr.ifr_name, ifa->ifa_label)) break; } } ret = -EADDRNOTAVAIL; if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS && cmd != SIOCKILLADDR) goto done; switch (cmd) { case SIOCGIFADDR: /* Get interface address */ sin->sin_addr.s_addr = ifa->ifa_local; goto rarok; case SIOCGIFBRDADDR: /* Get the broadcast address */ sin->sin_addr.s_addr = ifa->ifa_broadcast; goto rarok; case SIOCGIFDSTADDR: /* Get the destination address */ sin->sin_addr.s_addr = ifa->ifa_address; goto rarok; case SIOCGIFNETMASK: /* Get the netmask for the interface */ sin->sin_addr.s_addr = ifa->ifa_mask; goto rarok; case SIOCSIFFLAGS: if (colon) { ret = -EADDRNOTAVAIL; if (!ifa) break; ret = 0; if (!(ifr.ifr_flags & IFF_UP)) inet_del_ifa(in_dev, ifap, 1); break; } ret = dev_change_flags(dev, ifr.ifr_flags); break; case SIOCSIFADDR: /* Set interface address (and family) */ ret = -EINVAL; if (inet_abc_len(sin->sin_addr.s_addr) < 0) break; if (!ifa) { ret = -ENOBUFS; ifa = inet_alloc_ifa(); if (!ifa) break; if (colon) memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); } else { ret = 0; if (ifa->ifa_local == sin->sin_addr.s_addr) break; inet_del_ifa(in_dev, ifap, 0); ifa->ifa_broadcast = 0; ifa->ifa_scope = 0; } ifa->ifa_address = ifa->ifa_local = sin->sin_addr.s_addr; if (!(dev->flags & IFF_POINTOPOINT)) { ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address); ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen); if ((dev->flags & IFF_BROADCAST) && ifa->ifa_prefixlen < 31) ifa->ifa_broadcast = ifa->ifa_address | ~ifa->ifa_mask; } else { ifa->ifa_prefixlen = 32; ifa->ifa_mask = inet_make_mask(32); } ret = inet_set_ifa(dev, ifa); break; case SIOCSIFBRDADDR: /* Set the broadcast address */ ret = 0; if (ifa->ifa_broadcast != sin->sin_addr.s_addr) { inet_del_ifa(in_dev, ifap, 0); ifa->ifa_broadcast = sin->sin_addr.s_addr; inet_insert_ifa(ifa); } break; case SIOCSIFDSTADDR: /* Set the destination address */ ret = 0; if (ifa->ifa_address == sin->sin_addr.s_addr) break; ret = -EINVAL; if (inet_abc_len(sin->sin_addr.s_addr) < 0) break; ret = 0; inet_del_ifa(in_dev, ifap, 0); ifa->ifa_address = sin->sin_addr.s_addr; inet_insert_ifa(ifa); break; case SIOCSIFNETMASK: /* Set the netmask for the interface */ /* * The mask we set must be legal. */ ret = -EINVAL; if (bad_mask(sin->sin_addr.s_addr, 0)) break; ret = 0; if (ifa->ifa_mask != sin->sin_addr.s_addr) { __be32 old_mask = ifa->ifa_mask; inet_del_ifa(in_dev, ifap, 0); ifa->ifa_mask = sin->sin_addr.s_addr; ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); /* See if current broadcast address matches * with current netmask, then recalculate * the broadcast address. Otherwise it's a * funny address, so don't touch it since * the user seems to know what (s)he's doing... */ if ((dev->flags & IFF_BROADCAST) && (ifa->ifa_prefixlen < 31) && (ifa->ifa_broadcast == (ifa->ifa_local|~old_mask))) { ifa->ifa_broadcast = (ifa->ifa_local | ~sin->sin_addr.s_addr); } inet_insert_ifa(ifa); } break; case SIOCKILLADDR: /* Nuke all connections on this address */ ret = 0; tcp_v4_nuke_addr(sin->sin_addr.s_addr); break; } done: rtnl_unlock(); out: return ret; rarok: rtnl_unlock(); ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0; goto out; }
rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); } } static inline bool inetdev_valid_mtu(unsigned mtu) { return mtu >= 68; } /* Called only under RTNL semaphore */ static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = ptr; struct in_device *in_dev = __in_dev_get_rtnl(dev); ASSERT_RTNL(); if (!in_dev) { if (event == NETDEV_REGISTER) { in_dev = inetdev_init(dev); if (!in_dev) return notifier_from_errno(-ENOMEM); if (dev->flags & IFF_LOOPBACK) { IN_DEV_CONF_SET(in_dev, NOXFRM, 1); IN_DEV_CONF_SET(in_dev, NOPOLICY, 1); } } else if (event == NETDEV_CHANGEMTU) { /* Re-enabling IP */ if (inetdev_valid_mtu(dev->mtu))