Esempio n. 1
0
static int
ndisc_build_ll_hdr(struct sk_buff *skb, struct device *dev,
		   struct in6_addr *daddr, struct neighbour *neigh, int len)
{
	unsigned char ha[MAX_ADDR_LEN];
	unsigned char *h_dest = NULL;

	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);

	if (dev->hard_header) {
		if (ipv6_addr_type(daddr) & IPV6_ADDR_MULTICAST) {
			ndisc_mc_map(daddr, ha, dev, 1);
			h_dest = ha;
		} else if (neigh) {
			h_dest = neigh->ha;
		} else {
			neigh = neigh_lookup(&nd_tbl, daddr, dev);
			if (neigh) {
				if (neigh->nud_state&NUD_VALID) {
					memcpy(ha, neigh->ha, dev->addr_len);
					h_dest = ha;
				}
				neigh_release(neigh);
			}
		}

		if (dev->hard_header(skb, dev, ETH_P_IPV6, h_dest, NULL, len) < 0)
			return 0;
	}

	return 1;
}
Esempio n. 2
0
File: arp.c Progetto: 274914765/C
static int arp_req_delete(struct net *net, struct arpreq *r,
        struct net_device * dev)
{
    int err;
    __be32 ip;
    struct neighbour *neigh;

    if (r->arp_flags & ATF_PUBL)
        return arp_req_delete_public(net, r, dev);

    ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
    if (dev == NULL) {
        struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
                             .tos = RTO_ONLINK } } };
        struct rtable * rt;
        if ((err = ip_route_output_key(net, &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;
}
Esempio n. 3
0
static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
			    u16 vid, struct net_bridge_port *p)
{
	struct net_device *dev = br->dev;
	struct neighbour *n;
	struct arphdr *parp;
	u8 *arpptr, *sha;
	__be32 sip, tip;

	BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;

	if (dev->flags & IFF_NOARP)
		return;

	if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
		dev->stats.tx_dropped++;
		return;
	}
	parp = arp_hdr(skb);

	if (parp->ar_pro != htons(ETH_P_IP) ||
	    parp->ar_op != htons(ARPOP_REQUEST) ||
	    parp->ar_hln != dev->addr_len ||
	    parp->ar_pln != 4)
		return;

	arpptr = (u8 *)parp + sizeof(struct arphdr);
	sha = arpptr;
	arpptr += dev->addr_len;	/* sha */
	memcpy(&sip, arpptr, sizeof(sip));
	arpptr += sizeof(sip);
	arpptr += dev->addr_len;	/* tha */
	memcpy(&tip, arpptr, sizeof(tip));

	if (ipv4_is_loopback(tip) ||
	    ipv4_is_multicast(tip))
		return;

	n = neigh_lookup(&arp_tbl, &tip, dev);
	if (n) {
		struct net_bridge_fdb_entry *f;

		if (!(n->nud_state & NUD_VALID)) {
			neigh_release(n);
			return;
		}

		f = __br_fdb_get(br, n->ha, vid);
		if (f && ((p->flags & BR_PROXYARP) ||
			  (f->dst && (f->dst->flags & BR_PROXYARP_WIFI)))) {
			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip,
				 sha, n->ha, sha);
			BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
		}

		neigh_release(n);
	}
}
Esempio n. 4
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;
}
Esempio n. 5
0
/* Get eth_addr for a dst_ip by looking up into the ARP table */
int get_dst_haddr(unsigned char* daddr, u32 dst_ip, struct net_device *dev){
    struct neighbour *neigh = neigh_lookup(&arp_tbl, &dst_ip, dev);
    int err = -ENXIO;
    if(neigh){
        memcpy(daddr, neigh->ha, dev->addr_len);
        neigh_release(neigh);
        err = 0;
    }
    else{
        pr_debug("neigh_lookup failed!\n");
    }
    return err;
}
Esempio n. 6
0
int arp_invalidate(struct net_device *dev, __be32 ip)
{
	struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
	int err = -ENXIO;

	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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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(dev)) {
				__in_dev_get(dev)->cnf.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, 1, 0);
		neigh_release(neigh);
	}
	return err;
}
Esempio n. 9
0
File: arp.c Progetto: 274914765/C
static int arp_req_get(struct arpreq *r, struct net_device *dev)
{
    __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
    struct neighbour *neigh;
    int err = -ENXIO;

    neigh = neigh_lookup(&arp_tbl, &ip, dev);
    if (neigh) {
        read_lock_bh(&neigh->lock);
        memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
        r->arp_flags = arp_state_to_flags(neigh);
        read_unlock_bh(&neigh->lock);
        r->arp_ha.sa_family = dev->type;
        strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
        neigh_release(neigh);
        err = 0;
    }
    return err;
}
Esempio n. 10
0
static int arp_invalidate(struct net_device *dev, __be32 ip)
{
	struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
	int err = -ENXIO;
	struct neigh_table *tbl = &arp_tbl;

	if (neigh) {
		if (neigh->nud_state & ~NUD_NOARP)
			err = neigh_update(neigh, NULL, NUD_FAILED,
					   NEIGH_UPDATE_F_OVERRIDE|
					   NEIGH_UPDATE_F_ADMIN, 0);
		write_lock_bh(&tbl->lock);
		neigh_release(neigh);
		neigh_remove_one(neigh, tbl);
		write_unlock_bh(&tbl->lock);
	}

	return err;
}
Esempio n. 11
0
static void
cicp_kernel_resolve(ci_netif* ni, struct cp_fwd_key* key,
                    struct cp_fwd_data* data)
{
  int rc;
  struct rtable *rt = NULL;
  cicp_hwport_mask_t rx_hwports = 0;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38)
  /* rhel6 case */
  struct flowi fl;

  memset(&fl, 0, sizeof(fl));
  fl.fl4_dst = key->dst;
  fl.fl4_src = key->src;
  fl.fl4_tos = key->tos;
  fl.oif = key->ifindex;

  rc = ip_route_output_key(ni->cplane->cp_netns, &rt, &fl);
  if( rc < 0 ) {
    data->ifindex = CI_IFID_BAD;
    return;
  }
  data->src = fl.fl4_src;
#define DST_DEV(rt) rt->u.dst.dev
#else /* linux-2.6.39 and newer */
  struct flowi4 fl4;

  memset(&fl4, 0, sizeof(fl4));
  fl4.daddr = key->dst;
  fl4.saddr = key->src;
  fl4.flowi4_tos = key->tos;
  fl4.flowi4_oif = key->ifindex;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
  fl4.flowi4_uid = make_kuid(current_user_ns(), ni->state->uuid);
#endif

  rt = ip_route_output_key(ni->cplane->cp_netns, &fl4);
  if( IS_ERR(rt) ) {
    data->ifindex = CI_IFID_BAD;
    return;
  }
  data->src = fl4.saddr;
#define DST_DEV(rt) rt->dst.dev
#endif /* 2.6.39 */

  data->ifindex = DST_DEV(rt)->ifindex;
  data->next_hop = rt->rt_gateway;
  if( data->next_hop == 0 )
    data->next_hop = key->dst;

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
  data->mtu = 0;
  /* We'll use interface MTU and ignore the route MTU even if it has one
   * for the older kernels.  This code is mostly used for SYN-ACK replies,
   * so MTU value is not too important. */
#else
  data->mtu = rt->rt_pmtu;
#endif

  data->arp_valid = 0;
  if( data->ifindex != 1 ) {
    /* In theory the rt->dst structure has a reference to the neigh,
     * but in practice it is not easy to dig the neigh out. */
    struct neighbour *neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway,
                                           DST_DEV(rt));
    if( neigh != NULL && (neigh->nud_state & NUD_VALID) ) {
      data->arp_valid = 1;
      memcpy(data->dst_mac, neigh->ha, ETH_ALEN);
    }
    if( neigh != NULL )
      neigh_release(neigh);
  }

  ip_rt_put(rt);

  if( data->ifindex == CI_IFID_LOOP )
    return;

  /* We've got the route.  Let's look into llap table to find out the
   * network interface details. */
  rc = oo_cp_find_llap(ni->cplane, data->ifindex,
                       data->mtu == 0 ? &data->mtu : NULL,
                       &data->hwports, &rx_hwports, &data->src_mac, &data->encap);

  if( rc < 0 || rx_hwports == 0 )
    data->ifindex = CI_IFID_BAD;
}