コード例 #1
0
ファイル: linux_route.c プロジェクト: Th3Bill/authentec
/* Route IPv6 packet 'skbp', using the route key selectors in
   'route_selector' and the interface number 'ifnum_in'. */
Boolean
ssh_interceptor_reroute_skb_ipv6(SshInterceptor interceptor,
                                 struct sk_buff *skbp,
                                 SshUInt16 route_selector,
                                 SshUInt32 ifnum_in)
{
    /* we do not need a socket, only fake flow */
    struct flowi rt_key;
    struct dst_entry *dst;
    struct ipv6hdr *iph6;

    iph6 = (struct ipv6hdr *) SSH_SKB_GET_NETHDR(skbp);
    if (iph6 == NULL)
    {
        SSH_DEBUG(SSH_D_ERROR, ("Could not access IPv6 header"));
        return FALSE;
    }

    memset(&rt_key, 0, sizeof(rt_key));

    rt_key.fl6_dst = iph6->daddr;

    if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_SRC)
        rt_key.fl6_src = iph6->saddr;

    if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_OUT_IFNUM)
    {
        rt_key.oif = (skbp->dev ? skbp->dev->ifindex : 0);
        SSH_LINUX_ASSERT_IFNUM(rt_key.oif);
    }

#ifdef LINUX_IP6_ROUTE_OUTPUT_KEY_HAS_NET_ARGUMENT
    dst = ip6_route_output(&init_net, NULL, &rt_key);
#else /* LINUX_IP6_ROUTE_OUTPUT_KEY_HAS_NET_ARGUMENT */
    dst = ip6_route_output(NULL, &rt_key);
#endif /* LINUX_IP6_ROUTE_OUTPUT_KEY_HAS_NET_ARGUMENT */

    if (dst == NULL || dst->error != 0)
    {
        SSH_DEBUG(SSH_D_FAIL,
                  ("ip6_route_output failed."));

        SSH_DEBUG_HEXDUMP(SSH_D_NICETOKNOW,
                          ("dst "),
                          (unsigned char *) &iph6->daddr, sizeof(iph6->daddr));
        SSH_DEBUG_HEXDUMP(SSH_D_NICETOKNOW,
                          ("src "),
                          (unsigned char *) &iph6->saddr, sizeof(iph6->saddr));
        SSH_DEBUG(SSH_D_NICETOKNOW,
                  ("oif %d[%s]",
                   (skbp->dev ? skbp->dev->ifindex : -1),
                   (skbp->dev ? skbp->dev->name : "none")));
        return FALSE;
    }
    if (SSH_SKB_DST(skbp))
        dst_release(SSH_SKB_DST(skbp));
    SSH_SKB_DST_SET(skbp, dst_clone(dst));

    return TRUE;
}
コード例 #2
0
ファイル: linux_route.c プロジェクト: patrick-ken/kernel_808l
/* Route IPv4 packet 'skbp', using the route key selectors in 
   'route_selector' and the interface number 'ifnum_in'. */
Boolean
ssh_interceptor_reroute_skb_ipv4(SshInterceptor interceptor,
				 struct sk_buff *skbp,
				 SshUInt16 route_selector,
				 SshUInt32 ifnum_in)
{
  struct iphdr *iph;
  int rval = 0;

  /* Recalculate the route info as the engine might have touched the
     destination address. This can happen for example if we are in
     tunnel mode. */

  iph = (struct iphdr *) SSH_SKB_GET_NETHDR(skbp);
  if (iph == NULL)
    {
      SSH_DEBUG(SSH_D_ERROR, ("Could not access IP header"));
      return FALSE;
    }

  /* Release old dst_entry */
  if (skb_dst(skbp))
    dst_release(skb_dst(skbp));

  skb_dst_set(skbp, NULL);

  if ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_SRC)
      && (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_FLAG_LOCAL_SRC) == 0
      && (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IN_IFNUM))
    {
      u32 saddr = 0;
      u8 ipproto = 0;
      u8 tos = 0;
#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
#ifdef SSH_LINUX_FWMARK_EXTENSION_SELECTOR
      u32 fwmark = 0;
#endif /* SSH_LINUX_FWMARK_EXTENSION_SELECTOR */
#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
      struct net_device *dev;

      SSH_ASSERT(skbp->protocol == __constant_htons(ETH_P_IP));

      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_SRC)
	saddr = iph->saddr;
           
      /* Map 'ifnum_in' to a net_device. */
      SSH_LINUX_ASSERT_VALID_IFNUM(ifnum_in);
      dev = ssh_interceptor_ifnum_to_netdev(interceptor, ifnum_in);

      /* Clear the IP protocol, if selector does not define it.
	 Ugly, but necessary to make sure the skb gets
	 rerouted like engine expects. */
      if ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IPPROTO) == 0)
	{	  
	  ipproto = iph->protocol;
	  iph->protocol = 0;
	}

      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IP4_TOS)
	tos = RT_TOS(iph->tos);

#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
#ifdef SSH_LINUX_FWMARK_EXTENSION_SELECTOR
      /* Clear the nfmark, if selector does not define it.
	 Ugly, but necessary to make sure the skb gets
	 rerouted like engine expects. */
      if ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_EXTENSION) == 0)
	{
	  fwmark = SSH_SKB_MARK(skbp);
	  SSH_SKB_MARK(skbp) = 0;
	}
#endif /* SSH_LINUX_FWMARK_EXTENSION_SELECTOR */
#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
      
      /* Call ip_route_input */
      if (ip_route_input(skbp, iph->daddr, saddr, tos, dev) < 0)
	{
	  SSH_DEBUG(SSH_D_FAIL, 
		    ("ip_route_input failed. (0x%08x -> 0x%08x)",
		     iph->saddr, iph->daddr));

	  SSH_DEBUG(SSH_D_NICETOKNOW,
		    ("dst 0x%08x src 0x%08x iif %d[%s] proto %d tos 0x%02x "
		     "fwmark 0x%x",
		     iph->daddr, saddr,
		     (dev ? dev->ifindex : -1),
		     (dev ? dev->name : "none"), 
		     iph->protocol, tos, 
		     SSH_SKB_MARK(skbp)));

	  /* Release netdev reference */
	  if (dev)
	    ssh_interceptor_release_netdev(dev);

	  /* Note, skb modifications are not un-done as the caller frees the 
	     skb. If this is changed then the modifications should be un-done
	     here before returning. */

	  return FALSE;
	}

      /* Write original IP protocol back to skb */
      if (ipproto)
	iph->protocol = ipproto;

#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
#ifdef SSH_LINUX_FWMARK_EXTENSION_SELECTOR
      /* Write original fwmark back to skb */
      if (fwmark)
	SSH_SKB_MARK(skbp) = fwmark;
#endif /* SSH_LINUX_FWMARK_EXTENSION_SELECTOR */
#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */

      /* Release netdev reference */
      if (dev)
	ssh_interceptor_release_netdev(dev);
    }

  else
    {
      struct rtable *rt;
      struct flowi rt_key;

      if ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_FLAG_LOCAL_SRC) == 0)
	route_selector &= ~SSH_INTERCEPTOR_ROUTE_KEY_SRC;

      memset(&rt_key, 0, sizeof(rt_key));
      
      rt_key.fl4_dst = iph->daddr;
      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_SRC)
	rt_key.fl4_src = iph->saddr;
      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_OUT_IFNUM)
	rt_key.oif = (skbp->dev ? skbp->dev->ifindex : 0);
      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IPPROTO)
	rt_key.proto = iph->protocol;
      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IP4_TOS)
	rt_key.fl4_tos = RT_TOS(iph->tos);
      rt_key.fl4_scope = RT_SCOPE_UNIVERSE;

#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
#ifdef SSH_LINUX_FWMARK_EXTENSION_SELECTOR
      if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_EXTENSION)
	{
#ifdef LINUX_HAS_SKB_MARK
	  rt_key.mark = SSH_SKB_MARK(skbp);
#else /* LINUX_HAS_SKB_MARK */
#ifdef CONFIG_IP_ROUTE_FWMARK
	  rt_key.fl4_fwmark = SSH_SKB_MARK(skbp);
#endif /* CONFIG_IP_ROUTE_FWMARK */
#endif /* LINUX_HAS_SKB_MARK */
	}
#endif /* SSH_LINUX_FWMARK_EXTENSION_SELECTOR */
#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
      
      /* Call ip_route_output */
#ifdef LINUX_IP_ROUTE_OUTPUT_KEY_HAS_NET_ARGUMENT
      rval = ip_route_output_key(&init_net, &rt, &rt_key);
#else /* LINUX_IP_ROUTE_OUTPUT_KEY_HAS_NET_ARGUMENT */
      rval = ip_route_output_key(&rt, &rt_key);
#endif /* LINUX_IP_ROUTE_OUTPUT_KEY_HAS_NET_ARGUMENT */
      if (rval < 0)
	{
	  SSH_DEBUG(SSH_D_FAIL, 
		    ("ip_route_output_key failed (0x%08x -> 0x%08x): %d",
		     iph->saddr, iph->daddr, rval));

	  SSH_DEBUG(SSH_D_NICETOKNOW,
		    ("dst 0x%08x src 0x%08x oif %d[%s] proto %d tos 0x%02x"
		     "fwmark 0x%x",
		     iph->daddr,
		     ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_SRC) ? 
		      iph->saddr : 0),
		     ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_OUT_IFNUM) ?
		      rt_key.oif : -1),
		     ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_OUT_IFNUM) ?
		      (skbp->dev ? skbp->dev->name : "none") : "none"),
		     ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IPPROTO) ?
		      iph->protocol : -1),
		     ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_IP4_TOS) ?
		      iph->tos : 0),
		     ((route_selector & SSH_INTERCEPTOR_ROUTE_KEY_EXTENSION) ?
		      SSH_SKB_MARK(skbp) : 0)));

	  /* Note, skb modifications are not un-done as the caller frees the 
	     skb. If this is changed then the modifications should be un-done
	     here before returning. */

	  return FALSE;
	}

      /* Make a new dst because we just rechecked the route. */
      skb_dst_set(skbp, dst_clone(&rt->u.dst));
      
      /* Release the routing table entry ; otherwise a memory leak occurs
	 in the route entry table. */
      ip_rt_put(rt);
    }
  
  SSH_ASSERT(skb_dst(skbp) != NULL);

#ifdef SSH_IPSEC_IP_ONLY_INTERCEPTOR
#ifdef LINUX_FRAGMENTATION_AFTER_NF_POST_ROUTING
  if (route_selector & SSH_INTERCEPTOR_ROUTE_KEY_FLAG_TRANSFORM_APPLIED)
    {
      /* Check if need to create a child dst_entry with interface MTU. */
      if (skb_dst(skbp)->child == NULL)
	{
          if (interceptor_route_create_child_dst(skb_dst(skbp)) == NULL)
	    {
	      SSH_DEBUG(SSH_D_ERROR,
			("Could not create child dst_entry for dst %p",
			 skb_dst(skbp)));
	      return FALSE;
	    }
	}
     
      /* Pop dst stack and use the child entry with interface MTU 
	 for sending the packet. */
      skb_dst_set(skbp, dst_pop(skb_dst(skbp)));
    }
#endif /* LINUX_FRAGMENTATION_AFTER_NF_POST_ROUTING */
#endif /* SSH_IPSEC_IP_ONLY_INTERCEPTOR */

  return TRUE;
}