1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Linux INET implementation
7 * Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
10 #include <linux/types.h>
11 #include <linux/module.h>
15 #include <net/route.h>
16 #include <net/tcp_states.h>
17 #include <net/sock_reuseport.h>
19 int __ip4_datagram_connect(struct sock
*sk
, struct sockaddr
*uaddr
, int addr_len
)
21 struct inet_sock
*inet
= inet_sk(sk
);
22 struct sockaddr_in
*usin
= (struct sockaddr_in
*) uaddr
;
30 if (addr_len
< sizeof(*usin
))
33 if (usin
->sin_family
!= AF_INET
)
38 oif
= sk
->sk_bound_dev_if
;
39 saddr
= inet
->inet_saddr
;
40 if (ipv4_is_multicast(usin
->sin_addr
.s_addr
)) {
41 if (!oif
|| netif_index_is_l3_master(sock_net(sk
), oif
))
42 oif
= READ_ONCE(inet
->mc_index
);
44 saddr
= READ_ONCE(inet
->mc_addr
);
46 oif
= READ_ONCE(inet
->uc_index
);
48 fl4
= &inet
->cork
.fl
.u
.ip4
;
49 rt
= ip_route_connect(fl4
, usin
->sin_addr
.s_addr
, saddr
, oif
,
50 sk
->sk_protocol
, inet
->inet_sport
,
54 if (err
== -ENETUNREACH
)
55 IP_INC_STATS(sock_net(sk
), IPSTATS_MIB_OUTNOROUTES
);
59 if ((rt
->rt_flags
& RTCF_BROADCAST
) && !sock_flag(sk
, SOCK_BROADCAST
)) {
64 if (!inet
->inet_saddr
)
65 inet
->inet_saddr
= fl4
->saddr
; /* Update source address */
66 if (!inet
->inet_rcv_saddr
) {
67 inet
->inet_rcv_saddr
= fl4
->saddr
;
68 if (sk
->sk_prot
->rehash
)
69 sk
->sk_prot
->rehash(sk
);
71 inet
->inet_daddr
= fl4
->daddr
;
72 inet
->inet_dport
= usin
->sin_port
;
73 reuseport_has_conns_set(sk
);
74 sk
->sk_state
= TCP_ESTABLISHED
;
76 atomic_set(&inet
->inet_id
, get_random_u16());
78 sk_dst_set(sk
, &rt
->dst
);
83 EXPORT_SYMBOL(__ip4_datagram_connect
);
85 int ip4_datagram_connect(struct sock
*sk
, struct sockaddr
*uaddr
, int addr_len
)
90 res
= __ip4_datagram_connect(sk
, uaddr
, addr_len
);
94 EXPORT_SYMBOL(ip4_datagram_connect
);
96 /* Because UDP xmit path can manipulate sk_dst_cache without holding
97 * socket lock, we need to use sk_dst_set() here,
98 * even if we own the socket lock.
100 void ip4_datagram_release_cb(struct sock
*sk
)
102 const struct inet_sock
*inet
= inet_sk(sk
);
103 const struct ip_options_rcu
*inet_opt
;
104 __be32 daddr
= inet
->inet_daddr
;
105 struct dst_entry
*dst
;
111 dst
= __sk_dst_get(sk
);
112 if (!dst
|| !dst
->obsolete
|| dst
->ops
->check(dst
, 0)) {
116 inet_opt
= rcu_dereference(inet
->inet_opt
);
117 if (inet_opt
&& inet_opt
->opt
.srr
)
118 daddr
= inet_opt
->opt
.faddr
;
119 rt
= ip_route_output_ports(sock_net(sk
), &fl4
, sk
, daddr
,
120 inet
->inet_saddr
, inet
->inet_dport
,
121 inet
->inet_sport
, sk
->sk_protocol
,
122 ip_sock_rt_tos(sk
), sk
->sk_bound_dev_if
);
124 dst
= !IS_ERR(rt
) ? &rt
->dst
: NULL
;
129 EXPORT_SYMBOL_GPL(ip4_datagram_release_cb
);