aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/raw.c
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 /net/ipv4/raw.c
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>
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r--net/ipv4/raw.c59
1 files changed, 29 insertions, 30 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index a8659e0c4a6..6fee91f656a 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 }