File Index
Files and directories
Sign in
FILE

exthdrs.c

File preview with syntax highlighting.

linux-6.19.14/net/ipv6/exthdrs.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *	Extension Header handling for IPv6
   4 *	Linux INET6 implementation
   5 *
   6 *	Authors:
   7 *	Pedro Roque		<roque@di.fc.ul.pt>
   8 *	Andi Kleen		<ak@muc.de>
   9 *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  10 */
  11
  12/* Changes:
  13 *	yoshfuji		: ensure not to overrun while parsing
  14 *				  tlv options.
  15 *	Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
  16 *	YOSHIFUJI Hideaki @USAGI  Register inbound extension header
  17 *				  handlers as inet6_protocol{}.
  18 */
  19
  20#include <linux/errno.h>
  21#include <linux/types.h>
  22#include <linux/socket.h>
  23#include <linux/sockios.h>
  24#include <linux/net.h>
  25#include <linux/netdevice.h>
  26#include <linux/in6.h>
  27#include <linux/icmpv6.h>
  28#include <linux/slab.h>
  29#include <linux/export.h>
  30
  31#include <net/dst.h>
  32#include <net/sock.h>
  33#include <net/snmp.h>
  34
  35#include <net/ipv6.h>
  36#include <net/protocol.h>
  37#include <net/transp_v6.h>
  38#include <net/rawv6.h>
  39#include <net/ndisc.h>
  40#include <net/ip6_route.h>
  41#include <net/addrconf.h>
  42#include <net/calipso.h>
  43#if IS_ENABLED(CONFIG_IPV6_MIP6)
  44#include <net/xfrm.h>
  45#endif
  46#include <linux/seg6.h>
  47#include <net/seg6.h>
  48#ifdef CONFIG_IPV6_SEG6_HMAC
  49#include <net/seg6_hmac.h>
  50#endif
  51#include <net/rpl.h>
  52#include <linux/ioam6.h>
  53#include <linux/ioam6_genl.h>
  54#include <net/ioam6.h>
  55#include <net/dst_metadata.h>
  56
  57#include <linux/uaccess.h>
  58
  59/*********************
  60  Generic functions
  61 *********************/
  62
  63/* An unknown option is detected, decide what to do */
  64
  65static bool ip6_tlvopt_unknown(struct sk_buff *skb, int optoff,
  66			       bool disallow_unknowns)
  67{
  68	if (disallow_unknowns) {
  69		/* If unknown TLVs are disallowed by configuration
  70		 * then always silently drop packet. Note this also
  71		 * means no ICMP parameter problem is sent which
  72		 * could be a good property to mitigate a reflection DOS
  73		 * attack.
  74		 */
  75
  76		goto drop;
  77	}
  78
  79	switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
  80	case 0: /* ignore */
  81		return true;
  82
  83	case 1: /* drop packet */
  84		break;
  85
  86	case 3: /* Send ICMP if not a multicast address and drop packet */
  87		/* Actually, it is redundant check. icmp_send
  88		   will recheck in any case.
  89		 */
  90		if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
  91			break;
  92		fallthrough;
  93	case 2: /* send ICMP PARM PROB regardless and drop packet */
  94		icmpv6_param_prob_reason(skb, ICMPV6_UNK_OPTION, optoff,
  95					 SKB_DROP_REASON_UNHANDLED_PROTO);
  96		return false;
  97	}
  98
  99drop:
 100	kfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO);
 101	return false;
 102}
 103
 104static bool ipv6_hop_ra(struct sk_buff *skb, int optoff);
 105static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff);
 106static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff);
 107static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff);
 108#if IS_ENABLED(CONFIG_IPV6_MIP6)
 109static bool ipv6_dest_hao(struct sk_buff *skb, int optoff);
 110#endif
 111
 112/* Parse tlv encoded option header (hop-by-hop or destination) */
 113
 114static bool ip6_parse_tlv(bool hopbyhop,
 115			  struct sk_buff *skb,
 116			  int max_count)
 117{
 118	int len = (skb_transport_header(skb)[1] + 1) << 3;
 119	const unsigned char *nh = skb_network_header(skb);
 120	int off = skb_network_header_len(skb);
 121	bool disallow_unknowns = false;
 122	int tlv_count = 0;
 123	int padlen = 0;
 124
 125	if (unlikely(max_count < 0)) {
 126		disallow_unknowns = true;
 127		max_count = -max_count;
 128	}
 129
 130	off += 2;
 131	len -= 2;
 132
 133	while (len > 0) {
 134		int optlen, i;
 135
 136		if (nh[off] == IPV6_TLV_PAD1) {
 137			padlen++;
 138			if (padlen > 7)
 139				goto bad;
 140			off++;
 141			len--;
 142			continue;
 143		}
 144		if (len < 2)
 145			goto bad;
 146		optlen = nh[off + 1] + 2;
 147		if (optlen > len)
 148			goto bad;
 149
 150		if (nh[off] == IPV6_TLV_PADN) {
 151			/* RFC 2460 states that the purpose of PadN is
 152			 * to align the containing header to multiples
 153			 * of 8. 7 is therefore the highest valid value.
 154			 * See also RFC 4942, Section 2.1.9.5.
 155			 */
 156			padlen += optlen;
 157			if (padlen > 7)
 158				goto bad;
 159			/* RFC 4942 recommends receiving hosts to
 160			 * actively check PadN payload to contain
 161			 * only zeroes.
 162			 */
 163			for (i = 2; i < optlen; i++) {
 164				if (nh[off + i] != 0)
 165					goto bad;
 166			}
 167		} else {
 168			tlv_count++;
 169			if (tlv_count > max_count)
 170				goto bad;
 171
 172			if (hopbyhop) {
 173				switch (nh[off]) {
 174				case IPV6_TLV_ROUTERALERT:
 175					if (!ipv6_hop_ra(skb, off))
 176						return false;
 177					break;
 178				case IPV6_TLV_IOAM:
 179					if (!ipv6_hop_ioam(skb, off))
 180						return false;
 181
 182					nh = skb_network_header(skb);
 183					break;
 184				case IPV6_TLV_JUMBO:
 185					if (!ipv6_hop_jumbo(skb, off))
 186						return false;
 187					break;
 188				case IPV6_TLV_CALIPSO:
 189					if (!ipv6_hop_calipso(skb, off))
 190						return false;
 191					break;
 192				default:
 193					if (!ip6_tlvopt_unknown(skb, off,
 194								disallow_unknowns))
 195						return false;
 196					break;
 197				}
 198			} else {
 199				switch (nh[off]) {
 200#if IS_ENABLED(CONFIG_IPV6_MIP6)
 201				case IPV6_TLV_HAO:
 202					if (!ipv6_dest_hao(skb, off))
 203						return false;
 204					break;
 205#endif
 206				default:
 207					if (!ip6_tlvopt_unknown(skb, off,
 208								disallow_unknowns))
 209						return false;
 210					break;
 211				}
 212			}
 213			padlen = 0;
 214		}
 215		off += optlen;
 216		len -= optlen;
 217	}
 218
 219	if (len == 0)
 220		return true;
 221bad:
 222	kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
 223	return false;
 224}
 225
 226/*****************************
 227  Destination options header.
 228 *****************************/
 229
 230#if IS_ENABLED(CONFIG_IPV6_MIP6)
 231static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
 232{
 233	struct ipv6_destopt_hao *hao;
 234	struct inet6_skb_parm *opt = IP6CB(skb);
 235	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 236	SKB_DR(reason);
 237	int ret;
 238
 239	if (opt->dsthao) {
 240		net_dbg_ratelimited("hao duplicated\n");
 241		goto discard;
 242	}
 243	opt->dsthao = opt->dst1;
 244	opt->dst1 = 0;
 245
 246	hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
 247
 248	if (hao->length != 16) {
 249		net_dbg_ratelimited("hao invalid option length = %d\n",
 250				    hao->length);
 251		SKB_DR_SET(reason, IP_INHDR);
 252		goto discard;
 253	}
 254
 255	if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
 256		net_dbg_ratelimited("hao is not an unicast addr: %pI6\n",
 257				    &hao->addr);
 258		SKB_DR_SET(reason, INVALID_PROTO);
 259		goto discard;
 260	}
 261
 262	ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
 263			       (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
 264	if (unlikely(ret < 0)) {
 265		SKB_DR_SET(reason, XFRM_POLICY);
 266		goto discard;
 267	}
 268
 269	if (skb_cloned(skb)) {
 270		if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 271			goto discard;
 272
 273		/* update all variable using below by copied skbuff */
 274		hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) +
 275						  optoff);
 276		ipv6h = ipv6_hdr(skb);
 277	}
 278
 279	if (skb->ip_summed == CHECKSUM_COMPLETE)
 280		skb->ip_summed = CHECKSUM_NONE;
 281
 282	swap(ipv6h->saddr, hao->addr);
 283
 284	if (skb->tstamp == 0)
 285		__net_timestamp(skb);
 286
 287	return true;
 288
 289 discard:
 290	kfree_skb_reason(skb, reason);
 291	return false;
 292}
 293#endif
 294
 295static int ipv6_destopt_rcv(struct sk_buff *skb)
 296{
 297	struct inet6_dev *idev = __in6_dev_get(skb->dev);
 298	struct inet6_skb_parm *opt = IP6CB(skb);
 299#if IS_ENABLED(CONFIG_IPV6_MIP6)
 300	__u16 dstbuf;
 301#endif
 302	struct dst_entry *dst = skb_dst(skb);
 303	struct net *net = dev_net(skb->dev);
 304	int extlen;
 305
 306	if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
 307	    !pskb_may_pull(skb, (skb_transport_offset(skb) +
 308				 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 309		__IP6_INC_STATS(dev_net(dst_dev(dst)), idev,
 310				IPSTATS_MIB_INHDRERRORS);
 311fail_and_free:
 312		kfree_skb(skb);
 313		return -1;
 314	}
 315
 316	extlen = (skb_transport_header(skb)[1] + 1) << 3;
 317	if (extlen > READ_ONCE(net->ipv6.sysctl.max_dst_opts_len))
 318		goto fail_and_free;
 319
 320	opt->lastopt = opt->dst1 = skb_network_header_len(skb);
 321#if IS_ENABLED(CONFIG_IPV6_MIP6)
 322	dstbuf = opt->dst1;
 323#endif
 324
 325	if (ip6_parse_tlv(false, skb,
 326			  READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt))) {
 327		skb->transport_header += extlen;
 328		opt = IP6CB(skb);
 329#if IS_ENABLED(CONFIG_IPV6_MIP6)
 330		opt->nhoff = dstbuf;
 331#else
 332		opt->nhoff = opt->dst1;
 333#endif
 334		return 1;
 335	}
 336
 337	__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 338	return -1;
 339}
 340
 341static void seg6_update_csum(struct sk_buff *skb)
 342{
 343	struct ipv6_sr_hdr *hdr;
 344	struct in6_addr *addr;
 345	__be32 from, to;
 346
 347	/* srh is at transport offset and seg_left is already decremented
 348	 * but daddr is not yet updated with next segment
 349	 */
 350
 351	hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
 352	addr = hdr->segments + hdr->segments_left;
 353
 354	hdr->segments_left++;
 355	from = *(__be32 *)hdr;
 356
 357	hdr->segments_left--;
 358	to = *(__be32 *)hdr;
 359
 360	/* update skb csum with diff resulting from seg_left decrement */
 361
 362	update_csum_diff4(skb, from, to);
 363
 364	/* compute csum diff between current and next segment and update */
 365
 366	update_csum_diff16(skb, (__be32 *)(&ipv6_hdr(skb)->daddr),
 367			   (__be32 *)addr);
 368}
 369
 370static int ipv6_srh_rcv(struct sk_buff *skb)
 371{
 372	struct inet6_skb_parm *opt = IP6CB(skb);
 373	struct net *net = dev_net(skb->dev);
 374	struct ipv6_sr_hdr *hdr;
 375	struct inet6_dev *idev;
 376	struct in6_addr *addr;
 377	int accept_seg6;
 378
 379	hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
 380
 381	idev = __in6_dev_get(skb->dev);
 382	if (!idev) {
 383		kfree_skb(skb);
 384		return -1;
 385	}
 386
 387	accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled),
 388			  READ_ONCE(idev->cnf.seg6_enabled));
 389
 390	if (!accept_seg6) {
 391		kfree_skb(skb);
 392		return -1;
 393	}
 394
 395#ifdef CONFIG_IPV6_SEG6_HMAC
 396	if (!seg6_hmac_validate_skb(skb)) {
 397		kfree_skb(skb);
 398		return -1;
 399	}
 400#endif
 401
 402looped_back:
 403	if (hdr->segments_left == 0) {
 404		if (hdr->nexthdr == NEXTHDR_IPV6 || hdr->nexthdr == NEXTHDR_IPV4) {
 405			int offset = (hdr->hdrlen + 1) << 3;
 406
 407			skb_postpull_rcsum(skb, skb_network_header(skb),
 408					   skb_network_header_len(skb));
 409			skb_pull(skb, offset);
 410			skb_postpull_rcsum(skb, skb_transport_header(skb),
 411					   offset);
 412
 413			skb_reset_network_header(skb);
 414			skb_reset_transport_header(skb);
 415			skb->encapsulation = 0;
 416			if (hdr->nexthdr == NEXTHDR_IPV4)
 417				skb->protocol = htons(ETH_P_IP);
 418			__skb_tunnel_rx(skb, skb->dev, net);
 419
 420			netif_rx(skb);
 421			return -1;
 422		}
 423
 424		opt->srcrt = skb_network_header_len(skb);
 425		opt->lastopt = opt->srcrt;
 426		skb->transport_header += (hdr->hdrlen + 1) << 3;
 427		opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
 428
 429		return 1;
 430	}
 431
 432	if (hdr->segments_left >= (hdr->hdrlen >> 1)) {
 433		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 434		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 435				  ((&hdr->segments_left) -
 436				   skb_network_header(skb)));
 437		return -1;
 438	}
 439
 440	if (skb_cloned(skb)) {
 441		if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 442			__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 443					IPSTATS_MIB_OUTDISCARDS);
 444			kfree_skb(skb);
 445			return -1;
 446		}
 447
 448		hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
 449	}
 450
 451	hdr->segments_left--;
 452	addr = hdr->segments + hdr->segments_left;
 453
 454	skb_push(skb, sizeof(struct ipv6hdr));
 455
 456	if (skb->ip_summed == CHECKSUM_COMPLETE)
 457		seg6_update_csum(skb);
 458
 459	ipv6_hdr(skb)->daddr = *addr;
 460
 461	ip6_route_input(skb);
 462
 463	if (skb_dst(skb)->error) {
 464		dst_input(skb);
 465		return -1;
 466	}
 467
 468	if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
 469		if (ipv6_hdr(skb)->hop_limit <= 1) {
 470			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 471			icmpv6_send(skb, ICMPV6_TIME_EXCEED,
 472				    ICMPV6_EXC_HOPLIMIT, 0);
 473			kfree_skb(skb);
 474			return -1;
 475		}
 476		ipv6_hdr(skb)->hop_limit--;
 477
 478		skb_pull(skb, sizeof(struct ipv6hdr));
 479		goto looped_back;
 480	}
 481
 482	dst_input(skb);
 483
 484	return -1;
 485}
 486
 487static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
 488{
 489	struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr;
 490	struct inet6_skb_parm *opt = IP6CB(skb);
 491	struct net *net = dev_net(skb->dev);
 492	struct inet6_dev *idev;
 493	struct ipv6hdr *oldhdr;
 494	unsigned char *buf;
 495	int accept_rpl_seg;
 496	int i, err;
 497	u64 n = 0;
 498	u32 r;
 499
 500	idev = __in6_dev_get(skb->dev);
 501
 502	accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
 503			     READ_ONCE(idev->cnf.rpl_seg_enabled));
 504	if (!accept_rpl_seg) {
 505		kfree_skb(skb);
 506		return -1;
 507	}
 508
 509looped_back:
 510	hdr = (struct ipv6_rpl_sr_hdr *)skb_transport_header(skb);
 511
 512	if (hdr->segments_left == 0) {
 513		if (hdr->nexthdr == NEXTHDR_IPV6) {
 514			int offset = (hdr->hdrlen + 1) << 3;
 515
 516			skb_postpull_rcsum(skb, skb_network_header(skb),
 517					   skb_network_header_len(skb));
 518			skb_pull(skb, offset);
 519			skb_postpull_rcsum(skb, skb_transport_header(skb),
 520					   offset);
 521
 522			skb_reset_network_header(skb);
 523			skb_reset_transport_header(skb);
 524			skb->encapsulation = 0;
 525
 526			__skb_tunnel_rx(skb, skb->dev, net);
 527
 528			netif_rx(skb);
 529			return -1;
 530		}
 531
 532		opt->srcrt = skb_network_header_len(skb);
 533		opt->lastopt = opt->srcrt;
 534		skb->transport_header += (hdr->hdrlen + 1) << 3;
 535		opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
 536
 537		return 1;
 538	}
 539
 540	n = (hdr->hdrlen << 3) - hdr->pad - (16 - hdr->cmpre);
 541	r = do_div(n, (16 - hdr->cmpri));
 542	/* checks if calculation was without remainder and n fits into
 543	 * unsigned char which is segments_left field. Should not be
 544	 * higher than that.
 545	 */
 546	if (r || (n + 1) > 255) {
 547		kfree_skb(skb);
 548		return -1;
 549	}
 550
 551	if (hdr->segments_left > n + 1) {
 552		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 553		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 554				  ((&hdr->segments_left) -
 555				   skb_network_header(skb)));
 556		return -1;
 557	}
 558
 559	hdr->segments_left--;
 560	i = n - hdr->segments_left;
 561
 562	buf = kcalloc(struct_size(hdr, segments.addr, n + 2), 2, GFP_ATOMIC);
 563	if (unlikely(!buf)) {
 564		kfree_skb(skb);
 565		return -1;
 566	}
 567
 568	ohdr = (struct ipv6_rpl_sr_hdr *)buf;
 569	ipv6_rpl_srh_decompress(ohdr, hdr, &ipv6_hdr(skb)->daddr, n);
 570	chdr = (struct ipv6_rpl_sr_hdr *)(buf + ((ohdr->hdrlen + 1) << 3));
 571
 572	if (ipv6_addr_is_multicast(&ohdr->rpl_segaddr[i])) {
 573		kfree_skb(skb);
 574		kfree(buf);
 575		return -1;
 576	}
 577
 578	err = ipv6_chk_rpl_srh_loop(net, ohdr->rpl_segaddr, n + 1);
 579	if (err) {
 580		icmpv6_send(skb, ICMPV6_PARAMPROB, 0, 0);
 581		kfree_skb(skb);
 582		kfree(buf);
 583		return -1;
 584	}
 585
 586	swap(ipv6_hdr(skb)->daddr, ohdr->rpl_segaddr[i]);
 587
 588	ipv6_rpl_srh_compress(chdr, ohdr, &ipv6_hdr(skb)->daddr, n);
 589
 590	oldhdr = ipv6_hdr(skb);
 591
 592	skb_pull(skb, ((hdr->hdrlen + 1) << 3));
 593	skb_postpull_rcsum(skb, oldhdr,
 594			   sizeof(struct ipv6hdr) + ((hdr->hdrlen + 1) << 3));
 595	if (unlikely(!hdr->segments_left)) {
 596		if (pskb_expand_head(skb, sizeof(struct ipv6hdr) + ((chdr->hdrlen + 1) << 3), 0,
 597				     GFP_ATOMIC)) {
 598			__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS);
 599			kfree_skb(skb);
 600			kfree(buf);
 601			return -1;
 602		}
 603
 604		oldhdr = ipv6_hdr(skb);
 605	}
 606	skb_push(skb, ((chdr->hdrlen + 1) << 3) + sizeof(struct ipv6hdr));
 607	skb_reset_network_header(skb);
 608	skb_mac_header_rebuild(skb);
 609	skb_set_transport_header(skb, sizeof(struct ipv6hdr));
 610
 611	memmove(ipv6_hdr(skb), oldhdr, sizeof(struct ipv6hdr));
 612	memcpy(skb_transport_header(skb), chdr, (chdr->hdrlen + 1) << 3);
 613
 614	ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 615	skb_postpush_rcsum(skb, ipv6_hdr(skb),
 616			   sizeof(struct ipv6hdr) + ((chdr->hdrlen + 1) << 3));
 617
 618	kfree(buf);
 619
 620	ip6_route_input(skb);
 621
 622	if (skb_dst(skb)->error) {
 623		dst_input(skb);
 624		return -1;
 625	}
 626
 627	if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
 628		if (ipv6_hdr(skb)->hop_limit <= 1) {
 629			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 630			icmpv6_send(skb, ICMPV6_TIME_EXCEED,
 631				    ICMPV6_EXC_HOPLIMIT, 0);
 632			kfree_skb(skb);
 633			return -1;
 634		}
 635		ipv6_hdr(skb)->hop_limit--;
 636
 637		skb_pull(skb, sizeof(struct ipv6hdr));
 638		goto looped_back;
 639	}
 640
 641	dst_input(skb);
 642
 643	return -1;
 644}
 645
 646/********************************
 647  Routing header.
 648 ********************************/
 649
 650/* called with rcu_read_lock() */
 651static int ipv6_rthdr_rcv(struct sk_buff *skb)
 652{
 653	struct inet6_dev *idev = __in6_dev_get(skb->dev);
 654	struct inet6_skb_parm *opt = IP6CB(skb);
 655	struct in6_addr *addr = NULL;
 656	int n, i;
 657	struct ipv6_rt_hdr *hdr;
 658	struct rt0_hdr *rthdr;
 659	struct net *net = dev_net(skb->dev);
 660	int accept_source_route;
 661
 662	accept_source_route = READ_ONCE(net->ipv6.devconf_all->accept_source_route);
 663
 664	if (idev)
 665		accept_source_route = min(accept_source_route,
 666					  READ_ONCE(idev->cnf.accept_source_route));
 667
 668	if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
 669	    !pskb_may_pull(skb, (skb_transport_offset(skb) +
 670				 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 671		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 672		kfree_skb(skb);
 673		return -1;
 674	}
 675
 676	hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
 677
 678	if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
 679	    skb->pkt_type != PACKET_HOST) {
 680		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
 681		kfree_skb(skb);
 682		return -1;
 683	}
 684
 685	switch (hdr->type) {
 686	case IPV6_SRCRT_TYPE_4:
 687		/* segment routing */
 688		return ipv6_srh_rcv(skb);
 689	case IPV6_SRCRT_TYPE_3:
 690		/* rpl segment routing */
 691		return ipv6_rpl_srh_rcv(skb);
 692	default:
 693		break;
 694	}
 695
 696looped_back:
 697	if (hdr->segments_left == 0) {
 698		switch (hdr->type) {
 699#if IS_ENABLED(CONFIG_IPV6_MIP6)
 700		case IPV6_SRCRT_TYPE_2:
 701			/* Silently discard type 2 header unless it was
 702			 * processed by own
 703			 */
 704			if (!addr) {
 705				__IP6_INC_STATS(net, idev,
 706						IPSTATS_MIB_INADDRERRORS);
 707				kfree_skb(skb);
 708				return -1;
 709			}
 710			break;
 711#endif
 712		default:
 713			break;
 714		}
 715
 716		opt->lastopt = opt->srcrt = skb_network_header_len(skb);
 717		skb->transport_header += (hdr->hdrlen + 1) << 3;
 718		opt->dst0 = opt->dst1;
 719		opt->dst1 = 0;
 720		opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
 721		return 1;
 722	}
 723
 724	switch (hdr->type) {
 725#if IS_ENABLED(CONFIG_IPV6_MIP6)
 726	case IPV6_SRCRT_TYPE_2:
 727		if (accept_source_route < 0)
 728			goto unknown_rh;
 729		/* Silently discard invalid RTH type 2 */
 730		if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
 731			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 732			kfree_skb(skb);
 733			return -1;
 734		}
 735		break;
 736#endif
 737	default:
 738		goto unknown_rh;
 739	}
 740
 741	/*
 742	 *	This is the routing header forwarding algorithm from
 743	 *	RFC 2460, page 16.
 744	 */
 745
 746	n = hdr->hdrlen >> 1;
 747
 748	if (hdr->segments_left > n) {
 749		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 750		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 751				  ((&hdr->segments_left) -
 752				   skb_network_header(skb)));
 753		return -1;
 754	}
 755
 756	/* We are about to mangle packet header. Be careful!
 757	   Do not damage packets queued somewhere.
 758	 */
 759	if (skb_cloned(skb)) {
 760		/* the copy is a forwarded packet */
 761		if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 762			__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 763					IPSTATS_MIB_OUTDISCARDS);
 764			kfree_skb(skb);
 765			return -1;
 766		}
 767		hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
 768	}
 769
 770	if (skb->ip_summed == CHECKSUM_COMPLETE)
 771		skb->ip_summed = CHECKSUM_NONE;
 772
 773	i = n - --hdr->segments_left;
 774
 775	rthdr = (struct rt0_hdr *) hdr;
 776	addr = rthdr->addr;
 777	addr += i - 1;
 778
 779	switch (hdr->type) {
 780#if IS_ENABLED(CONFIG_IPV6_MIP6)
 781	case IPV6_SRCRT_TYPE_2:
 782		if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
 783				     (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
 784				     IPPROTO_ROUTING) < 0) {
 785			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
 786			kfree_skb(skb);
 787			return -1;
 788		}
 789		if (!ipv6_chk_home_addr(skb_dst_dev_net(skb), addr)) {
 790			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
 791			kfree_skb(skb);
 792			return -1;
 793		}
 794		break;
 795#endif
 796	default:
 797		break;
 798	}
 799
 800	if (ipv6_addr_is_multicast(addr)) {
 801		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
 802		kfree_skb(skb);
 803		return -1;
 804	}
 805
 806	swap(*addr, ipv6_hdr(skb)->daddr);
 807
 808	ip6_route_input(skb);
 809	if (skb_dst(skb)->error) {
 810		skb_push(skb, -skb_network_offset(skb));
 811		dst_input(skb);
 812		return -1;
 813	}
 814
 815	if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
 816		if (ipv6_hdr(skb)->hop_limit <= 1) {
 817			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 818			icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
 819				    0);
 820			kfree_skb(skb);
 821			return -1;
 822		}
 823		ipv6_hdr(skb)->hop_limit--;
 824		goto looped_back;
 825	}
 826
 827	skb_push(skb, -skb_network_offset(skb));
 828	dst_input(skb);
 829	return -1;
 830
 831unknown_rh:
 832	__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
 833	icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 834			  (&hdr->type) - skb_network_header(skb));
 835	return -1;
 836}
 837
 838static const struct inet6_protocol rthdr_protocol = {
 839	.handler	=	ipv6_rthdr_rcv,
 840	.flags		=	INET6_PROTO_NOPOLICY,
 841};
 842
 843static const struct inet6_protocol destopt_protocol = {
 844	.handler	=	ipv6_destopt_rcv,
 845	.flags		=	INET6_PROTO_NOPOLICY,
 846};
 847
 848static const struct inet6_protocol nodata_protocol = {
 849	.handler	=	dst_discard,
 850	.flags		=	INET6_PROTO_NOPOLICY,
 851};
 852
 853int __init ipv6_exthdrs_init(void)
 854{
 855	int ret;
 856
 857	ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 858	if (ret)
 859		goto out;
 860
 861	ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
 862	if (ret)
 863		goto out_rthdr;
 864
 865	ret = inet6_add_protocol(&nodata_protocol, IPPROTO_NONE);
 866	if (ret)
 867		goto out_destopt;
 868
 869out:
 870	return ret;
 871out_destopt:
 872	inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
 873out_rthdr:
 874	inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 875	goto out;
 876};
 877
 878void ipv6_exthdrs_exit(void)
 879{
 880	inet6_del_protocol(&nodata_protocol, IPPROTO_NONE);
 881	inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
 882	inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 883}
 884
 885/**********************************
 886  Hop-by-hop options.
 887 **********************************/
 888
 889/* Router Alert as of RFC 2711 */
 890
 891static bool ipv6_hop_ra(struct sk_buff *skb, int optoff)
 892{
 893	const unsigned char *nh = skb_network_header(skb);
 894
 895	if (nh[optoff + 1] == 2) {
 896		IP6CB(skb)->flags |= IP6SKB_ROUTERALERT;
 897		memcpy(&IP6CB(skb)->ra, nh + optoff + 2, sizeof(IP6CB(skb)->ra));
 898		return true;
 899	}
 900	net_dbg_ratelimited("ipv6_hop_ra: wrong RA length %d\n",
 901			    nh[optoff + 1]);
 902	kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
 903	return false;
 904}
 905
 906/* IOAM */
 907
 908static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff)
 909{
 910	struct ioam6_trace_hdr *trace;
 911	struct ioam6_namespace *ns;
 912	struct ioam6_hdr *hdr;
 913
 914	/* Bad alignment (must be 4n-aligned) */
 915	if (optoff & 3)
 916		goto drop;
 917
 918	/* Ignore if IOAM is not enabled on ingress */
 919	if (!READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_enabled))
 920		goto ignore;
 921
 922	/* Truncated Option header */
 923	hdr = (struct ioam6_hdr *)(skb_network_header(skb) + optoff);
 924	if (hdr->opt_len < 2)
 925		goto drop;
 926
 927	switch (hdr->type) {
 928	case IOAM6_TYPE_PREALLOC:
 929		/* Truncated Pre-allocated Trace header */
 930		if (hdr->opt_len < 2 + sizeof(*trace))
 931			goto drop;
 932
 933		/* Malformed Pre-allocated Trace header */
 934		trace = (struct ioam6_trace_hdr *)((u8 *)hdr + sizeof(*hdr));
 935		if (hdr->opt_len < 2 + sizeof(*trace) + trace->remlen * 4)
 936			goto drop;
 937
 938		/* Inconsistent Pre-allocated Trace header */
 939		if (trace->nodelen !=
 940		    ioam6_trace_compute_nodelen(be32_to_cpu(trace->type_be32)))
 941			goto drop;
 942
 943		/* Ignore if the IOAM namespace is unknown */
 944		ns = ioam6_namespace(dev_net(skb->dev), trace->namespace_id);
 945		if (!ns)
 946			goto ignore;
 947
 948		if (!skb_valid_dst(skb))
 949			ip6_route_input(skb);
 950
 951		/* About to mangle packet header */
 952		if (skb_ensure_writable(skb, optoff + 2 + hdr->opt_len))
 953			goto drop;
 954
 955		/* Trace pointer may have changed */
 956		trace = (struct ioam6_trace_hdr *)(skb_network_header(skb)
 957						   + optoff + sizeof(*hdr));
 958
 959		ioam6_fill_trace_data(skb, ns, trace, true);
 960
 961		ioam6_event(IOAM6_EVENT_TRACE, dev_net(skb->dev),
 962			    GFP_ATOMIC, (void *)trace, hdr->opt_len - 2);
 963		break;
 964	default:
 965		break;
 966	}
 967
 968ignore:
 969	return true;
 970
 971drop:
 972	kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
 973	return false;
 974}
 975
 976/* Jumbo payload */
 977
 978static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
 979{
 980	const unsigned char *nh = skb_network_header(skb);
 981	SKB_DR(reason);
 982	u32 pkt_len;
 983
 984	if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
 985		net_dbg_ratelimited("ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
 986				    nh[optoff+1]);
 987		SKB_DR_SET(reason, IP_INHDR);
 988		goto drop;
 989	}
 990
 991	pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
 992	if (pkt_len <= IPV6_MAXPLEN) {
 993		icmpv6_param_prob_reason(skb, ICMPV6_HDR_FIELD, optoff + 2,
 994					 SKB_DROP_REASON_IP_INHDR);
 995		return false;
 996	}
 997	if (ipv6_hdr(skb)->payload_len) {
 998		icmpv6_param_prob_reason(skb, ICMPV6_HDR_FIELD, optoff,
 999					 SKB_DROP_REASON_IP_INHDR);
1000		return false;
1001	}
1002
1003	if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
1004		SKB_DR_SET(reason, PKT_TOO_SMALL);
1005		goto drop;
1006	}
1007
1008	if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
1009		goto drop;
1010
1011	IP6CB(skb)->flags |= IP6SKB_JUMBOGRAM;
1012	return true;
1013
1014drop:
1015	kfree_skb_reason(skb, reason);
1016	return false;
1017}
1018
1019/* CALIPSO RFC 5570 */
1020
1021static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
1022{
1023	const unsigned char *nh = skb_network_header(skb);
1024
1025	if (nh[optoff + 1] < 8)
1026		goto drop;
1027
1028	if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
1029		goto drop;
1030
1031	if (!calipso_validate(skb, nh + optoff))
1032		goto drop;
1033
1034	return true;
1035
1036drop:
1037	kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
1038	return false;
1039}
1040
1041int ipv6_parse_hopopts(struct sk_buff *skb)
1042{
1043	struct inet6_skb_parm *opt = IP6CB(skb);
1044	struct net *net = dev_net(skb->dev);
1045	int extlen;
1046
1047	/*
1048	 * skb_network_header(skb) is equal to skb->data, and
1049	 * skb_network_header_len(skb) is always equal to
1050	 * sizeof(struct ipv6hdr) by definition of
1051	 * hop-by-hop options.
1052	 */
1053	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
1054	    !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
1055				 ((skb_transport_header(skb)[1] + 1) << 3)))) {
1056fail_and_free:
1057		kfree_skb(skb);
1058		return -1;
1059	}
1060
1061	extlen = (skb_transport_header(skb)[1] + 1) << 3;
1062	if (extlen > READ_ONCE(net->ipv6.sysctl.max_hbh_opts_len))
1063		goto fail_and_free;
1064
1065	opt->flags |= IP6SKB_HOPBYHOP;
1066	if (ip6_parse_tlv(true, skb,
1067			  READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt))) {
1068		skb->transport_header += extlen;
1069		opt = IP6CB(skb);
1070		opt->nhoff = sizeof(struct ipv6hdr);
1071		return 1;
1072	}
1073	return -1;
1074}
1075
1076/*
1077 *	Creating outbound headers.
1078 *
1079 *	"build" functions work when skb is filled from head to tail (datagram)
1080 *	"push"	functions work when headers are added from tail to head (tcp)
1081 *
1082 *	In both cases we assume, that caller reserved enough room
1083 *	for headers.
1084 */
1085
1086static void ipv6_push_rthdr0(struct sk_buff *skb, u8 *proto,
1087			     struct ipv6_rt_hdr *opt,
1088			     struct in6_addr **addr_p, struct in6_addr *saddr)
1089{
1090	struct rt0_hdr *phdr, *ihdr;
1091	int hops;
1092
1093	ihdr = (struct rt0_hdr *) opt;
1094
1095	phdr = skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
1096	memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
1097
1098	hops = ihdr->rt_hdr.hdrlen >> 1;
1099
1100	if (hops > 1)
1101		memcpy(phdr->addr, ihdr->addr + 1,
1102		       (hops - 1) * sizeof(struct in6_addr));
1103
1104	phdr->addr[hops - 1] = **addr_p;
1105	*addr_p = ihdr->addr;
1106
1107	phdr->rt_hdr.nexthdr = *proto;
1108	*proto = NEXTHDR_ROUTING;
1109}
1110
1111static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
1112			     struct ipv6_rt_hdr *opt,
1113			     struct in6_addr **addr_p, struct in6_addr *saddr)
1114{
1115	struct ipv6_sr_hdr *sr_phdr, *sr_ihdr;
1116	int plen, hops;
1117
1118	sr_ihdr = (struct ipv6_sr_hdr *)opt;
1119	plen = (sr_ihdr->hdrlen + 1) << 3;
1120
1121	sr_phdr = skb_push(skb, plen);
1122	memcpy(sr_phdr, sr_ihdr, sizeof(struct ipv6_sr_hdr));
1123
1124	hops = sr_ihdr->first_segment + 1;
1125	memcpy(sr_phdr->segments + 1, sr_ihdr->segments + 1,
1126	       (hops - 1) * sizeof(struct in6_addr));
1127
1128	sr_phdr->segments[0] = **addr_p;
1129	*addr_p = &sr_ihdr->segments[sr_ihdr->segments_left];
1130
1131	if (sr_ihdr->hdrlen > hops * 2) {
1132		int tlvs_offset, tlvs_length;
1133
1134		tlvs_offset = (1 + hops * 2) << 3;
1135		tlvs_length = (sr_ihdr->hdrlen - hops * 2) << 3;
1136		memcpy((char *)sr_phdr + tlvs_offset,
1137		       (char *)sr_ihdr + tlvs_offset, tlvs_length);
1138	}
1139
1140#ifdef CONFIG_IPV6_SEG6_HMAC
1141	if (sr_has_hmac(sr_phdr)) {
1142		struct net *net = NULL;
1143
1144		if (skb->dev)
1145			net = dev_net(skb->dev);
1146		else if (skb->sk)
1147			net = sock_net(skb->sk);
1148
1149		WARN_ON(!net);
1150
1151		if (net)
1152			seg6_push_hmac(net, saddr, sr_phdr);
1153	}
1154#endif
1155
1156	sr_phdr->nexthdr = *proto;
1157	*proto = NEXTHDR_ROUTING;
1158}
1159
1160static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
1161			    struct ipv6_rt_hdr *opt,
1162			    struct in6_addr **addr_p, struct in6_addr *saddr)
1163{
1164	switch (opt->type) {
1165	case IPV6_SRCRT_TYPE_0:
1166	case IPV6_SRCRT_STRICT:
1167	case IPV6_SRCRT_TYPE_2:
1168		ipv6_push_rthdr0(skb, proto, opt, addr_p, saddr);
1169		break;
1170	case IPV6_SRCRT_TYPE_4:
1171		ipv6_push_rthdr4(skb, proto, opt, addr_p, saddr);
1172		break;
1173	default:
1174		break;
1175	}
1176}
1177
1178static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
1179{
1180	struct ipv6_opt_hdr *h = skb_push(skb, ipv6_optlen(opt));
1181
1182	memcpy(h, opt, ipv6_optlen(opt));
1183	h->nexthdr = *proto;
1184	*proto = type;
1185}
1186
1187void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
1188			  u8 *proto,
1189			  struct in6_addr **daddr, struct in6_addr *saddr)
1190{
1191	if (opt->srcrt) {
1192		ipv6_push_rthdr(skb, proto, opt->srcrt, daddr, saddr);
1193		/*
1194		 * IPV6_RTHDRDSTOPTS is ignored
1195		 * unless IPV6_RTHDR is set (RFC3542).
1196		 */
1197		if (opt->dst0opt)
1198			ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
1199	}
1200	if (opt->hopopt)
1201		ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
1202}
1203
1204void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
1205{
1206	if (opt->dst1opt)
1207		ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
1208}
1209EXPORT_SYMBOL(ipv6_push_frag_opts);
1210
1211struct ipv6_txoptions *
1212ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
1213{
1214	struct ipv6_txoptions *opt2;
1215
1216	opt2 = sock_kmemdup(sk, opt, opt->tot_len, GFP_ATOMIC);
1217	if (opt2) {
1218		long dif = (char *)opt2 - (char *)opt;
1219		if (opt2->hopopt)
1220			*((char **)&opt2->hopopt) += dif;
1221		if (opt2->dst0opt)
1222			*((char **)&opt2->dst0opt) += dif;
1223		if (opt2->dst1opt)
1224			*((char **)&opt2->dst1opt) += dif;
1225		if (opt2->srcrt)
1226			*((char **)&opt2->srcrt) += dif;
1227		refcount_set(&opt2->refcnt, 1);
1228	}
1229	return opt2;
1230}
1231EXPORT_SYMBOL_GPL(ipv6_dup_options);
1232
1233static void ipv6_renew_option(int renewtype,
1234			      struct ipv6_opt_hdr **dest,
1235			      struct ipv6_opt_hdr *old,
1236			      struct ipv6_opt_hdr *new,
1237			      int newtype, char **p)
1238{
1239	struct ipv6_opt_hdr *src;
1240
1241	src = (renewtype == newtype ? new : old);
1242	if (!src)
1243		return;
1244
1245	memcpy(*p, src, ipv6_optlen(src));
1246	*dest = (struct ipv6_opt_hdr *)*p;
1247	*p += CMSG_ALIGN(ipv6_optlen(*dest));
1248}
1249
1250/**
1251 * ipv6_renew_options - replace a specific ext hdr with a new one.
1252 *
1253 * @sk: sock from which to allocate memory
1254 * @opt: original options
1255 * @newtype: option type to replace in @opt
1256 * @newopt: new option of type @newtype to replace (user-mem)
1257 *
1258 * Returns a new set of options which is a copy of @opt with the
1259 * option type @newtype replaced with @newopt.
1260 *
1261 * @opt may be NULL, in which case a new set of options is returned
1262 * containing just @newopt.
1263 *
1264 * @newopt may be NULL, in which case the specified option type is
1265 * not copied into the new set of options.
1266 *
1267 * The new set of options is allocated from the socket option memory
1268 * buffer of @sk.
1269 */
1270struct ipv6_txoptions *
1271ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
1272		   int newtype, struct ipv6_opt_hdr *newopt)
1273{
1274	int tot_len = 0;
1275	char *p;
1276	struct ipv6_txoptions *opt2;
1277
1278	if (opt) {
1279		if (newtype != IPV6_HOPOPTS && opt->hopopt)
1280			tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
1281		if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
1282			tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
1283		if (newtype != IPV6_RTHDR && opt->srcrt)
1284			tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
1285		if (newtype != IPV6_DSTOPTS && opt->dst1opt)
1286			tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
1287	}
1288
1289	if (newopt)
1290		tot_len += CMSG_ALIGN(ipv6_optlen(newopt));
1291
1292	if (!tot_len)
1293		return NULL;
1294
1295	tot_len += sizeof(*opt2);
1296	opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
1297	if (!opt2)
1298		return ERR_PTR(-ENOBUFS);
1299
1300	memset(opt2, 0, tot_len);
1301	refcount_set(&opt2->refcnt, 1);
1302	opt2->tot_len = tot_len;
1303	p = (char *)(opt2 + 1);
1304
1305	ipv6_renew_option(IPV6_HOPOPTS, &opt2->hopopt,
1306			  (opt ? opt->hopopt : NULL),
1307			  newopt, newtype, &p);
1308	ipv6_renew_option(IPV6_RTHDRDSTOPTS, &opt2->dst0opt,
1309			  (opt ? opt->dst0opt : NULL),
1310			  newopt, newtype, &p);
1311	ipv6_renew_option(IPV6_RTHDR,
1312			  (struct ipv6_opt_hdr **)&opt2->srcrt,
1313			  (opt ? (struct ipv6_opt_hdr *)opt->srcrt : NULL),
1314			  newopt, newtype, &p);
1315	ipv6_renew_option(IPV6_DSTOPTS, &opt2->dst1opt,
1316			  (opt ? opt->dst1opt : NULL),
1317			  newopt, newtype, &p);
1318
1319	opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
1320			  (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
1321			  (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
1322	opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
1323
1324	return opt2;
1325}
1326
1327struct ipv6_txoptions *__ipv6_fixup_options(struct ipv6_txoptions *opt_space,
1328					    struct ipv6_txoptions *opt)
1329{
1330	/*
1331	 * ignore the dest before srcrt unless srcrt is being included.
1332	 * --yoshfuji
1333	 */
1334	if (opt->dst0opt && !opt->srcrt) {
1335		if (opt_space != opt) {
1336			memcpy(opt_space, opt, sizeof(*opt_space));
1337			opt = opt_space;
1338		}
1339		opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
1340		opt->dst0opt = NULL;
1341	}
1342
1343	return opt;
1344}
1345EXPORT_SYMBOL_GPL(__ipv6_fixup_options);
1346
1347/**
1348 * fl6_update_dst - update flowi destination address with info given
1349 *                  by srcrt option, if any.
1350 *
1351 * @fl6: flowi6 for which daddr is to be updated
1352 * @opt: struct ipv6_txoptions in which to look for srcrt opt
1353 * @orig: copy of original daddr address if modified
1354 *
1355 * Returns NULL if no txoptions or no srcrt, otherwise returns orig
1356 * and initial value of fl6->daddr set in orig
1357 */
1358struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
1359				const struct ipv6_txoptions *opt,
1360				struct in6_addr *orig)
1361{
1362	if (!opt || !opt->srcrt)
1363		return NULL;
1364
1365	*orig = fl6->daddr;
1366
1367	switch (opt->srcrt->type) {
1368	case IPV6_SRCRT_TYPE_0:
1369	case IPV6_SRCRT_STRICT:
1370	case IPV6_SRCRT_TYPE_2:
1371		fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr;
1372		break;
1373	case IPV6_SRCRT_TYPE_4:
1374	{
1375		struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)opt->srcrt;
1376
1377		fl6->daddr = srh->segments[srh->segments_left];
1378		break;
1379	}
1380	default:
1381		return NULL;
1382	}
1383
1384	return orig;
1385}
1386EXPORT_SYMBOL_GPL(fl6_update_dst);
~/ Read-only file preview.