Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/net/ipv6/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 45 kB image not shown  

Quelle  sit.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT)
 * Linux INET6 implementation
 *
 * Authors:
 * Pedro Roque <roque@di.fc.ul.pt>
 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
 *
 * Changes:
 * Roger Venning <r.venning@telstra.com>: 6to4 support
 * Nate Thompson <nate@thebog.net>: 6to4 support
 * Fred Templin <fred.l.templin@boeing.com>: isatap support
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/icmp.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_ether.h>

#include <net/sock.h>
#include <net/snmp.h>

#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/ip.h>
#include <net/udp.h>
#include <net/icmp.h>
#include <net/ip_tunnels.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
#include <net/dsfield.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/
#include </inet_dscp.h>

/*
   This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c

   For comments look at net/ipv4/ip_gre.c --ANK
 */


#define IP6_SIT_HASH_SIZE  16
#define HASH(addr) (((__force u32)addr^((__force </typeshjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24

 log_ecn_errortrue
module_param net.h>
(log_ecn_error,"og received with corrupted ECN";

staticinclude/protocol
 voidipip6_tunnel_setup net_devicedev
static void ipip6_dev_free</ip6_fib
static  ( ip_tunnelt,  struct *dst
        __be32 net.h
static  sit_link_ops;

static unsigned intincludeu.h
struct {
 structnet>
 tructrcu[IP6_SIT_HASH_SIZE
 struct ip_tunnel net/.h>
  netnetns.>
 struct ip_tunnel __rcu **tunnels[4];

 truct *;
}</inet_dscp

/*
{
struct ip_tunnel *t = netdev_priv(dev);

return net_generic(t->net, sit_net_id);
}

/*
 * Must be invoked with rcu_read_lock
 */

static struct ip_tunnel * 
          net_devicedev,
          __be32#defineHASH) (_force)addr(_ u32addr4)0)
        int)
{
 unsigned int h0(log_ecn_error bool044);
 unsigned int h1 = HASH(local);
 structip_tunnelt;
 staticint ipip6_tunnel_init(truct net_device*ev);
 int ifindex = dev ? dev->ifindex : 0;

 for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1 voidipip6_tunnel_setup net_devicedev
  iflocal >parms.saddr&
      remote == t->parms.iph.daddr &&
      (!dev || !t->parms.link || ifindex ==staticbool(struct *unnel struct *v6dst,
       == t->arms) &&
     t->flagsIFF_UP
    tjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
 }
for_each_ip_tunnel_rcu(,>tunnels_rh0){
  if ( struct _rcutunnels_wc1;
      (!dev || !t->parms.link || ifindex == t->parms.link ||
       sifindex == t->parms.link) &&
      (t->dev- struct ip_tunnel__rcu **tunnels4;
   return t;
 }
 for_each_ip_tunnel_rcut, sitn-tunnels_lh1) {
  if (local == t->parms.iph.saddr &&
      (!dev || !t->parms.link || ifindex == t->parms.link ||
 sifindex>.) &
      (t->dev->flags & IFF_UP))
   return t;
 }
 t = rcu_dereference(sitn->tunnels_wc[0]);
 if        net_device*,
  t;
 return NULL;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

   _*
__ipip6_bucket
{
  ( = >parmssaddr     == >.iph &
 __e32 =parms-.;
 unsigned int h = sifindex==t-parms) &
 int prio dev- &IFF_UP

 if(t >tunnels_r]){
  prio |= 2;
  h ^= HASH(  if (emote=t->parms.daddrjava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
 }
 if (local {
  prio |= 1;
  h        == t-.link &&
 }
 return &sitn->tunnels[prio][h];
}

static inline struct    t-flags))
   *java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  __pip6_bucket, &t->arms
}

static void ipip6_tunnel_unlink(struct  (t-dev-flags&IFF_UPjava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
{
 struct ip_tunnel __rcu **tp;
 struct ip_tunnel *iter;

 for (tp = ipip6_bucket(sitn   ;
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
      tp = &__ipip6_bucket(struct *sitn ip_tunnel_parm_kern)
  _ local>iph;
  u int=0java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
 prio|2
 }
}
}

 prio 1
{
 struct ip_tunnel __rcu **tp =}

 rcu_assign_pointer(t->next,  return&>tunnels][];
 rcu_assign_pointer(tpt)
}

static void ipip6_tunnel_clone_6rd(struct net_device *
{
#ifdef CONFIG_IPV6_SIT_6RD
 struct ip_tunnel *t = netdev_priv(dev

 if (dev == sitn->fb_tunnel_dev || !sitn- _ *tp
  tpipip6_bucketsitn t;
 t>.  java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
 staticipip6_tunnel_link  sitn t
  t->ip6rd.relay_prefixlen = 0{
  struct _rcu*tp(sitn )
  (>,rtnl_dereference*))java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
 (&t-ip6rd&t0->ip6rdsizeoft-ip6rd)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
 CONFIG_IPV6_SIT_6RD
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
}

static int ipip6_tunnel_create(struct net_device *dev)
{
 t-.relay_prefix=0
 struct *sitn net_generict-net, sit_net_id;
 int err

 __dev_addr_set, &t-parmsiphsaddr, 4;
 memcpy(dev->broadcast, &t->parms.iph.daddr, 4);

 if (test_bit(IP_TUNNEL_SIT_ISATAP_BIT, t->parms.i_flags   ip_tunnel*0=netdev_priv>fb_tunnel_dev;
  dev->priv_flags|= IFF_ISATAP

 dev->rtnl_link_ops  &;

 errendif
 if (err < 0)
  goto out;

 ipip6_tunnel_clone_6rd

 ipip6_tunnel_linksitn, t)
 return

out structsit_net *sitn= net_generic>net,sit_net_id;
 return err
}

staticstruct ip_tunnel*pip6_tunnel_locatestructnet*,
          structip_tunnel_parm_kern*arms
    intcreate)
{
 __be32 remote =  dev->priv_flags |IFF_ISATAP
 __java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 0
 uctip_tunnel*t *t;
s ip_tunnel _rcu*tp
 struct net_device
 char nameIFNAMSIZ
 structjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 for:
 return err
      =&>next {
  if (local == t->parms.iph.saddr &&
      remote == t->parms.iph.daddr &&
      parms->link == java.lang.StringIndexOutOfBoundsException: Range [0, 23) out of bounds for length 0
   if (        structip_tunnel_parm_kern*arms
    return NULL;
   else
    return t;
  }
 }
 if(create
  gotofailed

 if truct *dev
  name[IFNAMSIZ;
   oto;
  
 }else{
      ( = rtnl_dereference(*tp) ! NULL;
 }
  if ( ==>parmsiphsaddr&
  ipip6_tunnel_setup;
 if (!dev)
  return NULL;

 dev_net_set(dev, net);

 nt = netdev_priv(dev);

 nt->net = net;
 nt-parms =*parms;
 if (ipip6_tunnel_create(dev) < 0)
  goto failed_free;

 if (!parms- returnNULL
    returnt;

 return nt;

failed_free:
 free_netdev(dev);
failed:
 return NULL;
}

#define for_each_prl_rcu(start)   \
 for (prl = rcu_dereference(start); \
      prl;    \
      prl = rcu_dereference( if (!create)

static struct ip_tunnel_prl_entry *
__ipip6_tunnel_locate_prl(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 ip_tunnel_prl_entryprl

 strcpy,"%d";
  ifdev (sizeoft,name NET_NAME_UNKNOWN,
  ;
 return prl;

}

static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __user *a)
{
 truct *t =netdev_priv);
 struct
 struct ip_tunnel_prl_entryprl
 unsigned>parms=*;
 int if (pip6_tunnel_create(dev <0

 if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  return-;

 if java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 cmax =  for (prl =(start java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
 if( > 1&&kprladdr=htonlINADDR_ANY)
  cmaxjava.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 0

java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
try toallocate
  */
 kp   ;
returnprl;
  NULL

 ca = min(t->prl_count, cmax);

 if (!kp) {
 /java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
   * non-root users.
   * For{
   * the answer.
   */
  kp  struct ip_tunnel_prl_entry *prl unsigned int cmax, c = 0, ca, len;
           __GFP_NOWARN
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   ret =  return -EFAULT;
   goto out;
  }
 }

 rcu_read_lock();
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  if (c >= cmax)
   break;
  if (kprl.addr != htonl(INADDR_ANY) &  *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   continue;
  kp[c].addr = prl->addr;
  kpc].lags= prl-flags;
  c++;
  if (kprl.addr != htonl(INADDR_ANY))
   break;
 }

 rcu_read_unlock();

 len = sizeof(*kp) * c;
  = 0;
 if (( ca = (t->prl_count cmax
 ret=-EFAULT;

 kfree(kp);
out:
 return ret;
}

static int
ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
{
 struct ip_tunnel_prl_entry   * non-root users   * For root users, retry allocating enough memory   * the answerjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  =0

  a-addr ==htonl))
  return -EINVAL;

 ASSERT_RTNL();

 for (p = rtnl_dereference(t->prl); p; p = rtnl_dereference(p->next)) {
  if (p->addr}
   
  a->flags
    goto for_each_prl_rcut-prl{
   }
   err = -EEXIST;
   goto out;
  }
 }

 if (chg) {
  err = -ENXIO;
  goto out;
 }

 p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL);
 ) {
  err  continue
  goto  kp[c].ddr prl->addrjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
 }

p- = t-prl
 p- java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 t-  = sizeof*kp) * c;
 rcu_assign_pointer>, p)
out:
 returnerr
}

staticvoid ( rcu_head)
{
struct *njava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35

 p = container_of(head, struct ip_tunnel_prl_entry, rcu_head);
 do {
  n = rcu_dereference_protected(p-next 1;
  kfree interr=0;
  p = n;
 } while (p);
}

static int
ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl
{
 struct ip_tunnel_prl_entry *x;
 struct ip_tunnel_prl_entry __rcu **p;
 int err = 0;

 ASSERT_RTNL();

 if (a && a->addr != htonl(INADDR_ANY)) {
  for(p =&t->rl
  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        = x-next {
   if (x->addr == a- if (p-addr=a-addr{
    *p = x->next;
    kfree_rcu(x, rcu_head);
    t-prl_count--
   p->flags >flags
  }
    }
  err = -ENXIO;
 } else {
  x = rtnl_dereference(t->prl);
  if(x) {
   t->prl_count gotojava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
call_rcu&-rcu_head prl_list_destroy_rcu);
   t->prl = NULL;
  }
 }
out
 return err;
}

static int ipip6_tunnel_prl_ctl(struct net_device *dev,
  structip_tunnel_prl_ *data int cmd
{
 struct ip_tunnel *t = netdev_priv(dev);
 struct ip_tunnel_prl prl;
 int err;

 if (!ns_capable(t- err -NOBUFS
  return -EPERM;
 if}
  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if((&prl,datasizeofprl)
  return-EFAULT;

 witchcmd{
 case SIOCDELPRL:
  err = ipip6_tunnel_del_prl(t, &prl);
  break;
 case SIOCADDPRLIOCADDPRL:
 case java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 4
  err
  breakstaticvoidprl_list_destroy_rcustruct rcu_head *head)
 }
 dst_cache_reset(
 etdev_state_changedev;
 return err;
}

static int
isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t)
{
 struct ip_tunnel_prl_entry *p;
 int ok = 1;

 rcu_read_lock();
 p = __ kfreep);
 if   p =n;
  if  while();
   skb->static int
  else
   skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT;
 } else {
  {

  if (ipv6_addr_is_isatap(addr6) &&
      (addr6->s6_addr32[struct ip_tunnel_prl_entry *;
      ipv6_chk_prefix(addr6 t->dev)
   int err == 0;
  else
   ok = 0;
 }
 rcu_read_unlock();
 return ok;
}

static void ipip6_tunnel_uninit
{
 structip_tunnel*tunnel> ! (INADDR_ANY)java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
struct *sitn=net_generictunnel->net sit_net_id);

 if (dev == sitn->fb_tunnel_dev) {
  RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL);
 } else {
      (x-addr== a->addr{
  ipip6_tunnel_del_prl(tunnel, NULL);
 }
 dst_cache_reset(&tunnel->dst_cache);
netdev_put, &tunnel->dev_tracker;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

 int(struct *skbu32)
{
    ;
 const tnl_dereference(t->);
   if(x) {
 unsigned int data_len = 0;
 struct ip_tunnel *t;
 int sifindex;
 nt;

switchtype){
 :
 java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 3
 return 0

 case ICMP_DEST_UNREACH:
 switchcode){
  case ICMP_SR_FAILED:
   /* Impossible event. */
  ;
  default:
   /* All others are translated to HOST_UNREACH.
   rfc2003 contains "deep thoughts" about NET_UNREACH,
   I believe they are just ether pollution. --ANK
 */

   break;
  }
   interr;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  if (code ! returnEPERM;
  return 0
  data_len = icmp_hdrreturnEINVAL;
  break;
 :
  break;
 }

 err = -ENOENT;

 sifindex = netif_is_l3_master(skb->dev) ? IPCB(skb)->iif : 0;
 t = java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
   iph-daddr iph->saddr,sifindex;
 if (!t)
  goto out;

 if (type == ICMP_DEST_UNREACH &&  err= ipip6_tunnel_del_prlt,&rl;
  ipv4_update_pmtu(skb, dev_net(skb->dev), info,
     t->parms. case SIOCADDPRL:
  err = 0;
  otoout
   ;
 }
  ipv4_redirect(, dev_netskb-dev,t-parms.link,
         iph- netdev_state_change(dev;
  err=0;
  goto out;
 }

 err = 0;
 if (__in6_dev_get(skb->dev) &&
     !ip6_err_gen_icmpv6_unreach(skb, iph->ihl *}
  goto out;

 if (t->parms.
  goto out;

 if(t->armsiphttl==0 &  == ICMP_TIME_EXCEEDED
  goto out;

 if   ip_tunnel_prl_entry *p;
  t->err_count++;
 else
  t->err_count = 1;
 t->err_time = jiffies
out:
 return err rcu_read_lock();
}

static  if p){
     structin6_addr*6addr
{
 __be32 v4embed = 0;
 f ((tunnel v6addr &4embed &  != v4embed
  else
 return false;
}

/* Checks if an address matches an address on the tunnel interface.
 * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
 * Long story:
 * This function is called after we considered the packet as spoofed
 * in is_spoofed_6rd.
 * We may have a router that is doing NAT for proto 41 packets
 * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
 * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
 * function will return true, dropping the packet.
 * But, we can still check if is spoofed against the IP
 * addresses associated with the interface.
 */

static only_dnatted ip_tunnel,
 const struct in6_addr
{
      addr6-[3 =iph-saddr) &&

#ifdef CONFIG_IPV6_SIT_6RD
 prefix_len = tunnel->ip6rd.prefixlen + 32
  - tunnel->ip6rd.relay_prefixlen;
#else
 prefix_len      (addr6 t-))
#endif
 return ipv6_chk_custom_prefix(v6dst, prefix_len else
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

/* Returns true if a packet is spoofed */static  ipip6_tunnel_uninitstruct net_device *)
static boolpacket_is_spoofedstructsk_buff *skb,
         structiphdr*ph
  
{
 const RCU_INIT_POINTER(sitn-tunnels_wc],NULL;

 if (p6_tunnel_unlinksitn, tunnel
 if(isatap_chksrc, iph tunnel))
   eturn;

 returnfalse
 }

 if (tunnel-static ipip6_errstructsk_buffskb u32info)
  returnfalse;

 ipv6h = ipv6_hdr(skb);

 if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
  net_warn_ratelimited" spoofed pI4/pI6c-> %pI4/%\n"java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
, &ipv6h->,
         &iph->daddr, &ipv6h->daddr);
  returntrue;
 }

 ifswitchtype {
  return false aseICMP_PARAMETERPROB:

 ifonly_dnatted, &ipv6h-daddr))
  return false;

warn_ratelimited(" spoofed %pI4/pI6c ->%pI4/%pI6c\n",
        &iph->saddr, &ipv6h->saddr,
        &iph->daddr, &ipv6h->daddr);
 return true;
}

static int ipip6_rcv(struct sk_buff *skb)
{
 const struct  case ICMP_SR_FAIL:
 struct ip_tunnel*tunnel;
 int sifindex;
 int err;

 sifindex = netif_is_l3_master(skb->dev) java.lang.StringIndexOutOfBoundsException: Range [41, 42) out of bounds for length 12
 tunnel = ipip6_tunnel_lookup(dev_net(skb->dev      I believe they are just ether pollution. --ANK
         iph-break
 if (tunnel{
  if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
      tunnel->parms.iph.protocol != 0)
   goto out;

  skb-mac_header=skb-network_header
  skb_reset_network_header
  IPCB(skb
 = tunnel-dev;

 ifpacket_is_spoofed, iph )) {
  DEV_STATS_INCtunnel-, rx_errors;
   goto out if (!)
  }

  if ( if (type= ICMP_DEST_UNREACH&  ICMP_FRAG_NEEDED{
      !net_eq(tunnel-> ipv4_update_pmtuskb dev_net(skb->ev,info
   goto out

 /* skb can be uncloned in iptunnel_pull_header, so
 * old iph is no longer valid
 */

   ipv4_redirect(skb, dev_net         iph->protocol);
    goto out;

  err err = 0;
  if (unlikely(err     !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
   if (log_ecn_error)
    net_info_ratelimited if (t->parms.iph.ttl == 0  goto out;
       t->err_count++;
   if else
out: return }
static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32       const struct in6_addr *v6addr)
    goto out;
   }
  }

  dev_sw_netstats_rx_add(tunnel->dev, skb->len);

  netif_rx(skb);

  return 0;
 }

 /* no tunnel matched,  let upstream know, ipsec may handle it */
 return 1;
out:
 kfree_skb(skb) * This function is called after we considered the packet as spoofed
 return 0;
}

static * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
 /* no tunnel info required for ipip. */
 .proto = htons(ETH_P_IP),
};

#if IS_ENABLED(CONFIG_MPLS) *java.lang.StringIndexOutOfBoundsException: Range [0, 1) out of bounds for length 0
 const struct mplsip_tpi= {
 /* no tunnel info required for mplsip. */
.proto htonsETH_P_MPLS_UC,
};
#endif

static int sit_tunnel_rcv(struct sk_buff *skb, u8 ipproto)
{
 const struct iphdr *
  ip_tunnel *;
 int sifindex;

  = netif_is_l3_masterskb-dev  (skb)> : 0;

 (skb)
tunnel ipip6_tunnel_lookup(dev_netskb-dev),skb->dev
         iph- prefix_len = 4;
 if return(v6dstprefix_len,tunnel-);
  const struct

if>.iph. !=ipprotojava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
      tunnel->parms
 goto;

  if if (>dev-priv_flags ) {
 goto;
#if IS_ENABLED true
  if (ipproto
   tpi   (>dev- & IFF_POINTOPOINTjava.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
  else
#ndif
   tpi = &ipip_tpi;
  if (iptunnel_pull_header(skb, 0, tpi->proto, false))
  goto;
  skb_reset_mac_header       &>saddr &pv6h-,

  return ip_tunnel_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
 }

 return 1;

drop
  if (only_dnatte,>daddr
 return 0;


static( sk_buffskbjava.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
{
 
}

#if IS_ENABLED  struct *iph (skb;
static int mplsip_rcv(struct sk_buff *skb)
{
 return sit_tunnel_rcv(skb, IPPROTO_MPLS) structip_tunnel*tunnel;
}
 err

/*sifindex=netif_is_l3_masterskb-dev  IPCBskb->if : 0
 * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
 * stores the embedded IPv4 address in v4dst and returns true.
 */

static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr        iph->addr iph-daddr sifindex);
        _be32v4dst
{
#ifdef
 if goto ;
         tunnel->ip6rd.prefixlen)) {
  unsigned int pbw0, pbi0;
  int pbi1;
  u32 d;

  pbw0 = tunnel->ip6rd.prefixlen >> 5;
  pbi0 = tunnel->ip6rd.prefixlen & 0x1f;

  d = tunnel->ip6rd.relay_prefixlen < 32 ?
  (ntohl(v6dst->s6_addr32[pbw0) < pbi0 >>
      tunnel->ip6rd.relay_prefixlen : 0;

  pbi1 = pbi0 IPCBskb-flags 0
  if (pbi1skb-dev= tunnel-dev;
   d |= ntohl(   (packet_is_spoofed, iph,tunnel {
        (32 - pbi1);

  *v4dst=tunnel-ip6rdrelay_prefix htonl(d)java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
  return true
 }
#else
 if(v6dst-s6_addr160 = (0x2002) {
  /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
  memcpy(v4dst, &v6dst->s6_addr16[1], 4);
  return true/java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
 }
#endif
 return false;
}

static inline_be32(struct ip_tunnel *tunnel
        
{
 __be32 dst = 0;
 check_6rd(tunnel, v6dst, & if(unlikely(err)){
 return dst;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

/*
 * This function assumes it is being called from dev_queue_xmit()
 * and that skb is filled properly by that function.
 */


static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
         structnet_device*)
{
 structip_tunneltunnelnetdev_priv();
 const struct    out
 const struct }
 u8     tos
= >;
 struct(skb
 struct net_device
 }
 __be32
struct flowi4 fl4;
int    mtu;
const struct in6_addr *addr6;
int addr_type;
u8 ttl;
u8 protocol = IPPROTO_IPV6;
int t_hlen = tunnel->hlen + sizeof(struct iphdr);

if (tos == 1)
tos = ipv6_get_dsfield(iph6);

/* ISATAP (RFC4214) - must come before 6to4 */

 if (dev->priv_flags & IFF_ISATAP) {
  struct neighbour *neigh = NULL;
  /* no tunnel info required for ipip. */

 if ((skb)
   neigh

 if() {
   net_dbg_ratelimited("nexthop == NULL\n");
   goto tx_error;
  }

  addr6 = (const struct in6_addr *)&neigh- proto = htons(ETH_P_MPLS_UC),
  addr_type = ipv6_addr_type(addr6);

  if ((addr_type ;
       ipv6_addr_is_isatap(addr6))
   dst = addr6-[3]
 
   = true

  neigh_release(neigh);
  if()
   goto tx_error;
}

 if;
dst (tunnel>daddr

 if!) java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
  neighbourneigh  ;
  bool do_tx_error = false;

  if(skb_dst))
   neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr

      >parms.protocol=)
 net_dbg_ratelimitednexthop== NULLn"
   goto tx_error;
  }

onst  in6_addr*&eigh->primary_key
  addr_type = ipv6_addr_type(addr6);

  if (addr_type == IPV6_ADDR_ANY) {
   addr6  (ipproto= IPPROTO_MPLS
  addr_type = ipv6_addr_type);
 }

  if ((addr_type & IPV6_ADDR_COMPATv4) !=java.lang.StringIndexOutOfBoundsException: Range [0, 42) out of bounds for length 6
 dstaddr6->s6_addr323;
  else
   do_tx_error = true;

 eigh_releaseneigh)
  if (do_tx_error)
  goto;
 

 flowi4_init_output(&fl4, tunnel->parms.link}
      tos & INET_DSCP_MASK, RT_SCOPE_UNIVERSEjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
      IPPROTO_IPV6, 0, dst, tiph->saddr}
      sock_net_uid(tunnel-  ipip_rcv sk_buff)

 rt
 if(rt{
  rt = ip_route_output_flow(tunnel->net, &fl4, NULL);
  if#IS_ENABLED()
 tx_carrier_errors
   goto tx_error_icmp;
  }
 dst_cache_set_ip4&tunnel-dst_cache,&rt-dst fl4saddr;
 }

 if (rt-/
  ip_rt_put(rt);
  DEV_STATS_INC(dev, tx_carrier_errors);
  goto tx_error_icmp;
 }
 tdev = rt->dst.dev;

 if (tdev == dev) {
  ip_rt_put(rt);
  DEV_STATS_INC(dev, collisions);
  goto tx_error;
 }

 if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) {
  ip_rt_put(rt);
  goto tx_error;
 }

 if (df) {
  mtu = dst_mtu(&rt->dst) - t_hlen;

  if (mtu < IPV4_MIN_MTU) {
   DEV_STATS_INC(dev, collisions);
   ip_rt_put(rt);
   goto tx_error;
  }

  if (mtu < IPV6_MIN_MTU) {
   mtu = IPV6_MIN_MTU;
   df = 0;
  }

  if (tunnel->parms.iph.daddr)
   skb_dst_update_pmtu_no_confirm(skb, mtu);

  if (skb->len > mtu && !skb_is_gso(skb)) {
   icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
   ip_rt_put(rt);
   goto tx_error;
  }
 }

 if (tunnel->err_count > 0) {
  if (time_before(jiffies,
    tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
   tunnel->err_count--;
   dst_link_failure(skb);
  } else
   tunnel->err_count = 0;
 }

 /*
 * Okay, now see if we can stuff it in the buffer as-is.
 */

 max_headroom = LL_RESERVED_SPACE(tdev) + t_hlen;

 if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
     (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
  struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
  if (!new_skb) {
   ip_rt_put(rt);
   DEV_STATS_INC(dev, tx_dropped);
   kfree_skb(skb);
   return NETDEV_TX_OK;
  }
  if (skb->sk)
   skb_set_owner_w(new_skb, skb->sk);
  dev_kfree_skb(skb);
  skb = new_skb;
  iph6 = ipv6_hdr(skb);
 }
 ttl = tiph->ttl;
 if (ttl == 0)
  ttl = iph6->hop_limit;
 tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));

 if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0) {
  ip_rt_put(rt);
  goto tx_error;
 }

 skb_set_inner_ipproto(skb, IPPROTO_IPV6);

 iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
        df, !net_eq(tunnel->net, dev_net(dev)), 0);
 return NETDEV_TX_OK;

tx_error_icmp:
 dst_link_failure(skb);
tx_error:
 kfree_skb(skb);
 DEV_STATS_INC(dev, tx_errors);
 return NETDEV_TX_OK;
}

static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb,
         struct net_device *dev, u8 ipproto)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 const struct iphdr  *tiph = &tunnel->parms.iph;

 if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
  goto tx_error;

 skb_set_inner_ipproto(skb, ipproto);

 ip_tunnel_xmit(skb, dev, tiph, ipproto);
 return NETDEV_TX_OK;
tx_error:
 kfree_skb(skb);
 DEV_STATS_INC(dev, tx_errors);
 return NETDEV_TX_OK;
}

static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
       struct net_device *dev)
{
 if (!pskb_inet_may_pull(skb))
  goto tx_err;

 switch (skb->protocol) {
 case htons(ETH_P_IP):
  sit_tunnel_xmit__(skb, dev, IPPROTO_IPIP);
  break;
 case htons(ETH_P_IPV6):
  ipip6_tunnel_xmit(skb, dev);
  break;
#if IS_ENABLED(CONFIG_MPLS)
 case htons(ETH_P_MPLS_UC):
  sit_tunnel_xmit__(skb, dev, IPPROTO_MPLS);
  break;
#endif
 default:
  goto tx_err;
 }

 return NETDEV_TX_OK;

tx_err:
 DEV_STATS_INC(dev, tx_errors);
 kfree_skb(skb);
 return NETDEV_TX_OK;

}

static void ipip6_tunnel_bind_dev(struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
 struct net_device *tdev = NULL;
 int hlen = LL_MAX_HEADER;
 const struct iphdr *iph;
 struct flowi4 fl4;

 iph = &tunnel->parms.iph;

 if (iph->daddr) {
  struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4,
         NULL,
         iph->daddr, iph->saddr,
         0, 0,
         IPPROTO_IPV6,
         iph->tos & INET_DSCP_MASK,
         tunnel->parms.link);

  if (!IS_ERR(rt)) {
   tdev = rt->dst.dev;
   ip_rt_put(rt);
  }
  dev->flags |= IFF_POINTOPOINT;
 }

 if (!tdev && tunnel->parms.link)
  tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);

 if (tdev && !netif_is_l3_master(tdev)) {
  int mtu;

  mtu = tdev->mtu - t_hlen;
  if (mtu < IPV6_MIN_MTU)
   mtu = IPV6_MIN_MTU;
  WRITE_ONCE(dev->mtu, mtu);
  hlen = tdev->hard_header_len + tdev->needed_headroom;
 }
 dev->needed_headroom = t_hlen + hlen;
}

static void ipip6_tunnel_update(struct ip_tunnel *t,
    struct ip_tunnel_parm_kern *p,
    __u32 fwmark)
{
 struct net *net = t->net;
 struct sit_net *sitn = net_generic(net, sit_net_id);

 ipip6_tunnel_unlink(sitn, t);
 synchronize_net();
 t->parms.iph.saddr = p->iph.saddr;
 t->parms.iph.daddr = p->iph.daddr;
 __dev_addr_set(t->dev, &p->iph.saddr, 4);
 memcpy(t->dev->broadcast, &p->iph.daddr, 4);
 ipip6_tunnel_link(sitn, t);
 t->parms.iph.ttl = p->iph.ttl;
 t->parms.iph.tos = p->iph.tos;
 t->parms.iph.frag_off = p->iph.frag_off;
 if (t->parms.link != p->link || t->fwmark != fwmark) {
  t->parms.link = p->link;
  t->fwmark = fwmark;
  ipip6_tunnel_bind_dev(t->dev);
 }
 dst_cache_reset(&t->dst_cache);
 netdev_state_change(t->dev);
}

#ifdef CONFIG_IPV6_SIT_6RD
static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
       struct ip_tunnel_6rd *ip6rd)
{
 struct in6_addr prefix;
 __be32 relay_prefix;

 if (ip6rd->relay_prefixlen > 32 ||
     ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64)
  return -EINVAL;

 ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen);
 if (!ipv6_addr_equal(&prefix, &ip6rd->prefix))
  return -EINVAL;
 if (ip6rd->relay_prefixlen)
  relay_prefix = ip6rd->relay_prefix &
          htonl(0xffffffffUL <<
         (32 - ip6rd->relay_prefixlen));
 else
  relay_prefix = 0;
 if (relay_prefix != ip6rd->relay_prefix)
  return -EINVAL;

 t->ip6rd.prefix = prefix;
 t->ip6rd.relay_prefix = relay_prefix;
 t->ip6rd.prefixlen = ip6rd->prefixlen;
 t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
 dst_cache_reset(&t->dst_cache);
 netdev_state_change(t->dev);
 return 0;
}

static int
ipip6_tunnel_get6rd(struct net_device *dev, struct ip_tunnel_parm __user *data)
{
 struct ip_tunnel *t = netdev_priv(dev);
 struct ip_tunnel_parm_kern p;
 struct ip_tunnel_6rd ip6rd;

 if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
  if (!ip_tunnel_parm_from_user(&p, data))
   return -EFAULT;
  t = ipip6_tunnel_locate(t->net, &p, 0);
 }
 if (!t)
  t = netdev_priv(dev);

 ip6rd.prefix = t->ip6rd.prefix;
 ip6rd.relay_prefix = t->ip6rd.relay_prefix;
 ip6rd.prefixlen = t->ip6rd.prefixlen;
 ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen;
 if (copy_to_user(data, &ip6rd, sizeof(ip6rd)))
  return -EFAULT;
 return 0;
}

static int
ipip6_tunnel_6rdctl(struct net_device *dev, struct ip_tunnel_6rd __user *data,
      int cmd)
{
 struct ip_tunnel *t = netdev_priv(dev);
 struct ip_tunnel_6rd ip6rd;
 int err;

 if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
  return -EPERM;
 if (copy_from_user(&ip6rd, data, sizeof(ip6rd)))
  return -EFAULT;

 if (cmd != SIOCDEL6RD) {
  err = ipip6_tunnel_update_6rd(t, &ip6rd);
  if (err < 0)
   return err;
 } else
  ipip6_tunnel_clone_6rd(dev, dev_to_sit_net(dev));
 return 0;
}

#endif /* CONFIG_IPV6_SIT_6RD */

static bool ipip6_valid_ip_proto(u8 ipproto)
{
 return ipproto == IPPROTO_IPV6 ||
  ipproto == IPPROTO_IPIP ||
#if IS_ENABLED(CONFIG_MPLS)
  ipproto == IPPROTO_MPLS ||
#endif
  ipproto == 0;
}

static int
__ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm_kern *p)
{
 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
  return -EPERM;

 if (!ipip6_valid_ip_proto(p->iph.protocol))
  return -EINVAL;
 if (p->iph.version != 4 ||
     p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)))
  return -EINVAL;

 if (p->iph.ttl)
  p->iph.frag_off |= htons(IP_DF);
 return 0;
}

static int
ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm_kern *p)
{
 struct ip_tunnel *t = netdev_priv(dev);

 if (dev == dev_to_sit_net(dev)->fb_tunnel_dev)
  t = ipip6_tunnel_locate(t->net, p, 0);
 if (!t)
  t = netdev_priv(dev);
 memcpy(p, &t->parms, sizeof(*p));
 return 0;
}

static int
ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm_kern *p)
{
 struct ip_tunnel *t = netdev_priv(dev);
 int err;

 err = __ipip6_tunnel_ioctl_validate(t->net, p);
 if (err)
  return err;

 t = ipip6_tunnel_locate(t->net, p, 1);
 if (!t)
  return -ENOBUFS;
 return 0;
}

static int
ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm_kern *p)
{
 struct ip_tunnel *t = netdev_priv(dev);
 int err;

 err = __ipip6_tunnel_ioctl_validate(t->net, p);
 if (err)
  return err;

 t = ipip6_tunnel_locate(t->net, p, 0);
 if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
  if (!t)
   return -ENOENT;
 } else {
  if (t) {
   if (t->dev != dev)
    return -EEXIST;
  } else {
   if (((dev->flags & IFF_POINTOPOINT) && !p->iph.daddr) ||
       (!(dev->flags & IFF_POINTOPOINT) && p->iph.daddr))
    return -EINVAL;
   t = netdev_priv(dev);
  }

  ipip6_tunnel_update(t, p, t->fwmark);
 }

 return 0;
}

static int
ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm_kern *p)
{
 struct ip_tunnel *t = netdev_priv(dev);

 if (!ns_capable(t->net->user_ns, CAP_NET_ADMIN))
  return -EPERM;

 if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
  t = ipip6_tunnel_locate(t->net, p, 0);
  if (!t)
   return -ENOENT;
  if (t == netdev_priv(dev_to_sit_net(dev)->fb_tunnel_dev))
   return -EPERM;
  dev = t->dev;
 }
 unregister_netdevice(dev);
 return 0;
}

static int
ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p,
   int cmd)
{
 switch (cmd) {
 case SIOCGETTUNNEL:
  return ipip6_tunnel_get(dev, p);
 case SIOCADDTUNNEL:
  return ipip6_tunnel_add(dev, p);
 case SIOCCHGTUNNEL:
  return ipip6_tunnel_change(dev, p);
 case SIOCDELTUNNEL:
  return ipip6_tunnel_del(dev, p);
 default:
  return -EINVAL;
 }
}

static int
ipip6_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
       void __user *data, int cmd)
{
 switch (cmd) {
 case SIOCGETTUNNEL:
 case SIOCADDTUNNEL:
 case SIOCCHGTUNNEL:
 case SIOCDELTUNNEL:
  return ip_tunnel_siocdevprivate(dev, ifr, data, cmd);
 case SIOCGETPRL:
  return ipip6_tunnel_get_prl(dev, data);
 case SIOCADDPRL:
 case SIOCDELPRL:
 case SIOCCHGPRL:
  return ipip6_tunnel_prl_ctl(dev, data, cmd);
#ifdef CONFIG_IPV6_SIT_6RD
 case SIOCGET6RD:
  return ipip6_tunnel_get6rd(dev, data);
 case SIOCADD6RD:
 case SIOCCHG6RD:
 case SIOCDEL6RD:
  return ipip6_tunnel_6rdctl(dev, data, cmd);
#endif
 default:
  return -EINVAL;
 }
}

static const struct net_device_ops ipip6_netdev_ops = {
 .ndo_init = ipip6_tunnel_init,
 .ndo_uninit = ipip6_tunnel_uninit,
 .ndo_start_xmit = sit_tunnel_xmit,
 .ndo_siocdevprivate = ipip6_tunnel_siocdevprivate,
 .ndo_get_iflink = ip_tunnel_get_iflink,
 .ndo_tunnel_ctl = ipip6_tunnel_ctl,
};

static void ipip6_dev_free(struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);

 dst_cache_destroy(&tunnel->dst_cache);
}

#define SIT_FEATURES (NETIF_F_SG    | \
        NETIF_F_FRAGLIST    | \
        NETIF_F_HIGHDMA    | \
        NETIF_F_GSO_SOFTWARE | \
        NETIF_F_HW_CSUM)

static void ipip6_tunnel_setup(struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 int t_hlen = tunnel->hlen + sizeof(struct iphdr);

 dev->netdev_ops  = &ipip6_netdev_ops;
 dev->header_ops  = &ip_tunnel_header_ops;
 dev->needs_free_netdev = true;
 dev->priv_destructor = ipip6_dev_free;

 dev->type  = ARPHRD_SIT;
 dev->mtu  = ETH_DATA_LEN - t_hlen;
 dev->min_mtu  = IPV6_MIN_MTU;
 dev->max_mtu  = IP6_MAX_MTU - t_hlen;
 dev->flags  = IFF_NOARP;
 netif_keep_dst(dev);
 dev->addr_len  = 4;
 dev->lltx  = true;
 dev->features  |= SIT_FEATURES;
 dev->hw_features |= SIT_FEATURES;
 dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;

}

static int ipip6_tunnel_init(struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 int err;

 tunnel->dev = dev;
 strcpy(tunnel->parms.name, dev->name);

 ipip6_tunnel_bind_dev(dev);

 err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
 if (err)
  return err;

 netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
 netdev_lockdep_set_classes(dev);
 return 0;
}

static void __net_init ipip6_fb_tunnel_init(struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 struct iphdr *iph = &tunnel->parms.iph;
 struct net *net = dev_net(dev);
 struct sit_net *sitn = net_generic(net, sit_net_id);

 iph->version  = 4;
 iph->protocol  = IPPROTO_IPV6;
 iph->ihl  = 5;
 iph->ttl  = 64;

 rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
}

static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[],
     struct netlink_ext_ack *extack)
{
 u8 proto;

 if (!data || !data[IFLA_IPTUN_PROTO])
  return 0;

 proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
 if (!ipip6_valid_ip_proto(proto))
  return -EINVAL;

 return 0;
}

static void ipip6_netlink_parms(struct nlattr *data[],
    struct ip_tunnel_parm_kern *parms,
    __u32 *fwmark)
{
 memset(parms, 0, sizeof(*parms));

 parms->iph.version = 4;
 parms->iph.protocol = IPPROTO_IPV6;
 parms->iph.ihl = 5;
 parms->iph.ttl = 64;

 if (!data)
  return;

 ip_tunnel_netlink_parms(data, parms);

 if (data[IFLA_IPTUN_FWMARK])
  *fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
}

#ifdef CONFIG_IPV6_SIT_6RD
/* This function returns true when 6RD attributes are present in the nl msg */
static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
        struct ip_tunnel_6rd *ip6rd)
{
 bool ret = false;
 memset(ip6rd, 0, sizeof(*ip6rd));

 if (!data)
  return ret;

 if (data[IFLA_IPTUN_6RD_PREFIX]) {
  ret = true;
  ip6rd->prefix = nla_get_in6_addr(data[IFLA_IPTUN_6RD_PREFIX]);
 }

 if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) {
  ret = true;
  ip6rd->relay_prefix =
   nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]);
 }

 if (data[IFLA_IPTUN_6RD_PREFIXLEN]) {
  ret = true;
  ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]);
 }

 if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) {
  ret = true;
  ip6rd->relay_prefixlen =
   nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
 }

 return ret;
}
#endif

static int ipip6_newlink(struct net_device *dev,
    struct rtnl_newlink_params *params,
    struct netlink_ext_ack *extack)
{
 struct nlattr **data = params->data;
 struct nlattr **tb = params->tb;
 struct ip_tunnel *nt;
 struct ip_tunnel_encap ipencap;
#ifdef CONFIG_IPV6_SIT_6RD
 struct ip_tunnel_6rd ip6rd;
#endif
 struct net *net;
 int err;

 net = params->link_net ? : dev_net(dev);
 nt = netdev_priv(dev);
 nt->net = net;

 if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
  err = ip_tunnel_encap_setup(nt, &ipencap);
  if (err < 0)
   return err;
 }

 ipip6_netlink_parms(data, &nt->parms, &nt->fwmark);

 if (ipip6_tunnel_locate(net, &nt->parms, 0))
  return -EEXIST;

 err = ipip6_tunnel_create(dev);
 if (err < 0)
  return err;

 if (tb[IFLA_MTU]) {
  u32 mtu = nla_get_u32(tb[IFLA_MTU]);

  if (mtu >= IPV6_MIN_MTU &&
      mtu <= IP6_MAX_MTU - dev->hard_header_len)
   dev->mtu = mtu;
 }

#ifdef CONFIG_IPV6_SIT_6RD
 if (ipip6_netlink_6rd_parms(data, &ip6rd)) {
  err = ipip6_tunnel_update_6rd(nt, &ip6rd);
  if (err < 0)
   unregister_netdevice_queue(dev, NULL);
 }
#endif

 return err;
}

static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
       struct nlattr *data[],
       struct netlink_ext_ack *extack)
{
 struct ip_tunnel *t = netdev_priv(dev);
 struct ip_tunnel_encap ipencap;
 struct ip_tunnel_parm_kern p;
 struct net *net = t->net;
 struct sit_net *sitn = net_generic(net, sit_net_id);
#ifdef CONFIG_IPV6_SIT_6RD
 struct ip_tunnel_6rd ip6rd;
#endif
 __u32 fwmark = t->fwmark;
 int err;

 if (dev == sitn->fb_tunnel_dev)
  return -EINVAL;

 if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
  err = ip_tunnel_encap_setup(t, &ipencap);
  if (err < 0)
   return err;
 }

 ipip6_netlink_parms(data, &p, &fwmark);

 if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
     (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
  return -EINVAL;

 t = ipip6_tunnel_locate(net, &p, 0);

 if (t) {
  if (t->dev != dev)
   return -EEXIST;
 } else
  t = netdev_priv(dev);

 ipip6_tunnel_update(t, &p, fwmark);

#ifdef CONFIG_IPV6_SIT_6RD
 if (ipip6_netlink_6rd_parms(data, &ip6rd))
  return ipip6_tunnel_update_6rd(t, &ip6rd);
#endif

 return 0;
}

static size_t ipip6_get_size(const struct net_device *dev)
{
 return
  /* IFLA_IPTUN_LINK */
  nla_total_size(4) +
  /* IFLA_IPTUN_LOCAL */
  nla_total_size(4) +
  /* IFLA_IPTUN_REMOTE */
  nla_total_size(4) +
  /* IFLA_IPTUN_TTL */
  nla_total_size(1) +
  /* IFLA_IPTUN_TOS */
  nla_total_size(1) +
  /* IFLA_IPTUN_PMTUDISC */
  nla_total_size(1) +
  /* IFLA_IPTUN_FLAGS */
  nla_total_size(2) +
  /* IFLA_IPTUN_PROTO */
  nla_total_size(1) +
#ifdef CONFIG_IPV6_SIT_6RD
  /* IFLA_IPTUN_6RD_PREFIX */
  nla_total_size(sizeof(struct in6_addr)) +
  /* IFLA_IPTUN_6RD_RELAY_PREFIX */
  nla_total_size(4) +
  /* IFLA_IPTUN_6RD_PREFIXLEN */
  nla_total_size(2) +
  /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
  nla_total_size(2) +
#endif
  /* IFLA_IPTUN_ENCAP_TYPE */
  nla_total_size(2) +
  /* IFLA_IPTUN_ENCAP_FLAGS */
  nla_total_size(2) +
  /* IFLA_IPTUN_ENCAP_SPORT */
  nla_total_size(2) +
  /* IFLA_IPTUN_ENCAP_DPORT */
  nla_total_size(2) +
  /* IFLA_IPTUN_FWMARK */
  nla_total_size(4) +
  0;
}

static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 struct ip_tunnel_parm_kern *parm = &tunnel->parms;

 if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
     nla_put_in_addr(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
     nla_put_in_addr(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
     nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
     nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
     nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
         !!(parm->iph.frag_off & htons(IP_DF))) ||
     nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
     nla_put_be16(skb, IFLA_IPTUN_FLAGS,
    ip_tunnel_flags_to_be16(parm->i_flags)) ||
     nla_put_u32(skb, IFLA_IPTUN_FWMARK, tunnel->fwmark))
  goto nla_put_failure;

#ifdef CONFIG_IPV6_SIT_6RD
 if (nla_put_in6_addr(skb, IFLA_IPTUN_6RD_PREFIX,
        &tunnel->ip6rd.prefix) ||
     nla_put_in_addr(skb, IFLA_IPTUN_6RD_RELAY_PREFIX,
       tunnel->ip6rd.relay_prefix) ||
     nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN,
   tunnel->ip6rd.prefixlen) ||
     nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
   tunnel->ip6rd.relay_prefixlen))
  goto nla_put_failure;
#endif

 if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
   tunnel->encap.type) ||
     nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT,
   tunnel->encap.sport) ||
     nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT,
   tunnel->encap.dport) ||
     nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
   tunnel->encap.flags))
  goto nla_put_failure;

 return 0;

nla_put_failure:
 return -EMSGSIZE;
}

static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
 [IFLA_IPTUN_LINK]  = { .type = NLA_U32 },
 [IFLA_IPTUN_LOCAL]  = { .type = NLA_U32 },
 [IFLA_IPTUN_REMOTE]  = { .type = NLA_U32 },
 [IFLA_IPTUN_TTL]  = { .type = NLA_U8 },
 [IFLA_IPTUN_TOS]  = { .type = NLA_U8 },
 [IFLA_IPTUN_PMTUDISC]  = { .type = NLA_U8 },
 [IFLA_IPTUN_FLAGS]  = { .type = NLA_U16 },
 [IFLA_IPTUN_PROTO]  = { .type = NLA_U8 },
#ifdef CONFIG_IPV6_SIT_6RD
 [IFLA_IPTUN_6RD_PREFIX]  = { .len = sizeof(struct in6_addr) },
 [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 },
 [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
 [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
#endif
 [IFLA_IPTUN_ENCAP_TYPE]  = { .type = NLA_U16 },
 [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
 [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
 [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
 [IFLA_IPTUN_FWMARK]  = { .type = NLA_U32 },
};

static void ipip6_dellink(struct net_device *dev, struct list_head *head)
{
 struct net *net = dev_net(dev);
 struct sit_net *sitn = net_generic(net, sit_net_id);

 if (dev != sitn->fb_tunnel_dev)
  unregister_netdevice_queue(dev, head);
}

static struct rtnl_link_ops sit_link_ops __read_mostly = {
 .kind  = "sit",
 .maxtype = IFLA_IPTUN_MAX,
 .policy  = ipip6_policy,
 .priv_size = sizeof(struct ip_tunnel),
 .setup  = ipip6_tunnel_setup,
 .validate = ipip6_validate,
 .newlink = ipip6_newlink,
 .changelink = ipip6_changelink,
 .get_size = ipip6_get_size,
 .fill_info = ipip6_fill_info,
 .dellink = ipip6_dellink,
 .get_link_net = ip_tunnel_get_link_net,
};

static struct xfrm_tunnel sit_handler __read_mostly = {
 .handler = ipip6_rcv,
 .err_handler = ipip6_err,
 .priority = 1,
};

static struct xfrm_tunnel ipip_handler __read_mostly = {
 .handler = ipip_rcv,
 .err_handler = ipip6_err,
 .priority = 2,
};

#if IS_ENABLED(CONFIG_MPLS)
static struct xfrm_tunnel mplsip_handler __read_mostly = {
 .handler = mplsip_rcv,
 .err_handler = ipip6_err,
 .priority = 2,
};
#endif

static void __net_exit sit_exit_rtnl_net(struct net *net, struct list_head *head)
{
 struct sit_net *sitn = net_generic(net, sit_net_id);
 struct net_device *dev, *aux;
 int prio;

 for_each_netdev_safe(net, dev, aux)
  if (dev->rtnl_link_ops == &sit_link_ops)
   unregister_netdevice_queue(dev, head);

 for (prio = 0; prio < 4; prio++) {
  int h;
  for (h = 0; h < (prio ? IP6_SIT_HASH_SIZE : 1); h++) {
   struct ip_tunnel *t;

   t = rtnl_net_dereference(net, sitn->tunnels[prio][h]);
   while (t) {
    /* If dev is in the same netns, it has already
 * been added to the list by the previous loop.
 */

    if (!net_eq(dev_net(t->dev), net))
     unregister_netdevice_queue(t->dev, head);

    t = rtnl_net_dereference(net, t->next);
   }
  }
 }
}

static int __net_init sit_init_net(struct net *net)
{
 struct sit_net *sitn = net_generic(net, sit_net_id);
 struct ip_tunnel *t;
 int err;

 sitn->tunnels[0] = sitn->tunnels_wc;
 sitn->tunnels[1] = sitn->tunnels_l;
 sitn->tunnels[2] = sitn->tunnels_r;
 sitn->tunnels[3] = sitn->tunnels_r_l;

 if (!net_has_fallback_tunnels(net))
  return 0;

 sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
        NET_NAME_UNKNOWN,
        ipip6_tunnel_setup);
 if (!sitn->fb_tunnel_dev) {
  err = -ENOMEM;
  goto err_alloc_dev;
 }
 dev_net_set(sitn->fb_tunnel_dev, net);
 sitn->fb_tunnel_dev->rtnl_link_ops = &sit_link_ops;
 /* FB netdevice is special: we have one, and only one per netns.
 * Allowing to move it to another netns is clearly unsafe.
 */

 sitn->fb_tunnel_dev->netns_immutable = true;

 t = netdev_priv(sitn->fb_tunnel_dev);
 t->net = net;

 err = register_netdev(sitn->fb_tunnel_dev);
 if (err)
  goto err_reg_dev;

 ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn);
 ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);

 strcpy(t->parms.name, sitn->fb_tunnel_dev->name);
 return 0;

err_reg_dev:
 free_netdev(sitn->fb_tunnel_dev);
err_alloc_dev:
 return err;
}

static struct pernet_operations sit_net_ops = {
 .init = sit_init_net,
 .exit_rtnl = sit_exit_rtnl_net,
 .id   = &sit_net_id,
 .size = sizeof(struct sit_net),
};

static void __exit sit_cleanup(void)
{
 rtnl_link_unregister(&sit_link_ops);
 xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
#if IS_ENABLED(CONFIG_MPLS)
 xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
#endif

 unregister_pernet_device(&sit_net_ops);
 rcu_barrier(); /* Wait for completion of call_rcu()'s */
}

static int __init sit_init(void)
{
 int err;

 pr_info("IPv6, IPv4 and MPLS over IPv4 tunneling driver\n");

 err = register_pernet_device(&sit_net_ops);
 if (err < 0)
  return err;
 err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
 if (err < 0) {
  pr_info("%s: can't register ip6ip4\n", __func__);
  goto xfrm_tunnel_failed;
 }
 err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
 if (err < 0) {
  pr_info("%s: can't register ip4ip4\n", __func__);
  goto xfrm_tunnel4_failed;
 }
#if IS_ENABLED(CONFIG_MPLS)
 err = xfrm4_tunnel_register(&mplsip_handler, AF_MPLS);
 if (err < 0) {
  pr_info("%s: can't register mplsip\n", __func__);
  goto xfrm_tunnel_mpls_failed;
 }
#endif
 err = rtnl_link_register(&sit_link_ops);
 if (err < 0)
  goto rtnl_link_failed;

out:
 return err;

rtnl_link_failed:
#if IS_ENABLED(CONFIG_MPLS)
 xfrm4_tunnel_deregister(&mplsip_handler, AF_MPLS);
xfrm_tunnel_mpls_failed:
#endif
 xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
xfrm_tunnel4_failed:
 xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
xfrm_tunnel_failed:
 unregister_pernet_device(&sit_net_ops);
 goto out;
}

module_init(sit_init);
module_exit(sit_cleanup);
MODULE_DESCRIPTION("IPv6-in-IPv4 tunnel SIT driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_RTNL_LINK("sit");
MODULE_ALIAS_NETDEV("sit0");

Messung V0.5
C=96 H=93 G=94

¤ Dauer der Verarbeitung: 0.20 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.