static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
{
	struct ip6_tnl_parm *p = &t->parms;
	int ret = 0;

	if (p->flags & IP6_TNL_F_CAP_XMIT) {
		struct net_device *ldev = NULL;

		if (p->link)
			ldev = dev_get_by_index(p->link);

		if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0)))
			printk(KERN_WARNING
			       "%s xmit: Local address not yet configured!\n",
			       p->name);
		else if (!ipv6_addr_is_multicast(&p->raddr) &&
			 unlikely(ipv6_chk_addr(&p->raddr, NULL, 0)))
			printk(KERN_WARNING
			       "%s xmit: Routing loop! "
			       "Remote address found on this node!\n",
			       p->name);
		else
			ret = 1;
		if (ldev)
			dev_put(ldev);
	}
	return ret;
}
Пример #2
0
static int ipip_tunnel_init(struct device *dev)
{
	struct device *tdev = NULL;
	struct ip_tunnel *tunnel;
	struct iphdr *iph;

	tunnel = (struct ip_tunnel*)dev->priv;
	iph = &tunnel->parms.iph;

	ipip_tunnel_init_gen(dev);

	if (iph->daddr) {
		struct rtable *rt;
		if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) {
			tdev = rt->u.dst.dev;
			ip_rt_put(rt);
		}
		dev->flags |= IFF_POINTOPOINT;
	}

	if (!tdev && tunnel->parms.link)
		tdev = dev_get_by_index(tunnel->parms.link);

	if (tdev) {
		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
		dev->mtu = tdev->mtu - sizeof(struct iphdr);
	}
	dev->iflink = tunnel->parms.link;

	return 0;
}
Пример #3
0
static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
{
    struct inet6_ifaddr *ifp;
    struct inet6_dev *idev;
    struct device *dev;
    int scope;

    if ((dev = dev_get_by_index(ifindex)) == NULL)
        return -ENODEV;

    if ((idev = ipv6_get_idev(dev)) == NULL)
        return -ENXIO;

    scope = ipv6_addr_scope(pfx);

    for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) {
        if (ifp->scope == scope && ifp->prefix_len == plen &&
                (!memcmp(pfx, &ifp->addr, sizeof(struct in6_addr)))) {
            ipv6_del_addr(ifp);

            /* If the last address is deleted administratively,
               disable IPv6 on this interface.
             */

            if (idev->addr_list == NULL)
                addrconf_ifdown(idev->dev, 1);
            return 0;
        }
    }
    return -EADDRNOTAVAIL;
}
Пример #4
0
static void ip6_frag_expire(unsigned long data)
{
	struct frag_queue *fq = (struct frag_queue *) data;

	spin_lock(&fq->lock);

	if (fq->last_in & COMPLETE)
		goto out;

	fq_kill(fq);

	IP6_INC_STATS_BH(Ip6ReasmTimeout);
	IP6_INC_STATS_BH(Ip6ReasmFails);

	/* Send error only if the first segment arrived. */
	if (fq->last_in&FIRST_IN && fq->fragments) {
		struct net_device *dev = dev_get_by_index(fq->iif);

		/*
		   But use as source device on which LAST ARRIVED
		   segment was received. And do not use fq->dev
		   pointer directly, device might already disappeared.
		 */
		if (dev) {
			fq->fragments->dev = dev;
			icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
				    dev);
			dev_put(dev);
		}
	}
out:
	spin_unlock(&fq->lock);
	fq_put(fq);
}
Пример #5
0
/*
 *	Manual configuration of address on an interface
 */
static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
{
    struct inet6_ifaddr *ifp;
    struct inet6_dev *idev;
    struct device *dev;
    int scope;

    if ((dev = dev_get_by_index(ifindex)) == NULL)
        return -ENODEV;

    if (!(dev->flags&IFF_UP))
        return -ENETDOWN;

    if ((idev = addrconf_add_dev(dev)) == NULL)
        return -ENOBUFS;

    scope = ipv6_addr_scope(pfx);

    if ((ifp = ipv6_add_addr(idev, pfx, scope)) == NULL)
        return -ENOMEM;

    ifp->prefix_len = plen;
    ifp->flags |= ADDR_PERMANENT;

    addrconf_dad_start(ifp);
    return 0;
}
Пример #6
0
static inline
bool copy_to_dev_skbs(struct pfq_sock *so, struct gc_queue_buff *queue, unsigned long long mask, int cpu, int gid)
{
	if (so->egress_index) {

		struct net_device *dev;
		bool ret;

               	dev = dev_get_by_index(&init_net, so->egress_index);

               	if (dev == NULL)
		{
			if (printk_ratelimit()) {
                        	printk(KERN_INFO "[PFQ] egress endpoint index (%d)\n", so->egress_index);
                        	return false;
			}
		}

 		ret = pfq_lazy_queue_xmit_by_mask(queue, mask, dev, so->egress_queue);

                dev_put(dev);

		return ret != 0;
	}

	return false;
}
Пример #7
0
static int raw_release(struct socket *sock)
{
	struct sock *sk = sock->sk;
	struct raw_opt *ro = raw_sk(sk);
	struct net_device *dev = NULL;

	DBG("socket %p, sk %p, refcnt %d\n", sock, sk,
	    atomic_read(&sk->sk_refcnt));

	if (ro->bound && ro->ifindex)
		dev = dev_get_by_index(ro->ifindex);

	/* remove current filters & unregister */
	if (ro->bound)
		raw_remove_filters(dev, sk);

	if (ro->count > 1)
		kfree(ro->filter);

	/* remove current error mask */
	if (ro->err_mask && ro->bound)
		can_rx_unregister(dev, 0, ro->err_mask | CAN_ERR_FLAG,
				  raw_rcv, sk);

	if (dev) {
		can_dev_unregister(dev, raw_notifier, sk);
		dev_put(dev);
	}

	sock_put(sk);

	return 0;
}
Пример #8
0
static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq)
{
	struct packet_mclist *ml, **mlp;

	rtnl_lock();

	for (mlp = &pkt_sk(sk)->mclist; (ml = *mlp) != NULL; mlp = &ml->next) {
		if (ml->ifindex == mreq->mr_ifindex &&
		    ml->type == mreq->mr_type &&
		    ml->alen == mreq->mr_alen &&
		    memcmp(ml->addr, mreq->mr_address, ml->alen) == 0) {
			if (--ml->count == 0) {
				struct net_device *dev;
				*mlp = ml->next;
				dev = dev_get_by_index(ml->ifindex);
				if (dev) {
					packet_dev_mc(dev, ml, -1);
					dev_put(dev);
				}
				kfree(ml);
			}
			rtnl_unlock();
			return 0;
		}
	}
	rtnl_unlock();
	return -EADDRNOTAVAIL;
}
Пример #9
0
static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
			  int *uaddr_len, int peer)
{
	struct net_device *dev;
	struct sock *sk = sock->sk;
	struct packet_sock *po = pkt_sk(sk);
	struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;

	if (peer)
		return -EOPNOTSUPP;

	sll->sll_family = AF_PACKET;
	sll->sll_ifindex = po->ifindex;
	sll->sll_protocol = po->num;
	dev = dev_get_by_index(po->ifindex);
	if (dev) {
		sll->sll_hatype = dev->type;
		sll->sll_halen = dev->addr_len;
		memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len);
		dev_put(dev);
	} else {
		sll->sll_hatype = 0;	/* Bad: we have no ARPHRD_UNSPEC */
		sll->sll_halen = 0;
	}
	*uaddr_len = sizeof(*sll);

	return 0;
}
/* Requests from userspace */
static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
{
	struct net_device *dev;

	if (info->attrs[IEEE802154_ATTR_DEV_NAME]) {
		char name[IFNAMSIZ + 1];

		nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME],
			    sizeof(name));
		dev = dev_get_by_name(&init_net, name);
	} else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) {
		dev = dev_get_by_index(&init_net,
			nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
	} else {
		return NULL;
	}

	if (!dev)
		return NULL;

	/* Check on mtu is currently a hacked solution because lowpan
	 * and wpan have the same ARPHRD type.
	 */
	if (dev->type != ARPHRD_IEEE802154 || dev->mtu != IEEE802154_MTU) {
		dev_put(dev);
		return NULL;
	}

	return dev;
}
Пример #11
0
void ipv6_sock_mc_close(struct sock *sk)
{
	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
	struct ipv6_mc_socklist *mc_lst;

	MDBG3((KERN_DEBUG
		"ipv6_sock_mc_close(sk=%p)\n", sk));

	write_lock_bh(&ipv6_sk_mc_lock);
	while ((mc_lst = np->ipv6_mc_list) != NULL) {
		struct net_device *dev;

		np->ipv6_mc_list = mc_lst->next;
		write_unlock_bh(&ipv6_sk_mc_lock);

		dev = dev_get_by_index(mc_lst->ifindex);
		if (dev) {
			ipv6_dev_mc_dec(dev, &mc_lst->addr);
			dev_put(dev);
		}

		sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));

		write_lock_bh(&ipv6_sk_mc_lock);
	}
	write_unlock_bh(&ipv6_sk_mc_lock);
}
Пример #12
0
/*
 * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
 */
static void ip_expire(unsigned long arg)
{
    struct ipq *qp;
    struct net *net;

    qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
    net = container_of(qp->q.net, struct net, ipv4.frags);

    spin_lock(&qp->q.lock);

    if (qp->q.last_in & INET_FRAG_COMPLETE)
        goto out;

    ipq_kill(qp);

    IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT);
    IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);

    if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
        struct sk_buff *head = qp->q.fragments;

        /* Send an ICMP "Fragment Reassembly Timeout" message. */
        if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) {
            icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
            dev_put(head->dev);
        }
    }
out:
    spin_unlock(&qp->q.lock);
    ipq_put(qp);
}
Пример #13
0
/**
 * mipv6_mn_send_home_na - send NA when returning home
 * @haddr: home address to advertise
 *
 * After returning home, MN must advertise all its valid addresses in
 * home link to all nodes.
 **/
void mipv6_mn_send_home_na(struct in6_addr *haddr)
{
	struct net_device *dev = NULL;
	struct in6_addr mc_allnodes;
	struct mn_info *hinfo = NULL;
 
	read_lock_bh(&mn_info_lock);
	hinfo = mipv6_mn_get_info(haddr);
	hinfo->is_at_home = 1;
	if (!hinfo) {
		read_unlock_bh(&mn_info_lock);
		return;
	}
	dev = dev_get_by_index(hinfo->ifindex);
	read_unlock_bh(&mn_info_lock);
	if (dev == NULL) {
		DEBUG((DBG_ERROR, "Send home_na: device not found."));
		return;
	}
	
	ipv6_addr_all_nodes(&mc_allnodes);
	if (ipv6_get_lladdr(dev, haddr) == 0)
		ndisc_send_na(dev, NULL, &mc_allnodes, haddr, 0, 0, 1, 1);
	ndisc_send_na(dev, NULL, &mc_allnodes, haddr, 0, 0, 1, 1);
	dev_put(dev);
}
Пример #14
0
/*
 *	socket leave on multicast group
 */
int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
{
	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
	struct ipv6_mc_socklist *mc_lst, **lnk;
#ifdef CONFIG_IPV6_MLD6_DEBUG
	char abuf[128];
	in6_ntop(addr, abuf);

	MDBG3((KERN_DEBUG
		"ipv6_sock_mc_drop(sk=%p, ifindex=%d, addr=%s)\n",
		sk, ifindex, abuf));
#endif

	write_lock_bh(&ipv6_sk_mc_lock);
	for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
		if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
		    ipv6_addr_cmp(&mc_lst->addr, addr) == 0) {
			struct net_device *dev;

			*lnk = mc_lst->next;
			write_unlock_bh(&ipv6_sk_mc_lock);

			/* Note: mc_lst->ifindex != 0 */
			if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
				ipv6_dev_mc_dec(dev, &mc_lst->addr);
				dev_put(dev);
			}
			sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
			return 0;
		}
	}
	write_unlock_bh(&ipv6_sk_mc_lock);

	return -ENOENT;
}
Пример #15
0
static void netlink_rcv_cb(struct sk_buff *skb)
{
	struct nlmsghdr *nlh;
	struct net_device *dev;
	u32 mlen;
	void *msg;
	int ifindex;

	if (skb->len >= NLMSG_SPACE(0)) {
		nlh = (struct nlmsghdr *)skb->data;

		if (skb->len < nlh->nlmsg_len ||
		nlh->nlmsg_len > ND_MAX_MSG_LEN) {
			printk(KERN_ERR "Invalid length (%d,%d)\n", skb->len,
				nlh->nlmsg_len);
			return;
		}

		memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN);
		msg = ND_NLMSG_DATA(nlh);
		mlen = ND_NLMSG_R_LEN(nlh);

		if (rcv_cb) {
			dev = dev_get_by_index(&init_net, ifindex);
			if (dev) {
				rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
				dev_put(dev);
			} else
				printk(KERN_ERR "dev_get_by_index(%d) "
					"is not found.\n", ifindex);
		} else
			printk(KERN_ERR "Unregistered Callback\n");
	}
}
Пример #16
0
/** 
 * mipv6_mn_move_homeaddr - Move home address from one interface to another.
 * @ifindex: interface index to which home address is moved
 * @haddr:  home address
 *
 * When an interface is stopped home addresses on that if need to be
 * moved to another interface.
 **/
int mipv6_mn_move_homeaddr(int ifindex, struct in6_addr *haddr) {
	
	struct in6_ifreq ifreq;

#ifdef CONFIG_IPV6_MOBILITY_DEBUG
	struct net_device *dev = NULL;
#endif
	DEBUG_FUNC();

	/* TODO!! */
	ifreq.ifr6_prefixlen = 64;
	
	ipv6_addr_copy(&ifreq.ifr6_addr, haddr);
	addrconf_del_ifaddr((void *)&ifreq);
	ifreq.ifr6_ifindex = ifindex;
	
	addrconf_add_ifaddr((void *)&ifreq);

#ifdef CONFIG_IPV6_MOBILITY_DEBUG
	dev = dev_get_by_index(ifindex);
	if (dev) {
		DEBUG((DBG_INFO, "Moved HA to %s", dev->name));
		dev_put(dev);
	}
#endif
	return 0;

}
Пример #17
0
bool copy_to_endpoint_skbs(struct pfq_sock *so, struct pfq_non_intrusive_skb *skbs, unsigned long long skbs_mask, int cpu, int gid)
{
	if (so->egress_index) {

		struct net_device *dev;
		struct sk_buff *skb;
		bool ret;
		int n;

                pfq_non_intrusive_for_each(skb, n, skbs)
		{
 			atomic_inc(&skb->users);
               	}

               	dev = dev_get_by_index(&init_net, so->egress_index);
               	if (dev == NULL)
		{
			if (printk_ratelimit()) {
                        	printk(KERN_INFO "[PFQ] egress endpoint index (%d)\n", so->egress_index);
                        	return false;
			}
		}

 		ret = pfq_queue_xmit_by_mask(skbs, skbs_mask, dev, so->egress_queue);
                dev_put(dev);
		return ret;
	}
Пример #18
0
static int raw_release(struct socket *sock)
{
	struct sock *sk = sock->sk;
	struct raw_sock *ro = raw_sk(sk);

	unregister_netdevice_notifier(&ro->notifier);

	lock_sock(sk);

	/* remove current filters & unregister */
	if (ro->bound) {
		if (ro->ifindex) {
			struct net_device *dev;

			dev = dev_get_by_index(&init_net, ro->ifindex);
			if (dev) {
				raw_disable_allfilters(dev, sk);
				dev_put(dev);
			}
		} else
			raw_disable_allfilters(NULL, sk);
	}

	if (ro->count > 1)
		kfree(ro->filter);

	ro->ifindex = 0;
	ro->bound   = 0;
	ro->count   = 0;

	release_sock(sk);
	sock_put(sk);

	return 0;
}
Пример #19
0
/*
 *	socket leave on multicast group
 */
int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
{
	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
	struct ipv6_mc_socklist *mc_lst, **lnk;

	write_lock_bh(&ipv6_sk_mc_lock);
	for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
		if (mc_lst->ifindex == ifindex &&
		    ipv6_addr_cmp(&mc_lst->addr, addr) == 0) {
			struct net_device *dev;

			*lnk = mc_lst->next;
			write_unlock_bh(&ipv6_sk_mc_lock);

			if ((dev = dev_get_by_index(ifindex)) != NULL) {
				ipv6_dev_mc_dec(dev, &mc_lst->addr);
				dev_put(dev);
			}
			sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
			return 0;
		}
	}
	write_unlock_bh(&ipv6_sk_mc_lock);

	return -ENOENT;
}
Пример #20
0
void ipv6_sock_ac_close(struct sock *sk)
{
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct net_device *dev = NULL;
	struct ipv6_ac_socklist *pac;
	int	prev_index;

	write_lock_bh(&ipv6_sk_ac_lock);
	pac = np->ipv6_ac_list;
	np->ipv6_ac_list = NULL;
	write_unlock_bh(&ipv6_sk_ac_lock);

	prev_index = 0;
	while (pac) {
		struct ipv6_ac_socklist *next = pac->acl_next;

		if (pac->acl_ifindex != prev_index) {
			if (dev)
				dev_put(dev);
			dev = dev_get_by_index(&init_net, pac->acl_ifindex);
			prev_index = pac->acl_ifindex;
		}
		if (dev)
			ipv6_dev_ac_dec(dev, &pac->acl_addr);
		sock_kfree_s(sk, pac, sizeof(*pac));
		pac = next;
	}
	if (dev)
		dev_put(dev);
}
Пример #21
0
/*
 *	socket leave an anycast group
 */
int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
{
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct net_device *dev;
	struct ipv6_ac_socklist *pac, *prev_pac;

	write_lock_bh(&ipv6_sk_ac_lock);
	prev_pac = NULL;
	for (pac = np->ipv6_ac_list; pac; pac = pac->acl_next) {
		if ((ifindex == 0 || pac->acl_ifindex == ifindex) &&
		     ipv6_addr_equal(&pac->acl_addr, addr))
			break;
		prev_pac = pac;
	}
	if (!pac) {
		write_unlock_bh(&ipv6_sk_ac_lock);
		return -ENOENT;
	}
	if (prev_pac)
		prev_pac->acl_next = pac->acl_next;
	else
		np->ipv6_ac_list = pac->acl_next;

	write_unlock_bh(&ipv6_sk_ac_lock);

	dev = dev_get_by_index(&init_net, pac->acl_ifindex);
	if (dev) {
		ipv6_dev_ac_dec(dev, &pac->acl_addr);
		dev_put(dev);
	}
	sock_kfree_s(sk, pac, sizeof(*pac));
	return 0;
}
Пример #22
0
/* Requests from userspace */
static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
{
	struct net_device *dev;

	if (info->attrs[IEEE802154_ATTR_DEV_NAME]) {
		char name[IFNAMSIZ + 1];
		nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME],
				sizeof(name));
		dev = dev_get_by_name(&init_net, name);
	} else if (info->attrs[IEEE802154_ATTR_DEV_INDEX])
		dev = dev_get_by_index(&init_net,
			nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
	else
		return NULL;

	if (!dev)
		return NULL;

	if (dev->type != ARPHRD_IEEE802154) {
		dev_put(dev);
		return NULL;
	}

	return dev;
}
Пример #23
0
static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
	struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
	struct sock *sk=sock->sk;
	struct net_device *dev = NULL;
	int err;


	/*
	 *	Check legality
	 */
	 
	if (addr_len < sizeof(struct sockaddr_ll))
		return -EINVAL;
	if (sll->sll_family != AF_PACKET)
		return -EINVAL;

	if (sll->sll_ifindex) {
		err = -ENODEV;
		dev = dev_get_by_index(sll->sll_ifindex);
		if (dev == NULL)
			goto out;
	}
	err = packet_do_bind(sk, dev, sll->sll_protocol ? : pkt_sk(sk)->num);
	if (dev)
		dev_put(dev);

out:
	return err;
}
Пример #24
0
/*
 * Create a Phonet header for the skb and send it out. Returns
 * non-zero error code if failed. The skb is freed then.
 */
int pn_skb_send(struct sock *sk, struct sk_buff *skb,
		const struct sockaddr_pn *target)
{
	struct net *net = sock_net(sk);
	struct net_device *dev;
	struct pn_sock *pn = pn_sk(sk);
	int err;
	u16 src, dst;
	u8 daddr, saddr, res;

	src = pn->sobject;
	if (target != NULL) {
		dst = pn_sockaddr_get_object(target);
		res = pn_sockaddr_get_resource(target);
	} else {
		dst = pn->dobject;
		res = pn->resource;
	}
	daddr = pn_addr(dst);

	err = -EHOSTUNREACH;
	if (sk->sk_bound_dev_if)
		dev = dev_get_by_index(net, sk->sk_bound_dev_if);
	else if (phonet_address_lookup(net, daddr) == 0) {
		dev = phonet_device_get(net);
		skb->pkt_type = PACKET_LOOPBACK;
	} else if (dst == 0) {
		/* Resource routing (small race until phonet_rcv()) */
		struct sock *sk = pn_find_sock_by_res(net, res);
		if (sk)	{
			sock_put(sk);
			dev = phonet_device_get(net);
			skb->pkt_type = PACKET_LOOPBACK;
		} else
			dev = phonet_route_output(net, daddr);
	} else
		dev = phonet_route_output(net, daddr);

	if (!dev || !(dev->flags & IFF_UP))
		goto drop;

	saddr = phonet_address_get(dev, daddr);
	if (saddr == PN_NO_ADDR)
		goto drop;

	if (!pn_addr(src))
		src = pn_object(saddr, pn_obj(src));

	err = pn_send(skb, dev, dst, src, res, 0);
	dev_put(dev);
	return err;

drop:
	printk(KERN_DEBUG "pn_skb_send DROP\n");
	kfree_skb(skb);
	if (dev)
		dev_put(dev);
	return err;
}
Пример #25
0
static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
		       struct msghdr *msg, size_t size)
{
	struct sock *sk = sock->sk;
	struct raw_sock *ro = raw_sk(sk);
	struct sk_buff *skb;
	struct net_device *dev;
	int ifindex;
	int err;

	if (msg->msg_name) {
		struct sockaddr_can *addr =
			(struct sockaddr_can *)msg->msg_name;

		if (addr->can_family != AF_CAN)
			return -EINVAL;

		ifindex = addr->can_ifindex;
	} else
		ifindex = ro->ifindex;

	if (size != sizeof(struct can_frame))
		return -EINVAL;

	dev = dev_get_by_index(&init_net, ifindex);
	if (!dev)
		return -ENXIO;

	skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
				  &err);
	if (!skb)
		goto put_dev;

	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
	if (err < 0)
		goto free_skb;
	err = sock_tx_timestamp(msg, sk, skb_tx(skb));
	if (err < 0)
		goto free_skb;
	skb->dev = dev;
	skb->sk  = sk;

	err = can_send(skb, ro->loopback);

	dev_put(dev);

	if (err)
		goto send_failed;

	return size;

free_skb:
	kfree_skb(skb);
put_dev:
	dev_put(dev);
send_failed:
	return err;
}
Пример #26
0
static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
	struct ifinfomsg *ifm;
	struct nlattr *tb[IFLA_MAX+1];
	struct net_device *dev = NULL;
	struct sk_buff *nskb;
	char *iw_buf = NULL, *iw = NULL;
	int iw_buf_len = 0;
	int err;

	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
	if (err < 0)
		return err;

	ifm = nlmsg_data(nlh);
	if (ifm->ifi_index >= 0) {
		dev = dev_get_by_index(ifm->ifi_index);
		if (dev == NULL)
			return -ENODEV;
	} else
		return -EINVAL;


#ifdef CONFIG_NET_WIRELESS_RTNETLINK
	if (tb[IFLA_WIRELESS]) {
		/* Call Wireless Extensions. We need to know the size before
		 * we can alloc. Various stuff checked in there... */
		err = wireless_rtnetlink_get(dev, nla_data(tb[IFLA_WIRELESS]),
					     nla_len(tb[IFLA_WIRELESS]),
					     &iw_buf, &iw_buf_len);
		if (err < 0)
			goto errout;

		iw += IW_EV_POINT_OFF;
	}
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

	nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
	if (nskb == NULL) {
		err = -ENOBUFS;
		goto errout;
	}

	err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
			       NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
	if (err < 0) {
		/* -EMSGSIZE implies BUG in if_nlmsg_size */
		WARN_ON(err == -EMSGSIZE);
		kfree_skb(nskb);
		goto errout;
	}
	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
errout:
	kfree(iw_buf);
	dev_put(dev);

	return err;
}
Пример #27
0
/* This cleans up af_inet6 a bit. -DaveM */
static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
	struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr;
	__u32 v4addr = 0;
	int addr_type;

	/* Check these errors. */
	if (sk->state != TCP_CLOSE || (addr_len < sizeof(struct sockaddr_in6)))
		return -EINVAL;

	addr_type = ipv6_addr_type(&addr->sin6_addr);

	/* Check if the address belongs to the host. */
	if (addr_type == IPV6_ADDR_MAPPED) {
		/* Raw sockets are IPv6 only */
		return(-EADDRNOTAVAIL);
	} else {
		if (addr_type != IPV6_ADDR_ANY) {
			if (addr_type & IPV6_ADDR_LINKLOCAL) {
				if (addr_len >= sizeof(struct sockaddr_in6) &&
				    addr->sin6_scope_id) {
					/* Override any existing binding,
					 * if another one is supplied by user.
					 */
					sk->bound_dev_if =
						addr->sin6_scope_id;
				}

				/* Binding to link-local address requires
				   an interface */
				if (!sk->bound_dev_if)
					return(-EINVAL);
				
				if (!dev_get_by_index(sk->bound_dev_if))
					return(-ENODEV);
			}

			/* ipv4 addr of the socket is invalid.  Only the
			 * unpecified and mapped address have a v4 equivalent.
			 */
			v4addr = LOOPBACK4_IPV6;
			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
				if (ipv6_chk_addr(&addr->sin6_addr, NULL, 0) == NULL)
					return(-EADDRNOTAVAIL);
			}
		}
	}

	sk->rcv_saddr = v4addr;
	sk->saddr = v4addr;
	memcpy(&sk->net_pinfo.af_inet6.rcv_saddr, &addr->sin6_addr, 
	       sizeof(struct in6_addr));
	if (!(addr_type & IPV6_ADDR_MULTICAST))
		memcpy(&sk->net_pinfo.af_inet6.saddr, &addr->sin6_addr, 
		       sizeof(struct in6_addr));
	return 0;
}
Пример #28
0
int mgt_response( unsigned int src_id, unsigned int src_seq,
                  unsigned int dev_type, unsigned int dev_seq,
                  unsigned int op, int oid, void *data, unsigned long len)
{
    int i;
    int err = 0;
    struct net_device *dev;
    struct resp_rec *pr;
    mgt_response_t resp_oid = NULL;
    mgt_response_t resp_def = NULL;

#ifdef DRIVER_DEBUG
    printk (KERN_ERR "mgt_response(%d, %d, %d, %d, %d, %x, <data>, %d)\n",
            src_id, src_seq, dev_type, dev_seq, op, oid, (unsigned int)len );
#endif

    if ( mgt_resp_table_init != -1 ) {

        if ( ! (dev = dev_get_by_index( dev_seq ) ) )
            return -1;

        for ( i = 0, pr = resp_table; ( pr->resp != NULL ) && ( i < RESP_TABLE_SZ ); i++, pr++ ) {
           if ( ( pr->src_seq == 0 ) && ( strncmp ( pr->name, dev->name, IFNAMSIZ ) == 0 ) ) {
               mgt_resp_table_init++;
               pr->src_seq = dev_seq;
           }
        }

        if ( i == mgt_resp_table_init ) {
            mgt_resp_table_init = -1;
        }

        dev_put( dev );
    }

    for ( i = 0, pr = resp_table; i < RESP_TABLE_SZ; i++, pr++ ) {
        if ( ( pr->src_id == src_id ) && ( pr->src_seq == src_seq ) && ( pr->resp != NULL ) ) {
            if ( pr->oid == oid ) {
                resp_oid = pr->resp;
                break;
            } else if ( pr->oid == 0 ) {
                resp_def = pr->resp;
            }
        }
    }

    /* only one response allowed (indication); specific handlers have priority over default handler */
    if ( resp_oid ) {
        if ( (*resp_oid)( src_id, src_seq, dev_type, dev_seq, op, oid, data, len ) < 0)
            err = -EPFNOSUPPORT;
    } else if ( cnf_hndl ) {
        if ( ( *cnf_hndl )( src_id, src_seq, dev_type, dev_seq, op, oid, data, len ) < 0 )
            err = -EPFNOSUPPORT;
    }

    return err;
}
Пример #29
0
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;
}
Пример #30
0
static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
		       struct msghdr *msg, size_t size)
{
	struct sock *sk = sock->sk;
	struct raw_opt *ro = raw_sk(sk);
	struct sk_buff *skb;
	struct net_device *dev;
	int ifindex;
	int err;

	DBG("socket %p, sk %p\n", sock, sk);

	if (msg->msg_name) {
		struct sockaddr_can *addr =
			(struct sockaddr_can *)msg->msg_name;

		if (addr->can_family != AF_CAN)
			return -EINVAL;

		ifindex = addr->can_ifindex;
	} else
		ifindex = ro->ifindex;

	dev = dev_get_by_index(ifindex);
	if (!dev) {
		DBG("device %d not found\n", ifindex);
		return -ENXIO;
	}

	skb = alloc_skb(size, GFP_KERNEL);
	if (!skb) {
		dev_put(dev);
		return -ENOMEM;
	}

	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
	if (err < 0) {
		kfree_skb(skb);
		dev_put(dev);
		return err;
	}
	skb->dev = dev;
	skb->sk  = sk;

	DBG("sending skbuff to interface %d\n", ifindex);
	DBG_SKB(skb);

	err = can_send(skb, ro->loopback);

	dev_put(dev);

	if (err)
		return err;

	return size;
}