static struct net_device *ipmr_new_tunnel(struct vifctl *v) { struct net_device *dev; dev = __dev_get_by_name(&init_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(&init_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 struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) { u32 remote = parms->iph.daddr; u32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; unsigned h = 0; int prio = 0; char name[IFNAMSIZ]; if (remote) { prio |= 2; h ^= HASH(remote); } if (local) { prio |= 1; h ^= HASH(local); } for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) return t; } if (!create) return NULL; if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); else { int i; for (i=1; i<100; i++) { sprintf(name, "tunl%d", i); if (__dev_get_by_name(name) == NULL) break; } if (i==100) goto failed; } dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup); if (dev == NULL) return NULL; nt = dev->priv; SET_MODULE_OWNER(dev); dev->init = ipip_tunnel_init; nt->parms = *parms; if (register_netdevice(dev) < 0) { free_netdev(dev); goto failed; } dev_hold(dev); ipip_tunnel_link(nt); return nt; failed: return NULL; }
int register_vlan_dev(struct net_device *dev) { struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; u16 vlan_id = vlan->vlan_id; struct vlan_group *grp, *ngrp = NULL; int err; grp = rtnl_dereference(real_dev->vlgrp); if (!grp) { ngrp = grp = vlan_group_alloc(real_dev); if (!grp) return -ENOBUFS; err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_free_group; } err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) goto out_uninit_applicant; err = register_netdevice(dev); if (err < 0) goto out_uninit_applicant; /* Account for reference in struct vlan_dev_info */ dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ /* So, got the sucker initialized, now lets place * it into our local structure. */ vlan_group_set_device(grp, vlan_id, dev); grp->nr_vlans++; if (ngrp) { if (ops->ndo_vlan_rx_register) ops->ndo_vlan_rx_register(real_dev, ngrp); rcu_assign_pointer(real_dev->vlgrp, ngrp); } if (real_dev->features & NETIF_F_HW_VLAN_FILTER) ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); return 0; out_uninit_applicant: if (ngrp) vlan_gvrp_uninit_applicant(real_dev); out_free_group: if (ngrp) { /* Free the group, after all cpu's are done. */ call_rcu(&ngrp->rcu, vlan_rcu_free); } return err; }
static int pim6_rcv(struct sk_buff *skb) { struct pimreghdr *pim; struct ipv6hdr *encap; struct net_device *reg_dev = NULL; struct net *net = dev_net(skb->dev); int reg_vif_num = net->ipv6.mroute_reg_vif_num; if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) goto drop; pim = (struct pimreghdr *)skb_transport_header(skb); if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || (pim->flags & PIM_NULL_REGISTER) || (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, sizeof(*pim), IPPROTO_PIM, csum_partial((void *)pim, sizeof(*pim), 0)) && csum_fold(skb_checksum(skb, 0, skb->len, 0)))) goto drop; /* check if the inner packet is destined to mcast group */ encap = (struct ipv6hdr *)(skb_transport_header(skb) + sizeof(*pim)); if (!ipv6_addr_is_multicast(&encap->daddr) || encap->payload_len == 0 || ntohs(encap->payload_len) + sizeof(*pim) > skb->len) goto drop; read_lock(&mrt_lock); if (reg_vif_num >= 0) reg_dev = net->ipv6.vif6_table[reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); if (reg_dev == NULL) goto drop; skb->mac_header = skb->network_header; skb_pull(skb, (u8 *)encap - skb->data); skb_reset_network_header(skb); skb->dev = reg_dev; skb->protocol = htons(ETH_P_IPV6); skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; skb_dst_drop(skb); reg_dev->stats.rx_bytes += skb->len; reg_dev->stats.rx_packets++; nf_reset(skb); netif_rx(skb); dev_put(reg_dev); return 0; drop: kfree_skb(skb); return 0; }
static int ip6ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); ip6ip6_tnl_dev_init_gen(dev); dev_hold(dev); tnls_wc[0] = t; return 0; }
void __netdev_watchdog_up(struct net_device *dev) { if (dev->tx_timeout) { if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = 5*HZ; if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo)) dev_hold(dev); } }
int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) { struct net_device *dev = NULL; struct ipv6_mc_socklist *mc_lst; struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; int err; if (!(ipv6_addr_type(addr) & IPV6_ADDR_MULTICAST)) return -EINVAL; mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL); if (mc_lst == NULL) return -ENOMEM; mc_lst->next = NULL; memcpy(&mc_lst->addr, addr, sizeof(struct in6_addr)); mc_lst->ifindex = ifindex; if (ifindex == 0) { struct rt6_info *rt; rt = rt6_lookup(addr, NULL, 0, 0); if (rt) { dev = rt->rt6i_dev; dev_hold(dev); dst_release(&rt->u.dst); } } else dev = dev_get_by_index(ifindex); if (dev == NULL) { sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return -ENODEV; } /* * now add/increase the group membership on the device */ err = ipv6_dev_mc_inc(dev, addr); if (err) { sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); dev_put(dev); return err; } write_lock_bh(&ipv6_sk_mc_lock); mc_lst->next = np->ipv6_mc_list; np->ipv6_mc_list = mc_lst; write_unlock_bh(&ipv6_sk_mc_lock); dev_put(dev); return 0; }
void __netdev_watchdog_up(struct net_device *dev) { if (dev->netdev_ops->ndo_tx_timeout) { if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = 5*HZ; if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + dev->watchdog_timeo))) dev_hold(dev); } }
static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, struct ip_tunnel_parm *parms, int create) { __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; char name[IFNAMSIZ]; struct sit_net *sitn = net_generic(net, sit_net_id); for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) return t; } if (!create) goto failed; if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); else sprintf(name, "sit%%d"); dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); if (dev == NULL) return NULL; dev_net_set(dev, net); if (strchr(name, '%')) { if (dev_alloc_name(dev, name) < 0) goto failed_free; } nt = netdev_priv(dev); nt->parms = *parms; ipip6_tunnel_init(dev); ipip6_tunnel_clone_6rd(dev, sitn); if (parms->i_flags & SIT_ISATAP) dev->priv_flags |= IFF_ISATAP; if (register_netdevice(dev) < 0) goto failed_free; dev_hold(dev); ipip6_tunnel_link(sitn, nt); return nt; failed_free: free_netdev(dev); failed: return NULL; }
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo) { int err; struct dst_entry *dst; struct net_device *dev; struct xfrm_state_offload *xso = &x->xso; xfrm_address_t *saddr; xfrm_address_t *daddr; if (!x->type_offload) return -EINVAL; /* We don't yet support UDP encapsulation, TFC padding and ESN. */ if (x->encap || x->tfcpad || (x->props.flags & XFRM_STATE_ESN)) return 0; dev = dev_get_by_index(net, xuo->ifindex); if (!dev) { if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) { saddr = &x->props.saddr; daddr = &x->id.daddr; } else { saddr = &x->id.daddr; daddr = &x->props.saddr; } dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr, x->props.family, x->props.output_mark); if (IS_ERR(dst)) return 0; dev = dst->dev; dev_hold(dev); dst_release(dst); } if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_state_add) { dev_put(dev); return 0; } xso->dev = dev; xso->num_exthdrs = 1; xso->flags = xuo->flags; err = dev->xfrmdev_ops->xdo_dev_state_add(x); if (err) { dev_put(dev); return err; } return 0; }
static void ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ip6_tnl_dev_init_gen(dev); t->parms.proto = IPPROTO_IPV6; dev_hold(dev); ip6n->tnls_wc[0] = t; }
static int pim6_rcv(struct sk_buff *skb) { struct pimreghdr *pim; struct ipv6hdr *encap; struct net_device *reg_dev = NULL; if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) goto drop; pim = (struct pimreghdr *)skb_transport_header(skb); if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || (pim->flags & PIM_NULL_REGISTER) || (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && csum_fold(skb_checksum(skb, 0, skb->len, 0)))) goto drop; /* check if the inner packet is destined to mcast group */ encap = (struct ipv6hdr *)(skb_transport_header(skb) + sizeof(*pim)); if (!ipv6_addr_is_multicast(&encap->daddr) || encap->payload_len == 0 || ntohs(encap->payload_len) + sizeof(*pim) > skb->len) goto drop; read_lock(&mrt_lock); if (reg_vif_num >= 0) reg_dev = vif6_table[reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); if (reg_dev == NULL) goto drop; skb->mac_header = skb->network_header; skb_pull(skb, (u8 *)encap - skb->data); skb_reset_network_header(skb); skb->dev = reg_dev; skb->protocol = htons(ETH_P_IP); skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; dst_release(skb->dst); ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len; ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++; skb->dst = NULL; nf_reset(skb); netif_rx(skb); dev_put(reg_dev); return 0; drop: kfree_skb(skb); return 0; }
static void linkwatch_add_event(struct net_device *dev) { unsigned long flags; spin_lock_irqsave(&lweventlist_lock, flags); if (list_empty(&dev->link_watch_list)) { list_add_tail(&dev->link_watch_list, &lweventlist); dev_hold(dev); } spin_unlock_irqrestore(&lweventlist_lock, flags); }
static struct net_device *rxe_get_netdev(struct ib_device *device, u8 port_num) { struct rxe_dev *rxe = to_rdev(device); if (rxe->ndev) { dev_hold(rxe->ndev); return rxe->ndev; } return NULL; }
int register_vlan_dev(struct net_device *dev) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; u16 vlan_id = vlan->vlan_id; struct vlan_info *vlan_info; struct vlan_group *grp; int err; err = vlan_vid_add(real_dev, vlan_id); if (err) return err; vlan_info = rtnl_dereference(real_dev->vlan_info); /* vlan_info should be there now. vlan_vid_add took care of it */ BUG_ON(!vlan_info); grp = &vlan_info->grp; if (grp->nr_vlan_devs == 0) { err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_vid_del; } err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) goto out_uninit_applicant; err = register_netdevice(dev); if (err < 0) goto out_uninit_applicant; /* Account for reference in struct vlan_dev_priv */ dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ /* So, got the sucker initialized, now lets place * it into our local structure. */ vlan_group_set_device(grp, vlan_id, dev); grp->nr_vlan_devs++; return 0; out_uninit_applicant: if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); out_vid_del: vlan_vid_del(real_dev, vlan_id); return err; }
struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) { u32 remote = parms->iph.daddr; u32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) return t; } if (!create) return NULL; MOD_INC_USE_COUNT; dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL); if (dev == NULL) { MOD_DEC_USE_COUNT; return NULL; } memset(dev, 0, sizeof(*dev) + sizeof(*t)); dev->priv = (void*)(dev+1); nt = (struct ip_tunnel*)dev->priv; nt->dev = dev; dev->init = ipip6_tunnel_init; dev->features |= NETIF_F_DYNALLOC; memcpy(&nt->parms, parms, sizeof(*parms)); nt->parms.name[IFNAMSIZ-1] = '\0'; strcpy(dev->name, nt->parms.name); if (dev->name[0] == 0) { int i; for (i=1; i<100; i++) { sprintf(dev->name, "sit%d", i); if (__dev_get_by_name(dev->name) == NULL) break; } if (i==100) goto failed; memcpy(nt->parms.name, dev->name, IFNAMSIZ); } if (register_netdevice(dev) < 0) goto failed; dev_hold(dev); ipip6_tunnel_link(nt); /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: kfree(dev); MOD_DEC_USE_COUNT; return NULL; }
/* Dirty hack. We did it in 2.2 (in __dst_free), * we have _very_ good reasons not to repeat * this mistake in 2.3, but we have no choice * now. _It_ _is_ _explicit_ _deliberate_ * _race_ _condition_. * * Commented and originally written by Alexey. */ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, int unregister) { if (dst->ops->ifdown) dst->ops->ifdown(dst, dev, unregister); if (dev != dst->dev) return; if (!unregister) { dst->input = dst->output = dst_discard; } else { dst->dev = dev_net(dst->dev)->loopback_dev; dev_hold(dst->dev); dev_put(dev); if (dst->neighbour && dst->neighbour->dev == dev) { dst->neighbour->dev = dst->dev; dev_hold(dst->dev); dev_put(dev); } } }
static struct net_device *qedr_get_netdev(struct ib_device *dev, u8 port_num) { struct qedr_dev *qdev; qdev = get_qedr_dev(dev); dev_hold(qdev->ndev); /* The HW vendor's device driver must guarantee * that this function returns NULL before the net device reaches * NETDEV_UNREGISTER_FINAL state. */ return qdev->ndev; }
/* Create a child dst_entry with locked interface MTU, and attach it to `dst'. This is needed on newer linux kernels and IP_ONLY_INTERCEPTOR builds, where the IP stack fragments packets to path MTU after ssh_interceptor_send. */ static struct dst_entry * interceptor_route_create_child_dst(struct dst_entry *dst) { struct dst_entry *child; /* Allocate a dst_entry and copy relevant fields from dst. */ child = dst_alloc(dst->ops); if (child == NULL) return NULL; child->input = dst->input; child->output = dst->output; /* Child is not added to dst hash, and linux native IPsec is disabled. */ child->flags |= (DST_NOHASH | DST_NOPOLICY | DST_NOXFRM); /* Copy route metrics and lock MTU to interface MTU. */ memcpy(child->metrics, dst->metrics, sizeof(child->metrics)); child->metrics[RTAX_LOCK-1] |= 1 << RTAX_MTU; #ifdef CONFIG_NET_CLS_ROUTE child->tclassid = dst->tclassid; #endif /* CONFIG_NET_CLS_ROUTE */ child->xfrm = NULL; if (dst->hh) { atomic_inc(&dst->hh->hh_refcnt); child->hh = dst->hh; } if (dst->neighbour) { child->neighbour = neigh_clone(dst->neighbour); } if (dst->dev) { dev_hold(dst->dev); child->dev = dst->dev; } SSH_ASSERT(dst->child == NULL); dst->child = dst_clone(child); SSH_DEBUG(SSH_D_MIDOK, ("Allocated child %p dst_entry for dst %p mtu %d", child, dst, dst_mtu(dst))); return child; }
/* * sfe_cm_find_dev_and_mac_addr() * Find the device and MAC address for a given IPv4 address. * * Returns true if we find the device and MAC address, otherwise false. * * We look up the rtable entry for the address and, from its neighbour * structure, obtain the hardware address. This means this function also * works if the neighbours are routers too. */ static bool sfe_cm_find_dev_and_mac_addr(uint32_t addr, struct net_device **dev, uint8_t *mac_addr) { struct neighbour *neigh; struct rtable *rt; struct dst_entry *dst; struct net_device *mac_dev; /* * Look up the rtable entry for the IP address then get the hardware * address from its neighbour structure. This means this work when the * neighbours are routers too. */ rt = ip_route_output(&init_net, addr, 0, 0, 0); if (unlikely(IS_ERR(rt))) { return false; } dst = (struct dst_entry *)rt; rcu_read_lock(); neigh = dst_get_neighbour_noref(dst); if (unlikely(!neigh)) { rcu_read_unlock(); dst_release(dst); return false; } if (unlikely(!(neigh->nud_state & NUD_VALID))) { rcu_read_unlock(); dst_release(dst); return false; } mac_dev = neigh->dev; if (!mac_dev) { rcu_read_unlock(); dst_release(dst); return false; } memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); dev_hold(mac_dev); *dev = mac_dev; rcu_read_unlock(); dst_release(dst); return true; }
/* Some devices are known to send Neigbor Solicitation messages and * require Neigbor Advertisement replies. The IPv6 core will not * respond since IFF_NOARP is set, so we must handle them ourselves. */ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci) { struct ipv6hdr *iph = (void *)buf; struct nd_msg *msg = (void *)(iph + 1); struct net_device *netdev; struct inet6_dev *in6_dev; bool is_router; /* we'll only respond to requests from unicast addresses to * our solicited node addresses. */ if (!ipv6_addr_is_solict_mult(&iph->daddr) || !(ipv6_addr_type(&iph->saddr) & IPV6_ADDR_UNICAST)) return; /* need to send the NA on the VLAN dev, if any */ rcu_read_lock(); if (tci) { netdev = __vlan_find_dev_deep_rcu(dev->net, htons(ETH_P_8021Q), tci); if (!netdev) { rcu_read_unlock(); return; } } else { netdev = dev->net; } dev_hold(netdev); rcu_read_unlock(); in6_dev = in6_dev_get(netdev); if (!in6_dev) goto out; is_router = !!in6_dev->cnf.forwarding; in6_dev_put(in6_dev); /* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target, is_router /* router */, true /* solicited */, false /* override */, true /* inc_opt */); #else ipv6_stub->ndisc_send_na(netdev, NULL, &iph->saddr, &msg->target, is_router, true, false, true); #endif out: dev_put(netdev); }
int register_vlan_dev(struct net_device *dev) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; u16 vlan_id = vlan->vlan_id; struct vlan_info *vlan_info; struct vlan_group *grp; int err; err = vlan_vid_add(real_dev, vlan_id); if (err) return err; vlan_info = rtnl_dereference(real_dev->vlan_info); BUG_ON(!vlan_info); grp = &vlan_info->grp; if (grp->nr_vlan_devs == 0) { err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_vid_del; } err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) goto out_uninit_applicant; err = register_netdevice(dev); if (err < 0) goto out_uninit_applicant; dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); linkwatch_fire_event(dev); vlan_group_set_device(grp, vlan_id, dev); grp->nr_vlan_devs++; return 0; out_uninit_applicant: if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); out_vid_del: vlan_vid_del(real_dev, vlan_id); return err; }
static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) { struct net_dev_context *nd; unsigned long flags; spin_lock_irqsave(&list_lock, flags); nd = get_net_dev(iface); if (nd && nd->rx.linked && nd->tx.linked) dev_hold(nd->dev); else nd = NULL; spin_unlock_irqrestore(&list_lock, flags); return nd; }
static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) { __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; char name[IFNAMSIZ]; for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) return t; } if (!create) goto failed; if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); else { int i; for (i=1; i<100; i++) { sprintf(name, "sit%d", i); if (__dev_get_by_name(name) == NULL) break; } if (i==100) goto failed; } dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); if (dev == NULL) return NULL; nt = netdev_priv(dev); dev->init = ipip6_tunnel_init; nt->parms = *parms; if (register_netdevice(dev) < 0) { free_netdev(dev); goto failed; } dev_hold(dev); ipip6_tunnel_link(nt); return nt; failed: return NULL; }
/* * Find the NET/ROM device for the given callsign. */ struct net_device *nr_dev_get(ax25_address *addr) { struct net_device *dev; read_lock(&dev_base_lock); for (dev = dev_base; dev != NULL; dev = dev->next) { if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) { dev_hold(dev); goto out; } } out: read_unlock(&dev_base_lock); return dev; }
void linkwatch_fire_event(struct net_device *dev) { int urgent = linkwatch_urgent_event(dev); //当设备上有一个未决链接状态变更事件时,新事件就不需要排入队列 //此情况的侦测可以通过检查dev->state中的__LINK_STATE_LINKWATCH_PENDING标识进行。 if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) { dev_hold(dev); linkwatch_add_event(dev); } else if (!urgent) return; linkwatch_schedule_work(urgent); }
static struct ib_gid_table_entry * alloc_gid_entry(const struct ib_gid_attr *attr) { struct ib_gid_table_entry *entry; entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return NULL; kref_init(&entry->kref); memcpy(&entry->attr, attr, sizeof(*attr)); if (entry->attr.ndev) dev_hold(entry->attr.ndev); INIT_WORK(&entry->del_work, free_gid_work); entry->state = GID_TABLE_ENTRY_INVALID; return entry; }
/* some callers cannot sleep, and they can call this function, * transmitting the packets later, when interrupts are on */ static struct sk_buff * aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) { struct aoe_hdr *h; struct aoe_cfghdr *ch; struct sk_buff *skb, *sl, *sl_tail; struct net_device *ifp; sl = sl_tail = NULL; read_lock(&dev_base_lock); for_each_netdev(ifp) { dev_hold(ifp); if (!is_aoe_netif(ifp)) goto cont; skb = new_skb(sizeof *h + sizeof *ch); if (skb == NULL) { printk(KERN_INFO "aoe: skb alloc failure\n"); goto cont; } skb_put(skb, sizeof *h + sizeof *ch); skb->dev = ifp; if (sl_tail == NULL) sl_tail = skb; h = aoe_hdr(skb); memset(h, 0, sizeof *h + sizeof *ch); memset(h->dst, 0xff, sizeof h->dst); memcpy(h->src, ifp->dev_addr, sizeof h->src); h->type = __constant_cpu_to_be16(ETH_P_AOE); h->verfl = AOE_HVER; h->major = cpu_to_be16(aoemajor); h->minor = aoeminor; h->cmd = AOECMD_CFG; skb->next = sl; sl = skb; cont: dev_put(ifp); } read_unlock(&dev_base_lock); if (tail != NULL) *tail = sl_tail; return sl; }
static int __init ipip6_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; strcpy(tunnel->parms.name, dev->name); iph->version = 4; iph->protocol = IPPROTO_IPV6; iph->ihl = 5; iph->ttl = 64; dev_hold(dev); tunnels_wc[0] = tunnel; return 0; }
static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, struct ip_tunnel_parm *parms, int create) { struct ip_tunnel *t, *nt; struct net_device *dev; char name[IFNAMSIZ]; struct ipgre_net *ign = net_generic(net, ipgre_net_id); t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE); if (t || !create) return t; if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); else sprintf(name, "gre%%d"); dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup); if (!dev) return NULL; dev_net_set(dev, net); if (strchr(name, '%')) { if (dev_alloc_name(dev, name) < 0) goto failed_free; } nt = netdev_priv(dev); nt->parms = *parms; dev->rtnl_link_ops = &ipgre_link_ops; dev->mtu = ipgre_tunnel_bind_dev(dev); if (register_netdevice(dev) < 0) goto failed_free; dev_hold(dev); ipgre_tunnel_link(ign, nt); return nt; failed_free: free_netdev(dev); return NULL; }