aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-05-08 20:12:19 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-09 00:24:06 -0400
commit77968b78242ee25e2a4d759f0fca8dd52df6d479 (patch)
tree6de21f3a2efe49cb30ea8109fdfc79d30d6b27a3
parente474995f290ff7bc236b549aa9a89ae445ee5b1b (diff)
ipv4: Pass flow keys down into datagram packet building engine.
This way ip_output.c no longer needs rt->rt_{src,dst}. We already have these keys sitting, ready and waiting, on the stack or in a socket structure. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ip.h8
-rw-r--r--net/ipv4/icmp.c74
-rw-r--r--net/ipv4/ip_output.c39
-rw-r--r--net/ipv4/raw.c59
-rw-r--r--net/ipv4/udp.c4
5 files changed, 91 insertions, 93 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index acf8b7814c4e..a4253795c5c5 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -117,12 +117,14 @@ extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int od
117extern ssize_t ip_append_page(struct sock *sk, struct page *page, 117extern ssize_t ip_append_page(struct sock *sk, struct page *page,
118 int offset, size_t size, int flags); 118 int offset, size_t size, int flags);
119extern struct sk_buff *__ip_make_skb(struct sock *sk, 119extern struct sk_buff *__ip_make_skb(struct sock *sk,
120 struct flowi4 *fl4,
120 struct sk_buff_head *queue, 121 struct sk_buff_head *queue,
121 struct inet_cork *cork); 122 struct inet_cork *cork);
122extern int ip_send_skb(struct sk_buff *skb); 123extern int ip_send_skb(struct sk_buff *skb);
123extern int ip_push_pending_frames(struct sock *sk); 124extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
124extern void ip_flush_pending_frames(struct sock *sk); 125extern void ip_flush_pending_frames(struct sock *sk);
125extern struct sk_buff *ip_make_skb(struct sock *sk, 126extern struct sk_buff *ip_make_skb(struct sock *sk,
127 struct flowi4 *fl4,
126 int getfrag(void *from, char *to, int offset, int len, 128 int getfrag(void *from, char *to, int offset, int len,
127 int odd, struct sk_buff *skb), 129 int odd, struct sk_buff *skb),
128 void *from, int length, int transhdrlen, 130 void *from, int length, int transhdrlen,
@@ -130,9 +132,9 @@ extern struct sk_buff *ip_make_skb(struct sock *sk,
130 struct rtable **rtp, 132 struct rtable **rtp,
131 unsigned int flags); 133 unsigned int flags);
132 134
133static inline struct sk_buff *ip_finish_skb(struct sock *sk) 135static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
134{ 136{
135 return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); 137 return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
136} 138}
137 139
138/* datagram.c */ 140/* datagram.c */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index cfeca3c2152d..be5cc8d04c00 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -290,6 +290,7 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
290} 290}
291 291
292static void icmp_push_reply(struct icmp_bxm *icmp_param, 292static void icmp_push_reply(struct icmp_bxm *icmp_param,
293 struct flowi4 *fl4,
293 struct ipcm_cookie *ipc, struct rtable **rt) 294 struct ipcm_cookie *ipc, struct rtable **rt)
294{ 295{
295 struct sock *sk; 296 struct sock *sk;
@@ -315,7 +316,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
315 icmp_param->head_len, csum); 316 icmp_param->head_len, csum);
316 icmph->checksum = csum_fold(csum); 317 icmph->checksum = csum_fold(csum);
317 skb->ip_summed = CHECKSUM_NONE; 318 skb->ip_summed = CHECKSUM_NONE;
318 ip_push_pending_frames(sk); 319 ip_push_pending_frames(sk, fl4);
319 } 320 }
320} 321}
321 322
@@ -328,6 +329,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
328 struct ipcm_cookie ipc; 329 struct ipcm_cookie ipc;
329 struct rtable *rt = skb_rtable(skb); 330 struct rtable *rt = skb_rtable(skb);
330 struct net *net = dev_net(rt->dst.dev); 331 struct net *net = dev_net(rt->dst.dev);
332 struct flowi4 fl4;
331 struct sock *sk; 333 struct sock *sk;
332 struct inet_sock *inet; 334 struct inet_sock *inet;
333 __be32 daddr; 335 __be32 daddr;
@@ -351,57 +353,52 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
351 if (ipc.opt->opt.srr) 353 if (ipc.opt->opt.srr)
352 daddr = icmp_param->replyopts.opt.opt.faddr; 354 daddr = icmp_param->replyopts.opt.opt.faddr;
353 } 355 }
354 { 356 memset(&fl4, 0, sizeof(fl4));
355 struct flowi4 fl4 = { 357 fl4.daddr = daddr;
356 .daddr = daddr, 358 fl4.saddr = rt->rt_spec_dst;
357 .saddr = rt->rt_spec_dst, 359 fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
358 .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), 360 fl4.flowi4_proto = IPPROTO_ICMP;
359 .flowi4_proto = IPPROTO_ICMP, 361 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
360 }; 362 rt = ip_route_output_key(net, &fl4);
361 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); 363 if (IS_ERR(rt))
362 rt = ip_route_output_key(net, &fl4); 364 goto out_unlock;
363 if (IS_ERR(rt))
364 goto out_unlock;
365 }
366 if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, 365 if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
367 icmp_param->data.icmph.code)) 366 icmp_param->data.icmph.code))
368 icmp_push_reply(icmp_param, &ipc, &rt); 367 icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
369 ip_rt_put(rt); 368 ip_rt_put(rt);
370out_unlock: 369out_unlock:
371 icmp_xmit_unlock(sk); 370 icmp_xmit_unlock(sk);
372} 371}
373 372
374static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, 373static struct rtable *icmp_route_lookup(struct net *net,
374 struct flowi4 *fl4,
375 struct sk_buff *skb_in,
375 const struct iphdr *iph, 376 const struct iphdr *iph,
376 __be32 saddr, u8 tos, 377 __be32 saddr, u8 tos,
377 int type, int code, 378 int type, int code,
378 struct icmp_bxm *param) 379 struct icmp_bxm *param)
379{ 380{
380 struct flowi4 fl4 = {
381 .daddr = (param->replyopts.opt.opt.srr ?
382 param->replyopts.opt.opt.faddr : iph->saddr),
383 .saddr = saddr,
384 .flowi4_tos = RT_TOS(tos),
385 .flowi4_proto = IPPROTO_ICMP,
386 .fl4_icmp_type = type,
387 .fl4_icmp_code = code,
388 };
389 struct rtable *rt, *rt2; 381 struct rtable *rt, *rt2;
390 int err; 382 int err;
391 383
392 security_skb_classify_flow(skb_in, flowi4_to_flowi(&fl4)); 384 memset(fl4, 0, sizeof(*fl4));
393 rt = __ip_route_output_key(net, &fl4); 385 fl4->daddr = (param->replyopts.opt.opt.srr ?
386 param->replyopts.opt.opt.faddr : iph->saddr);
387 fl4->saddr = saddr;
388 fl4->flowi4_tos = RT_TOS(tos);
389 fl4->flowi4_proto = IPPROTO_ICMP;
390 fl4->fl4_icmp_type = type;
391 fl4->fl4_icmp_code = code;
392 security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
393 rt = __ip_route_output_key(net, fl4);
394 if (IS_ERR(rt)) 394 if (IS_ERR(rt))
395 return rt; 395 return rt;
396 396
397 /* No need to clone since we're just using its address. */ 397 /* No need to clone since we're just using its address. */
398 rt2 = rt; 398 rt2 = rt;
399 399
400 if (!fl4.saddr)
401 fl4.saddr = rt->rt_src;
402
403 rt = (struct rtable *) xfrm_lookup(net, &rt->dst, 400 rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
404 flowi4_to_flowi(&fl4), NULL, 0); 401 flowi4_to_flowi(fl4), NULL, 0);
405 if (!IS_ERR(rt)) { 402 if (!IS_ERR(rt)) {
406 if (rt != rt2) 403 if (rt != rt2)
407 return rt; 404 return rt;
@@ -410,19 +407,19 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
410 } else 407 } else
411 return rt; 408 return rt;
412 409
413 err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4), AF_INET); 410 err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET);
414 if (err) 411 if (err)
415 goto relookup_failed; 412 goto relookup_failed;
416 413
417 if (inet_addr_type(net, fl4.saddr) == RTN_LOCAL) { 414 if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
418 rt2 = __ip_route_output_key(net, &fl4); 415 rt2 = __ip_route_output_key(net, fl4);
419 if (IS_ERR(rt2)) 416 if (IS_ERR(rt2))
420 err = PTR_ERR(rt2); 417 err = PTR_ERR(rt2);
421 } else { 418 } else {
422 struct flowi4 fl4_2 = {}; 419 struct flowi4 fl4_2 = {};
423 unsigned long orefdst; 420 unsigned long orefdst;
424 421
425 fl4_2.daddr = fl4.saddr; 422 fl4_2.daddr = fl4->saddr;
426 rt2 = ip_route_output_key(net, &fl4_2); 423 rt2 = ip_route_output_key(net, &fl4_2);
427 if (IS_ERR(rt2)) { 424 if (IS_ERR(rt2)) {
428 err = PTR_ERR(rt2); 425 err = PTR_ERR(rt2);
@@ -430,7 +427,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
430 } 427 }
431 /* Ugh! */ 428 /* Ugh! */
432 orefdst = skb_in->_skb_refdst; /* save old refdst */ 429 orefdst = skb_in->_skb_refdst; /* save old refdst */
433 err = ip_route_input(skb_in, fl4.daddr, fl4.saddr, 430 err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
434 RT_TOS(tos), rt2->dst.dev); 431 RT_TOS(tos), rt2->dst.dev);
435 432
436 dst_release(&rt2->dst); 433 dst_release(&rt2->dst);
@@ -442,7 +439,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
442 goto relookup_failed; 439 goto relookup_failed;
443 440
444 rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst, 441 rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
445 flowi4_to_flowi(&fl4), NULL, 442 flowi4_to_flowi(fl4), NULL,
446 XFRM_LOOKUP_ICMP); 443 XFRM_LOOKUP_ICMP);
447 if (!IS_ERR(rt2)) { 444 if (!IS_ERR(rt2)) {
448 dst_release(&rt->dst); 445 dst_release(&rt->dst);
@@ -481,6 +478,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
481 struct icmp_bxm icmp_param; 478 struct icmp_bxm icmp_param;
482 struct rtable *rt = skb_rtable(skb_in); 479 struct rtable *rt = skb_rtable(skb_in);
483 struct ipcm_cookie ipc; 480 struct ipcm_cookie ipc;
481 struct flowi4 fl4;
484 __be32 saddr; 482 __be32 saddr;
485 u8 tos; 483 u8 tos;
486 struct net *net; 484 struct net *net;
@@ -599,7 +597,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
599 ipc.opt = &icmp_param.replyopts.opt; 597 ipc.opt = &icmp_param.replyopts.opt;
600 ipc.tx_flags = 0; 598 ipc.tx_flags = 0;
601 599
602 rt = icmp_route_lookup(net, skb_in, iph, saddr, tos, 600 rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos,
603 type, code, &icmp_param); 601 type, code, &icmp_param);
604 if (IS_ERR(rt)) 602 if (IS_ERR(rt))
605 goto out_unlock; 603 goto out_unlock;
@@ -620,7 +618,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
620 icmp_param.data_len = room; 618 icmp_param.data_len = room;
621 icmp_param.head_len = sizeof(struct icmphdr); 619 icmp_param.head_len = sizeof(struct icmphdr);
622 620
623 icmp_push_reply(&icmp_param, &ipc, &rt); 621 icmp_push_reply(&icmp_param, &fl4, &ipc, &rt);
624ende: 622ende:
625 ip_rt_put(rt); 623 ip_rt_put(rt);
626out_unlock: 624out_unlock:
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index b88ee5fdcbca..dca637b9d8ae 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1267,6 +1267,7 @@ static void ip_cork_release(struct inet_cork *cork)
1267 * and push them out. 1267 * and push them out.
1268 */ 1268 */
1269struct sk_buff *__ip_make_skb(struct sock *sk, 1269struct sk_buff *__ip_make_skb(struct sock *sk,
1270 struct flowi4 *fl4,
1270 struct sk_buff_head *queue, 1271 struct sk_buff_head *queue,
1271 struct inet_cork *cork) 1272 struct inet_cork *cork)
1272{ 1273{
@@ -1333,8 +1334,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
1333 ip_select_ident(iph, &rt->dst, sk); 1334 ip_select_ident(iph, &rt->dst, sk);
1334 iph->ttl = ttl; 1335 iph->ttl = ttl;
1335 iph->protocol = sk->sk_protocol; 1336 iph->protocol = sk->sk_protocol;
1336 iph->saddr = rt->rt_src; 1337 iph->saddr = fl4->saddr;
1337 iph->daddr = rt->rt_dst; 1338 iph->daddr = fl4->daddr;
1338 1339
1339 skb->priority = sk->sk_priority; 1340 skb->priority = sk->sk_priority;
1340 skb->mark = sk->sk_mark; 1341 skb->mark = sk->sk_mark;
@@ -1370,11 +1371,11 @@ int ip_send_skb(struct sk_buff *skb)
1370 return err; 1371 return err;
1371} 1372}
1372 1373
1373int ip_push_pending_frames(struct sock *sk) 1374int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4)
1374{ 1375{
1375 struct sk_buff *skb; 1376 struct sk_buff *skb;
1376 1377
1377 skb = ip_finish_skb(sk); 1378 skb = ip_finish_skb(sk, fl4);
1378 if (!skb) 1379 if (!skb)
1379 return 0; 1380 return 0;
1380 1381
@@ -1403,6 +1404,7 @@ void ip_flush_pending_frames(struct sock *sk)
1403} 1404}
1404 1405
1405struct sk_buff *ip_make_skb(struct sock *sk, 1406struct sk_buff *ip_make_skb(struct sock *sk,
1407 struct flowi4 *fl4,
1406 int getfrag(void *from, char *to, int offset, 1408 int getfrag(void *from, char *to, int offset,
1407 int len, int odd, struct sk_buff *skb), 1409 int len, int odd, struct sk_buff *skb),
1408 void *from, int length, int transhdrlen, 1410 void *from, int length, int transhdrlen,
@@ -1432,7 +1434,7 @@ struct sk_buff *ip_make_skb(struct sock *sk,
1432 return ERR_PTR(err); 1434 return ERR_PTR(err);
1433 } 1435 }
1434 1436
1435 return __ip_make_skb(sk, &queue, &cork); 1437 return __ip_make_skb(sk, fl4, &queue, &cork);
1436} 1438}
1437 1439
1438/* 1440/*
@@ -1461,6 +1463,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
1461 struct inet_sock *inet = inet_sk(sk); 1463 struct inet_sock *inet = inet_sk(sk);
1462 struct ip_options_data replyopts; 1464 struct ip_options_data replyopts;
1463 struct ipcm_cookie ipc; 1465 struct ipcm_cookie ipc;
1466 struct flowi4 fl4;
1464 __be32 daddr; 1467 __be32 daddr;
1465 struct rtable *rt = skb_rtable(skb); 1468 struct rtable *rt = skb_rtable(skb);
1466 1469
@@ -1478,20 +1481,16 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
1478 daddr = replyopts.opt.opt.faddr; 1481 daddr = replyopts.opt.opt.faddr;
1479 } 1482 }
1480 1483
1481 { 1484 flowi4_init_output(&fl4, arg->bound_dev_if, 0,
1482 struct flowi4 fl4; 1485 RT_TOS(ip_hdr(skb)->tos),
1483 1486 RT_SCOPE_UNIVERSE, sk->sk_protocol,
1484 flowi4_init_output(&fl4, arg->bound_dev_if, 0, 1487 ip_reply_arg_flowi_flags(arg),
1485 RT_TOS(ip_hdr(skb)->tos), 1488 daddr, rt->rt_spec_dst,
1486 RT_SCOPE_UNIVERSE, sk->sk_protocol, 1489 tcp_hdr(skb)->source, tcp_hdr(skb)->dest);
1487 ip_reply_arg_flowi_flags(arg), 1490 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
1488 daddr, rt->rt_spec_dst, 1491 rt = ip_route_output_key(sock_net(sk), &fl4);
1489 tcp_hdr(skb)->source, tcp_hdr(skb)->dest); 1492 if (IS_ERR(rt))
1490 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); 1493 return;
1491 rt = ip_route_output_key(sock_net(sk), &fl4);
1492 if (IS_ERR(rt))
1493 return;
1494 }
1495 1494
1496 /* And let IP do all the hard work. 1495 /* And let IP do all the hard work.
1497 1496
@@ -1512,7 +1511,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
1512 arg->csumoffset) = csum_fold(csum_add(skb->csum, 1511 arg->csumoffset) = csum_fold(csum_add(skb->csum,
1513 arg->csum)); 1512 arg->csum));
1514 skb->ip_summed = CHECKSUM_NONE; 1513 skb->ip_summed = CHECKSUM_NONE;
1515 ip_push_pending_frames(sk); 1514 ip_push_pending_frames(sk, &fl4);
1516 } 1515 }
1517 1516
1518 bh_unlock_sock(sk); 1517 bh_unlock_sock(sk);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index a8659e0c4a6e..6fee91f656a9 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -314,9 +314,10 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb)
314 return 0; 314 return 0;
315} 315}
316 316
317static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, 317static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
318 struct rtable **rtp, 318 void *from, size_t length,
319 unsigned int flags) 319 struct rtable **rtp,
320 unsigned int flags)
320{ 321{
321 struct inet_sock *inet = inet_sk(sk); 322 struct inet_sock *inet = inet_sk(sk);
322 struct net *net = sock_net(sk); 323 struct net *net = sock_net(sk);
@@ -327,7 +328,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
327 struct rtable *rt = *rtp; 328 struct rtable *rt = *rtp;
328 329
329 if (length > rt->dst.dev->mtu) { 330 if (length > rt->dst.dev->mtu) {
330 ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, 331 ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
331 rt->dst.dev->mtu); 332 rt->dst.dev->mtu);
332 return -EMSGSIZE; 333 return -EMSGSIZE;
333 } 334 }
@@ -372,7 +373,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
372 373
373 if (iphlen >= sizeof(*iph)) { 374 if (iphlen >= sizeof(*iph)) {
374 if (!iph->saddr) 375 if (!iph->saddr)
375 iph->saddr = rt->rt_src; 376 iph->saddr = fl4->saddr;
376 iph->check = 0; 377 iph->check = 0;
377 iph->tot_len = htons(length); 378 iph->tot_len = htons(length);
378 if (!iph->id) 379 if (!iph->id)
@@ -455,6 +456,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
455 struct inet_sock *inet = inet_sk(sk); 456 struct inet_sock *inet = inet_sk(sk);
456 struct ipcm_cookie ipc; 457 struct ipcm_cookie ipc;
457 struct rtable *rt = NULL; 458 struct rtable *rt = NULL;
459 struct flowi4 fl4;
458 int free = 0; 460 int free = 0;
459 __be32 daddr; 461 __be32 daddr;
460 __be32 saddr; 462 __be32 saddr;
@@ -558,27 +560,23 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
558 saddr = inet->mc_addr; 560 saddr = inet->mc_addr;
559 } 561 }
560 562
561 { 563 flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
562 struct flowi4 fl4; 564 RT_SCOPE_UNIVERSE,
565 inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
566 FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0);
563 567
564 flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, 568 if (!inet->hdrincl) {
565 RT_SCOPE_UNIVERSE, 569 err = raw_probe_proto_opt(&fl4, msg);
566 inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, 570 if (err)
567 FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0);
568
569 if (!inet->hdrincl) {
570 err = raw_probe_proto_opt(&fl4, msg);
571 if (err)
572 goto done;
573 }
574
575 security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
576 rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
577 if (IS_ERR(rt)) {
578 err = PTR_ERR(rt);
579 rt = NULL;
580 goto done; 571 goto done;
581 } 572 }
573
574 security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
575 rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
576 if (IS_ERR(rt)) {
577 err = PTR_ERR(rt);
578 rt = NULL;
579 goto done;
582 } 580 }
583 581
584 err = -EACCES; 582 err = -EACCES;
@@ -590,19 +588,20 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
590back_from_confirm: 588back_from_confirm:
591 589
592 if (inet->hdrincl) 590 if (inet->hdrincl)
593 err = raw_send_hdrinc(sk, msg->msg_iov, len, 591 err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len,
594 &rt, msg->msg_flags); 592 &rt, msg->msg_flags);
595 593
596 else { 594 else {
597 if (!ipc.addr) 595 if (!ipc.addr)
598 ipc.addr = rt->rt_dst; 596 ipc.addr = fl4.daddr;
599 lock_sock(sk); 597 lock_sock(sk);
600 err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0, 598 err = ip_append_data(sk, ip_generic_getfrag,
601 &ipc, &rt, msg->msg_flags); 599 msg->msg_iov, len, 0,
600 &ipc, &rt, msg->msg_flags);
602 if (err) 601 if (err)
603 ip_flush_pending_frames(sk); 602 ip_flush_pending_frames(sk);
604 else if (!(msg->msg_flags & MSG_MORE)) { 603 else if (!(msg->msg_flags & MSG_MORE)) {
605 err = ip_push_pending_frames(sk); 604 err = ip_push_pending_frames(sk, &fl4);
606 if (err == -ENOBUFS && !inet->recverr) 605 if (err == -ENOBUFS && !inet->recverr)
607 err = 0; 606 err = 0;
608 } 607 }
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ba9f137f5aa7..006e2ccd6cc2 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -774,7 +774,7 @@ static int udp_push_pending_frames(struct sock *sk)
774 struct sk_buff *skb; 774 struct sk_buff *skb;
775 int err = 0; 775 int err = 0;
776 776
777 skb = ip_finish_skb(sk); 777 skb = ip_finish_skb(sk, fl4);
778 if (!skb) 778 if (!skb)
779 goto out; 779 goto out;
780 780
@@ -958,7 +958,7 @@ back_from_confirm:
958 958
959 /* Lockless fast path for the non-corking case. */ 959 /* Lockless fast path for the non-corking case. */
960 if (!corkreq) { 960 if (!corkreq) {
961 skb = ip_make_skb(sk, getfrag, msg->msg_iov, ulen, 961 skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen,
962 sizeof(struct udphdr), &ipc, &rt, 962 sizeof(struct udphdr), &ipc, &rt,
963 msg->msg_flags); 963 msg->msg_flags);
964 err = PTR_ERR(skb); 964 err = PTR_ERR(skb);