~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv4/datagram.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  *      common UDP/RAW code
  4  *      Linux INET implementation
  5  *
  6  * Authors:
  7  *      Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
  8  */
  9 
 10 #include <linux/types.h>
 11 #include <linux/module.h>
 12 #include <linux/in.h>
 13 #include <net/ip.h>
 14 #include <net/sock.h>
 15 #include <net/route.h>
 16 #include <net/tcp_states.h>
 17 #include <net/sock_reuseport.h>
 18 
 19 int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 20 {
 21         struct inet_sock *inet = inet_sk(sk);
 22         struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
 23         struct flowi4 *fl4;
 24         struct rtable *rt;
 25         __be32 saddr;
 26         int oif;
 27         int err;
 28 
 29 
 30         if (addr_len < sizeof(*usin))
 31                 return -EINVAL;
 32 
 33         if (usin->sin_family != AF_INET)
 34                 return -EAFNOSUPPORT;
 35 
 36         sk_dst_reset(sk);
 37 
 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);
 43                 if (!saddr)
 44                         saddr = READ_ONCE(inet->mc_addr);
 45         } else if (!oif) {
 46                 oif = READ_ONCE(inet->uc_index);
 47         }
 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,
 51                               usin->sin_port, sk);
 52         if (IS_ERR(rt)) {
 53                 err = PTR_ERR(rt);
 54                 if (err == -ENETUNREACH)
 55                         IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
 56                 goto out;
 57         }
 58 
 59         if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
 60                 ip_rt_put(rt);
 61                 err = -EACCES;
 62                 goto out;
 63         }
 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);
 70         }
 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;
 75         sk_set_txhash(sk);
 76         atomic_set(&inet->inet_id, get_random_u16());
 77 
 78         sk_dst_set(sk, &rt->dst);
 79         err = 0;
 80 out:
 81         return err;
 82 }
 83 EXPORT_SYMBOL(__ip4_datagram_connect);
 84 
 85 int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 86 {
 87         int res;
 88 
 89         lock_sock(sk);
 90         res = __ip4_datagram_connect(sk, uaddr, addr_len);
 91         release_sock(sk);
 92         return res;
 93 }
 94 EXPORT_SYMBOL(ip4_datagram_connect);
 95 
 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.
 99  */
100 void ip4_datagram_release_cb(struct sock *sk)
101 {
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;
106         struct flowi4 fl4;
107         struct rtable *rt;
108 
109         rcu_read_lock();
110 
111         dst = __sk_dst_get(sk);
112         if (!dst || !dst->obsolete || dst->ops->check(dst, 0)) {
113                 rcu_read_unlock();
114                 return;
115         }
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);
123 
124         dst = !IS_ERR(rt) ? &rt->dst : NULL;
125         sk_dst_set(sk, dst);
126 
127         rcu_read_unlock();
128 }
129 EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);
130 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php