Esempio n. 1
0
int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
{
	struct rt6_info *rt;

	rt = dst_alloc(&ip6_dst_ops);
	if (rt == NULL)
		return -ENOMEM;

	rt->u.dst.flags = DST_HOST;
	rt->u.dst.input = ip6_input;
	rt->u.dst.output = ip6_output;
	rt->rt6i_dev = dev_get_by_name("lo");
	rt->u.dst.pmtu = ipv6_get_mtu(rt->rt6i_dev);
	rt->u.dst.advmss = max_t(unsigned int, rt->u.dst.pmtu - 60, ip6_rt_min_advmss);
	if (rt->u.dst.advmss > 65535-20)
		rt->u.dst.advmss = 65535;
	rt->rt6i_hoplimit = ipv6_get_hoplimit(rt->rt6i_dev);
	rt->u.dst.obsolete = -1;

	rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
	rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
	if (rt->rt6i_nexthop == NULL) {
		dst_free((struct dst_entry *) rt);
		return -ENOMEM;
	}

	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
	rt->rt6i_dst.plen = 128;
	rt6_ins(rt, NULL);

	return 0;
}
Esempio n. 2
0
/* Route the packet according to the routing keys specified in
 * route_info. Keys are :
 *  - ifindex : 
 *      0 if no oif preferred, 
 *      otherwise set to the index of the desired oif
 *  - route_info->gw :
 *      0 if no gateway specified,
 *      otherwise set to the next host to which the pkt must be routed
 * If success, skb->dev is the output device to which the packet must 
 * be sent and skb->dst is not NULL
 *
 * RETURN:  1 if the packet was succesfully routed to the 
 *            destination desired
 *          0 if the kernel routing table could not route the packet
 *            according to the keys specified
 */
static int 
route6(struct sk_buff *skb,
       unsigned int ifindex,
       const struct ip6t_route_target_info *route_info)
{
	struct rt6_info *rt = NULL;
	struct ipv6hdr *ipv6h = skb->nh.ipv6h;
	struct in6_addr *gw = (struct in6_addr*)&route_info->gw;

	DEBUGP("ip6t_ROUTE: called with: ");
	DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
	DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
	DEBUGP("OUT=%s\n", route_info->oif);
	
	if (ipv6_addr_any(gw))
		rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
	else
		rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);

	if (!rt)
		goto no_route;

	DEBUGP("ip6t_ROUTE: routing gives: ");
	DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
	DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
	DEBUGP("OUT=%s\n", rt->rt6i_dev->name);

	if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
		goto wrong_route;
	
	if (!rt->rt6i_nexthop) {
		DEBUGP("ip6t_ROUTE: discovering neighbour\n");
		rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
	}

	/* Drop old route. */
	dst_release(skb->dst);
	skb->dst = &rt->u.dst;
	skb->dev = rt->rt6i_dev;
	return 1;

 wrong_route:
	dst_release(&rt->u.dst);
 no_route:
	if (!net_ratelimit())
		return 0;

	printk("ip6t_ROUTE: no explicit route found ");
	if (ifindex)
		printk("via interface %s ", route_info->oif);
	if (!ipv6_addr_any(gw))
		printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
	printk("\n");
	return 0;
}
Esempio n. 3
0
static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
				struct in6_addr *saddr)
{
	int err;
	struct rt6_info *rt;

	/*
	 *	Clone the route.
	 */

	rt = ip6_rt_copy(ort);

	if (rt) {
		ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);

		if (!(rt->rt6i_flags&RTF_GATEWAY))
			ipv6_addr_copy(&rt->rt6i_gateway, daddr);

		rt->rt6i_dst.plen = 128;
		rt->rt6i_flags |= RTF_CACHE;
		rt->u.dst.flags |= DST_HOST;

#ifdef CONFIG_IPV6_SUBTREES
		if (rt->rt6i_src.plen && saddr) {
			ipv6_addr_copy(&rt->rt6i_src.addr, saddr);
			rt->rt6i_src.plen = 128;
		}
#endif

		rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);

		dst_hold(&rt->u.dst);

		err = rt6_ins(rt, NULL);
		if (err == 0)
			return rt;

		rt->u.dst.error = err;

		return rt;
	}
	dst_hold(&ip6_null_entry.u.dst);
	return &ip6_null_entry;
}