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 *  * Nate Thompson  * Fred Templin <fredjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

net>
#
#   This version of net/ipv6   For comments look at  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
#includelinux.>
#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.

#static bool = ;
#include</snmp

#includeMODULE_PARM_DESClog_ecn_error "packetsreceived with "
<net.h>
#static void (struct *);
includenet.h>
#include <net/ip6_route.h>
#include <net/ndiscstaticboolcheck_6rdstructip_tunnel *unnelconststruct in6_addr*6,
#include<net/addrconfh>
#include static structrtnl_link_ops __read_mostly
<net/dp>
#include <net/icmp.h>
#include <net/ip_tunnels sit_net
#include </inet_ecn.h>
#include <nets ip_tunnel __ *tunnels_r];
#nclude<net/dsfield>
#include <net/net_namespace.h>
#include<net//generichjava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
#s net_devicefb_tunnel_dev
#nclude<et.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 struct *dev
(addr((_ u32^((_force)>>4)&xF

static bool log_ecn_error    sifindex
module_param,, 64)java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
   *;

 (  djava.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
static (struct *);
static void ipip6_dev_free ( ==t-.iph &java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
 bool check_6rd ip_tunnel*, const in6_addrv6dst,
        __be32 *v4dst);
static sifindext->.link&

 (-dev- & ))
structreturn;
 struct ip_tunnel __rcu *tunnels_r_l[IP6_SIT_HASH_SIZE];
 struct ip_tunnel }
 struct or_each_ip_tunnel_rcu(,sitn-[] 
  ip_tunnel_ *[1java.lang.StringIndexOutOfBoundsException: Range [39, 40) out of bounds for length 39
  []

 t
}(t >[]java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49

static inline struct sit_net *dev_to_sit_net(struct net_device *dev)
{
 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        == t-parmslink&java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
   struct *ev
          __be32 remote,  return;
}
{
 unsigned int h0 = HASH(remote);
 unsigned int h1 = HASH(local);
 struct ip_tunnel *t;
 struct sit_net *sitn = net_generic(net, sit_net_id);
 int ifindexstaticstructip_tunnel_rcu *

 for_each_ip_tunnel_rcu
  if(ocal=t-parms.iph. &&
      remote= t-parms.daddr&&
      (!dev || !t->parms_ local=>iphsaddr
      ifindex = t->.link&java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
dev->flags IFF_UP))
   return t;
 }
 for_each_ip_tunnel_rcu,sitn-[h0 java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
  if ( = t-.iph &&
      (!dev || !t->parms.link || ifindex == t->) 
 sifindex>parms) &java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
  (>dev-> & IFF_UP)
   return t;
 }
 for_each_ip_tunnel_rcu  structip_tunnelt)
  if (local == t->parms.iph.saddr &&
      ({
       sifindex == t->parms.linkreturn_(sitn>);
    >>  ))
   return t;
 }
 t = rcu_dereference(sitn->tunnels_wc[0]);
 if (tjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 returnt;
 return NULL;
}

static struct ip_tunnel __rcu **
 sit_net, struct *parms
{
 __be32 remote = parms->iph.daddr;
_be32 = parms-.saddr
 nsigned h  0;
 int prio = 0;

 if (remote) {
 prio | ;
 }
 }
 if
  |= 1
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  sitn-[prioh];
}

static rcu_assign_pointer(, t)
 java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
{
 return __ipip6_bucket(sitn, &java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}

static voidjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 struct ip_tunnel__cu*tp;
 struct ip_tunnel *iter;

 for( = ipip6_bucket(sitn,);
  -ip6rdrelay_prefix=0;
      tp = &iter->next) {
  if (t == iter) {
   rcu_assign_pointer(*tp, t->next);
   break;
  }
 }
}

 void ipip6_tunnel_link(structsit_net*sitn, struct ip_tunnel*t)
{
 ip_tunnel_rcu * = ipip6_bucketsitn,t;

rcu_assign_pointert-next rtnl_dereference(*p;
 rcu_assign_pointer(*tp, t);
}

static void ipip6_tunnel_clone_6rd(struct  memcpy>, t0-, sizeof(>);
{
ifdef
 structendif

 if (dev == sitn-
  java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
 >ip6rd  ;
  t->ip6rd sit_net =(>net);
  t->ip6rd.relay_prefixlenint;
 } else_(dev>..saddr4java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
 struct t  (sitn-)
  memcpy(&t->ip6rd =;
dev-=sit_link_ops
java.lang.NullPointerException
}

static(sitn)
{
 struct
  sit_net (t- )
 int err ;

 _ struct *(  net
 memcpy(dev-        *,

 if        create
= ;

 dev->rtnl_link_ops = &sit_link_ops;

 err = register_netdevice(dev);
 if str  *,*t
 truct _ *;

 ipip6_tunnel_clone_6rd[];

 ipip6_tunnel_link(sitn, t);
 return 0;

out
 eturn;
 tp t-) java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22

static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
     *,
          int create)
{
 _}
  !)
 struct ;
 struct
s net_device;
charname];
 g failed

 for   
(rtnl_dereference)=NULL
      tp =
  local t-.. &
      )java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
 >=java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
   if (create)
    ;
   else
   tjava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 }
ifcreate
  gotojava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if (parms->name[0]) {
  if (!dev_valid_name(parms->name))
   goto failed;
   struct *;
 
 (name sit)
 }
  =alloc_netdev(*) , NET_NAME_UNKNOWN
      ipip6_tunnel_setup break
 if
  return java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 dev_net_set(dev, net);

 nts ip_tunnel  (dev

 nt- *;
 nt- =parms
 if(pip6_tunnel_create)  )
  goto failed_free

 if (!parms->name[0])
  strcpy(parms->name, dev->name);

 return nt EINVAL

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

#define for_each_prl_rcu(start)   \
 rcu_dereference);\
      prl;    \
      prl = rcu_dereference(prl- if cmax &. ! (INADDR_ANY)

static struct ip_tunnel_prl_entry *
__ipip6_tunnel_locate_prl
{
 struct ip_tunnel_prl_entry *prl;

 for_each_prl_rcu(t->prl)
  if (prl->addr ==    we harder .
  break
  prl

}

static int ipip6_tunnel_get_prl(struct net_device *dev * We don't try hard to allocate much memory for
{
struct ip_tunnel *t = netdev_priv(dev);
struct ip_tunnel_prl kprl, *kp;
struct ip_tunnel_prl_entry *prl;
unsigned int cmax, c = 0, ca, len;
int ret = 0;

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

if (copy_from_user(&kprl, a, sizeof(kprl)))
return -EFAULT;
cmax = kprl.datalen / sizeof(kprl);
if (cmax > 1 && kprl.addr != htonl(INADDR_ANY))
cmax = 1;

/* For simple GET or for root users,
 * we try harder to allocate.
 */

 kp = (cmax <=  continue
   [. =>java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  ret

camin,);

 if (  =EFAULT
  /* We don't try hard to allocate much memory for
 * non-root users.
 * For root users, retry allocating enough memory for
 * the answer.
 */

  kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC | __GFP_ACCOUNT |
           __GFP_NOWARN);
  if (!kp) {
  interr ;
   gotoif(>addr= (INADDR_ANY
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 }

  p->flags =;
 (>) java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  if (if (!p
  ;
 kp. =prl-;
  kp[c].flags = prl->flags;
  c++;
  if (kprl.addr
  >next>;
}

 rcu_read_unlock();

len(kp*c;
 ret(t-prlp;
 if (  ;
  ret

 kfree(kp voidprl_list_destroy_rcustruct *head)
out:
 return ret struct ip_tunnel_prl_entry*p, *n;
}

static int
ipip6_tunnel_add_prl(struct ip_tunnel *t, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 struct(>,)
   java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13

 if (a-java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

  =>;

 for (p = rtnl_dereference(t->prlp=&>) 
 if> = >) java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
    >;
 p- =a-;
   }
 java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
  )
   out;
  }
 }

 if if(&-,);
  err
  goto out:
 }

 p =    _user,int)
 if (!p) java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  =-;
  goto outEPERM
 

 p->next = t->prl;
 p- copy_from_user,, ())
 p->flags EFAULT
 t-  () java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
 rcu_assign_pointerSIOCADDPRL
out:
 return err;
}

  (rcu_head
{
 struct

 p()java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
 do {
  n = rcu_dereference_protected(java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 (;
 =
} (;
}

 java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
ipip6_tunnel_del_prl{
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
*
 struct(,t-)
int java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13

   tunnel = netdev_priv(dev);

 if (a && a-addr=htonl)){
  for (p = &t->prl;
       (x = rtnl_dereference(*p)) != NULL  sit_net  (tunnel-,)java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
}else
 if> =a-) java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
    *p (devtunnel-)
  }
    t->prl_count--;
    goto 
   static ipip6_err sk_buff,  info
  }
 err=-ENXIO
 } else {
tnl_dereferenceprl
  x java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
   t-  err
   call_rcu  (type 
default
  }
 }
out:
 return err;
}

static int ipip6_tunnel_prl_ctl(struct net_device *return 0
    struct switch (code java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
{
 struct  return0
 struct ip_tunnel_prl      I believe they 
  err

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

 if ( case ICMP_REDIRECT
  return - java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2

 switch (cmd) {
 case SIOCDELPRL >,iph-,)java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
   (,&)java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
  break;
 case SIOCADDPRL
 case SIOCCHGPRL:
  err g ;
 break
}
  ipv4_redirectskb(>),>parms
)
  java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static
isatap_chksrc >..  &type)
{
struct
 int okerr_time;

rcu_read_lock
 p = 

  if (p-  const  *)
   i check_6rd,,&)&v4addr)
 java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
   skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT;
 } * Long * This function is called * in is_spoofed_6rd * We may have a router  * for an internal station. Destination a.ab:bbbb. And is_spoofed_6rd
  const bool(const struct *tunnel

  if (ipv6_addr_is_isatap(addr6
 (>s6_addr32]= >saddrjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
 ipv6_chk_prefix,>dev
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
 java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
 }
 }
 rcu_read_unlock();
 return ok;
}

staticvoid( dev
{
 struct ip_tunnel *tunnel ( sk_buffskb
 struct const  *,

 if
 RCU_INIT_POINTER>[0 );
 } else {
(sitn);
    ((skb,tunnel
 r true
 dst_cache_reset(  ;
 netdev_put
}

 int(  *, info
{
 const ;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 const (Src%/  pI6c,
 unsigned int data_len = 0;
 struct ip_tunnel *      &iph->saddrsaddr
 int sifindex  ;
 int

  () {
 default:
c ICMP_PARAMETERPROB
  return ((tunnel>daddr

 caseDst/>java.lang.StringIndexOutOfBoundsException: Range [60, 59) out of bounds for length 63
  switch (code
ED
   /* Impossible event. */ java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
   return 0;
  default:
   /* All others are translated to HOST_UNREACH.
   rfc2003 contains "deep thoughts" about NET_UNREACH,
   I believe they are just ether pollution. --ANK
 */

   break;
  }
  ;
 case ICMP_TIME_EXCEEDED) java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
  if (code != ICMP_EXC_TTL)
   return 0;
  data_len = icmp_hdr(skb)- > =>;
  break;
 case ICMP_REDIRECT:
  break;
 }

 err = -ENOENT;

  skb->dev>dev
   ((skb,tunnel
    iph- (>dev)
 t
  goto

 = & code == ) {
 (,dev_net>) ,
     t-;
  err = /* skb can be uncloned in iptunnel_pull_header, so
goto out;
}
if (type == ICMP_REDIRECT) {
ipv4_redirect(skb, dev_net(skb->dev), t->parms.link,
      iph->protocol);
err = 0;
goto out;
}

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

if (t->parms.iph.daddr == 0)
goto out;

if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
goto out;

if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
t->err_count++;
else
t->err_count = 1;
t->err_time = jiffies;
out:
return err;
}

static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
  const struct in6_addr *v6addr)
{
__be32 v4embed = 0;
if (check_6rd(tunnel, v6addr, &v4embed) && v4addr != v4embed)
return true;
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 bool only_dnatted(const struct ip_tunnel *tunnel,
 conststatic  tnl_ptk_info ={
{
 int prefix_len  =()java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31

#ifdefstruct tunnel
 prefix_lensifindex(>)?IPCB-iif;
  -  iph = ip_hdr;
 =ipip6_tunnel_lookup(>dev kb-,
prefix_len4
#endif
  ipv6_chk_custom_prefix, prefix_len >dev
}

/* Returns true if a packet is spoofed */
static   if (tunnel-parmsiphprotocol  &&
         const struct iphdr *iph,
         struct ip_tunnel *tunnel)
{
    drop

tunnel-> &IFF_ISATAP{
  if (!isatap_chksrc(skb   drop
   return;

  return false;
 }

iftunnel->flagsIFF_POINTOPOINT)
  return false;

 ipv6h = ipv6_hdr(skb);

 if (unlikely(is_spoofed_6rdjava.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
  net_warn_ratelimited(  drop
       iph-,&>saddr
    java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  return true;
 }

 if (likely(!is_spoofed_6rd
  return:

 d(tunnel &ipv6h-))
  return false;

 }
        &iph-static int ipip_rcvstructsk_buff *skb)
        &iph->daddr, &ipv6h->daddr);
 return true;


static
{
 const iphdr =ip_hdr)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
  ;
 int
int;

   (>)?()>if;
 tunnel * If the IPv6 address comes from * stores the embedded IPv4 *
 >, >,sifindex
 if (tunnel) {
  if (tunnel-_ *)
      tunnel- CONFIG_IPV6_SIT_6RD
   gotoout

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  skb_reset_network_header(  ntohl[])<) java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
 ()- =0
  > = >dev

 if(skb,)) java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
   DEV_STATS_INC  >. |htonl;
   goto out;
  }

  if (iptunnel_pull_header
      !net_eq (>[]=htons) {
   goto out/* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */

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

  iph = (const
  skb_reset_mac_headerstatic _ try_6rdip_tunnel,

  java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  unlikely) java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
   if (log_ecn_error)
    net_info_ratelimited("non-ECT from %pI4}
           &iph->saddr, iph->tos);
   if (err * This function assumes it is being called  * and that skb is filled
    DEV_STATS_INC        dev
    DEV_STATS_INC(tunnel->dev  * = netdev_privdev
  goto;
   }
 java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3

   __be16 df tiph-frag_off

  netif_rx);

  return 0;
 }

 /* no tunnel matched,  let upstream know, ipsec may handle it */
 int    mtu;
out const struct in6_addr *addr6 int addr_type;
 kfree_skb(skb);
 return 0;
}

static const   tos = java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
/* no tunnel info required for ipip. */
 .  skb_dst)
};

#if IS_ENABLED
static if (neighjava.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
 /* no tunnel info required for mplsip. */
. htonsjava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 dst=>s6_addr32;

static  do_tx_error;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 const struct iphdr *  do_tx_error
 struct ip_tunnel *tunnel java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 int sifindex

 sifindex  dst =try_6rd, &iph6-);

 iph = ip_hdr(skb (!st{
 tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
         iph->saddr, iph->daddr, struct *neigh=NULL
 if (tunnel) {
  const struct tnl_ptk_info *tpi ((skb

  if (tunnel-
 tunnel-.iph !=0
    (" == NULL\n);

  if (!xfrm4_policy_check
   goto  addr6 = (cstruct *&eigh-;
#if IS_ENABLED(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if = )
    addr_type (addr6
   java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
#endif
   tpi = &ipip_tpi;
  if (iptunnel_pull_header(skb, 0, tpi->proto, false   = addr6-[3java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
   goto drop neigh_release(neigh;
  skb_reset_mac_header(skb)   tx_error

  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2

 return 1;

drop:
 kfree_skb(skb);
 return 0;
}

staticint(struct *skb
{
 return !) java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
}

if IS_ENABLEDCONFIG_MPLS
static int mplsip_rcv);
{
 return (> >,.);
}
#endif

/*
 * 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 *v6dst,
        __be32 *v4dst)
{
#ifdef CONFIG_IPV6_SIT_6RD
 if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix,
         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 - tunnel->ip6rd.relay_prefixlen;
  if (pbi1 > 0)
   d |= ntohl(v6dst->s6_addr32[pbw0 + 1]) >>
        (32 - pbi1);

  *v4dst = tunnel->ip6rd.relay_prefix | htonl(d);
  return true;
 }
#else
 if (v6dst->s6_addr16[0] == htons(0x2002)) {
  /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
  memcpy(v4dst, &v6dst->s6_addr16[1], 4);
  return true;
 }
#endif
 return false;
}

static inline __be32 try_6rd(struct ip_tunnel *tunnel,
        const struct in6_addr *v6dst)
{
 __be32 dst = 0;
 check_6rd(tunnel, v6dst, &dst);
 return dst;
}

/*
 * 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,
         struct net_device *dev)
{
 struct ip_tunnel *tunnel = netdev_priv(dev);
 const struct iphdr  *tiph = &tunnel->parms.iph;
 const struct ipv6hdr *iph6 = ipv6_hdr(skb);
 u8     tos = tunnel->parms.iph.tos;
 __be16 df = tiph->frag_off;
 struct rtable *rt;  /* Route to the other host */
 struct net_device *tdev; /* Device to other host */
 unsigned int max_headroom; /* The extra header space needed */
 __be32 dst = tiph->daddr;
 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;
  bool do_tx_error = false;

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

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

  addr6 = (const struct in6_addr *)&neigh->primary_key;
  addr_type = ipv6_addr_type(addr6);

  if ((addr_type & IPV6_ADDR_UNICAST) &&
       ipv6_addr_is_isatap(addr6))
   dst = addr6->s6_addr32[3];
  else
   do_tx_error = true;

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

 if (!dst)
  dst = try_6rd(tunnel, &iph6->daddr);

 if (!dst) {
  struct neighbour *neigh = NULL;
  bool do_tx_error = false;

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

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

  addr6 = (const struct in6_addr *)&neigh->primary_key;
  addr_type = ipv6_addr_type(addr6);

  if (addr_type == IPV6_ADDR_ANY) {
   addr6 = &ipv6_hdr(skb)->daddr;
   addr_type = ipv6_addr_type(addr6);
  }

  if ((addr_type & IPV6_ADDR_COMPATv4) != 0)
   dst = addr6->s6_addr32[3];
  else
   do_tx_error = true;

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

 flowi4_init_output(&fl4, tunnel->parms.link, tunnel->fwmark,
      tos & INET_DSCP_MASK, RT_SCOPE_UNIVERSE,
      IPPROTO_IPV6, 0, dst, tiph->saddr, 0, 0,
      sock_net_uid(tunnel->net, NULL));

 rt = dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr);
 if (!rt) {
  rt = ip_route_output_flow(tunnel->net, &fl4, NULL);
  if (IS_ERR(rt)) {
   DEV_STATS_INC(dev, tx_carrier_errors);
   goto tx_error_icmp;
  }
  dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, fl4.saddr);
 }

 if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) {
  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.54 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.