net/ipv6/ip6_output.c
changeset 2 d1f6d8b6f81c
parent 0 aa628870c1d3
equal deleted inserted replaced
1:0056487c491e 2:d1f6d8b6f81c
   135 	if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
   135 	if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
   136 		struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL;
   136 		struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL;
   137 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
   137 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
   138 
   138 
   139 		if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
   139 		if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
   140 		    ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
   140 		    ((mroute6_socket(dev_net(dev)) &&
       
   141 		     !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
   141 		     ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
   142 		     ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
   142 					 &ipv6_hdr(skb)->saddr))) {
   143 					 &ipv6_hdr(skb)->saddr))) {
   143 			struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
   144 			struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
   144 
   145 
   145 			/* Do not check for IFF_ALLMULTI; multicast routing
   146 			/* Do not check for IFF_ALLMULTI; multicast routing
   488 	/* IPv6 specs say nothing about it, but it is clear that we cannot
   489 	/* IPv6 specs say nothing about it, but it is clear that we cannot
   489 	   send redirects to source routed frames.
   490 	   send redirects to source routed frames.
   490 	   We don't send redirects to frames decapsulated from IPsec.
   491 	   We don't send redirects to frames decapsulated from IPsec.
   491 	 */
   492 	 */
   492 	if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
   493 	if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
   493 	    !skb->sp) {
   494 	    !skb_sec_path(skb)) {
   494 		struct in6_addr *target = NULL;
   495 		struct in6_addr *target = NULL;
   495 		struct rt6_info *rt;
   496 		struct rt6_info *rt;
   496 		struct neighbour *n = dst->neighbour;
   497 		struct neighbour *n = dst->neighbour;
   497 
   498 
   498 		/*
   499 		/*
  1102 	kfree_skb(skb);
  1103 	kfree_skb(skb);
  1103 
  1104 
  1104 	return err;
  1105 	return err;
  1105 }
  1106 }
  1106 
  1107 
       
  1108 static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
       
  1109 					       gfp_t gfp)
       
  1110 {
       
  1111 	return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
       
  1112 }
       
  1113 
       
  1114 static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
       
  1115 						gfp_t gfp)
       
  1116 {
       
  1117 	return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
       
  1118 }
       
  1119 
  1107 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
  1120 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
  1108 	int offset, int len, int odd, struct sk_buff *skb),
  1121 	int offset, int len, int odd, struct sk_buff *skb),
  1109 	void *from, int length, int transhdrlen,
  1122 	void *from, int length, int transhdrlen,
  1110 	int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
  1123 	int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
  1111 	struct rt6_info *rt, unsigned int flags)
  1124 	struct rt6_info *rt, unsigned int flags)
  1127 	if (skb_queue_empty(&sk->sk_write_queue)) {
  1140 	if (skb_queue_empty(&sk->sk_write_queue)) {
  1128 		/*
  1141 		/*
  1129 		 * setup for corking
  1142 		 * setup for corking
  1130 		 */
  1143 		 */
  1131 		if (opt) {
  1144 		if (opt) {
  1132 			if (np->cork.opt == NULL) {
  1145 			if (WARN_ON(np->cork.opt))
  1133 				np->cork.opt = kmalloc(opt->tot_len,
       
  1134 						       sk->sk_allocation);
       
  1135 				if (unlikely(np->cork.opt == NULL))
       
  1136 					return -ENOBUFS;
       
  1137 			} else if (np->cork.opt->tot_len < opt->tot_len) {
       
  1138 				printk(KERN_DEBUG "ip6_append_data: invalid option length\n");
       
  1139 				return -EINVAL;
  1146 				return -EINVAL;
  1140 			}
  1147 
  1141 			memcpy(np->cork.opt, opt, opt->tot_len);
  1148 			np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
  1142 			inet->cork.flags |= IPCORK_OPT;
  1149 			if (unlikely(np->cork.opt == NULL))
       
  1150 				return -ENOBUFS;
       
  1151 
       
  1152 			np->cork.opt->tot_len = opt->tot_len;
       
  1153 			np->cork.opt->opt_flen = opt->opt_flen;
       
  1154 			np->cork.opt->opt_nflen = opt->opt_nflen;
       
  1155 
       
  1156 			np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt,
       
  1157 							    sk->sk_allocation);
       
  1158 			if (opt->dst0opt && !np->cork.opt->dst0opt)
       
  1159 				return -ENOBUFS;
       
  1160 
       
  1161 			np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt,
       
  1162 							    sk->sk_allocation);
       
  1163 			if (opt->dst1opt && !np->cork.opt->dst1opt)
       
  1164 				return -ENOBUFS;
       
  1165 
       
  1166 			np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt,
       
  1167 							   sk->sk_allocation);
       
  1168 			if (opt->hopopt && !np->cork.opt->hopopt)
       
  1169 				return -ENOBUFS;
       
  1170 
       
  1171 			np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt,
       
  1172 							    sk->sk_allocation);
       
  1173 			if (opt->srcrt && !np->cork.opt->srcrt)
       
  1174 				return -ENOBUFS;
       
  1175 
  1143 			/* need source address above miyazawa*/
  1176 			/* need source address above miyazawa*/
  1144 		}
  1177 		}
  1145 		dst_hold(&rt->u.dst);
  1178 		dst_hold(&rt->u.dst);
  1146 		inet->cork.dst = &rt->u.dst;
  1179 		inet->cork.dst = &rt->u.dst;
  1147 		inet->cork.fl = *fl;
  1180 		inet->cork.fl = *fl;
  1164 		length += exthdrlen;
  1197 		length += exthdrlen;
  1165 		transhdrlen += exthdrlen;
  1198 		transhdrlen += exthdrlen;
  1166 	} else {
  1199 	} else {
  1167 		rt = (struct rt6_info *)inet->cork.dst;
  1200 		rt = (struct rt6_info *)inet->cork.dst;
  1168 		fl = &inet->cork.fl;
  1201 		fl = &inet->cork.fl;
  1169 		if (inet->cork.flags & IPCORK_OPT)
  1202 		opt = np->cork.opt;
  1170 			opt = np->cork.opt;
       
  1171 		transhdrlen = 0;
  1203 		transhdrlen = 0;
  1172 		exthdrlen = 0;
  1204 		exthdrlen = 0;
  1173 		mtu = inet->cork.fragsize;
  1205 		mtu = inet->cork.fragsize;
  1174 	}
  1206 	}
  1175 
  1207 
  1404 	return err;
  1436 	return err;
  1405 }
  1437 }
  1406 
  1438 
  1407 static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
  1439 static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
  1408 {
  1440 {
  1409 	inet->cork.flags &= ~IPCORK_OPT;
  1441 	if (np->cork.opt) {
  1410 	kfree(np->cork.opt);
  1442 		kfree(np->cork.opt->dst0opt);
  1411 	np->cork.opt = NULL;
  1443 		kfree(np->cork.opt->dst1opt);
       
  1444 		kfree(np->cork.opt->hopopt);
       
  1445 		kfree(np->cork.opt->srcrt);
       
  1446 		kfree(np->cork.opt);
       
  1447 		np->cork.opt = NULL;
       
  1448 	}
       
  1449 
  1412 	if (inet->cork.dst) {
  1450 	if (inet->cork.dst) {
  1413 		dst_release(inet->cork.dst);
  1451 		dst_release(inet->cork.dst);
  1414 		inet->cork.dst = NULL;
  1452 		inet->cork.dst = NULL;
  1415 		inet->cork.flags &= ~IPCORK_ALLFRAG;
  1453 		inet->cork.flags &= ~IPCORK_ALLFRAG;
  1416 	}
  1454 	}