3 * Linux INET implementation
6 * Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
14 #include <linux/types.h>
15 #include <linux/module.h>
20 #include <net/route.h>
21 #include <net/tcp_states.h>
23 int ip4_datagram_connect(struct sock
*sk
, struct sockaddr
*uaddr
, int addr_len
)
25 struct inet_sock
*inet
= inet_sk(sk
);
26 struct sockaddr_in
*usin
= (struct sockaddr_in
*) uaddr
;
34 if (addr_len
< sizeof(*usin
))
37 if (usin
->sin_family
!= AF_INET
)
44 oif
= sk
->sk_bound_dev_if
;
45 saddr
= inet
->inet_saddr
;
46 if (ipv4_is_multicast(usin
->sin_addr
.s_addr
)) {
50 saddr
= inet
->mc_addr
;
52 fl4
= &inet
->cork
.fl
.u
.ip4
;
53 rt
= ip_route_connect(fl4
, usin
->sin_addr
.s_addr
, saddr
,
54 RT_CONN_FLAGS(sk
), oif
,
56 inet
->inet_sport
, usin
->sin_port
, sk
, true);
59 if (err
== -ENETUNREACH
)
60 IP_INC_STATS_BH(sock_net(sk
), IPSTATS_MIB_OUTNOROUTES
);
64 if ((rt
->rt_flags
& RTCF_BROADCAST
) && !sock_flag(sk
, SOCK_BROADCAST
)) {
69 if (!inet
->inet_saddr
)
70 inet
->inet_saddr
= fl4
->saddr
; /* Update source address */
71 if (!inet
->inet_rcv_saddr
) {
72 inet
->inet_rcv_saddr
= fl4
->saddr
;
73 if (sk
->sk_prot
->rehash
)
74 sk
->sk_prot
->rehash(sk
);
76 inet
->inet_daddr
= fl4
->daddr
;
77 inet
->inet_dport
= usin
->sin_port
;
78 sk
->sk_state
= TCP_ESTABLISHED
;
79 inet
->inet_id
= jiffies
;
81 sk_dst_set(sk
, &rt
->dst
);
87 EXPORT_SYMBOL(ip4_datagram_connect
);
89 void ip4_datagram_release_cb(struct sock
*sk
)
91 const struct inet_sock
*inet
= inet_sk(sk
);
92 const struct ip_options_rcu
*inet_opt
;
93 __be32 daddr
= inet
->inet_daddr
;
97 if (! __sk_dst_get(sk
) || __sk_dst_check(sk
, 0))
101 inet_opt
= rcu_dereference(inet
->inet_opt
);
102 if (inet_opt
&& inet_opt
->opt
.srr
)
103 daddr
= inet_opt
->opt
.faddr
;
104 rt
= ip_route_output_ports(sock_net(sk
), &fl4
, sk
, daddr
,
105 inet
->inet_saddr
, inet
->inet_dport
,
106 inet
->inet_sport
, sk
->sk_protocol
,
107 RT_CONN_FLAGS(sk
), sk
->sk_bound_dev_if
);
109 __sk_dst_set(sk
, &rt
->dst
);
112 EXPORT_SYMBOL_GPL(ip4_datagram_release_cb
);