cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

datagram.c (3098B)


      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
     19int __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 = inet->mc_index;
     43		if (!saddr)
     44			saddr = inet->mc_addr;
     45	}
     46	fl4 = &inet->cork.fl.u.ip4;
     47	rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr, oif,
     48			      sk->sk_protocol, inet->inet_sport,
     49			      usin->sin_port, sk);
     50	if (IS_ERR(rt)) {
     51		err = PTR_ERR(rt);
     52		if (err == -ENETUNREACH)
     53			IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
     54		goto out;
     55	}
     56
     57	if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
     58		ip_rt_put(rt);
     59		err = -EACCES;
     60		goto out;
     61	}
     62	if (!inet->inet_saddr)
     63		inet->inet_saddr = fl4->saddr;	/* Update source address */
     64	if (!inet->inet_rcv_saddr) {
     65		inet->inet_rcv_saddr = fl4->saddr;
     66		if (sk->sk_prot->rehash)
     67			sk->sk_prot->rehash(sk);
     68	}
     69	inet->inet_daddr = fl4->daddr;
     70	inet->inet_dport = usin->sin_port;
     71	reuseport_has_conns(sk, true);
     72	sk->sk_state = TCP_ESTABLISHED;
     73	sk_set_txhash(sk);
     74	inet->inet_id = prandom_u32();
     75
     76	sk_dst_set(sk, &rt->dst);
     77	err = 0;
     78out:
     79	return err;
     80}
     81EXPORT_SYMBOL(__ip4_datagram_connect);
     82
     83int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
     84{
     85	int res;
     86
     87	lock_sock(sk);
     88	res = __ip4_datagram_connect(sk, uaddr, addr_len);
     89	release_sock(sk);
     90	return res;
     91}
     92EXPORT_SYMBOL(ip4_datagram_connect);
     93
     94/* Because UDP xmit path can manipulate sk_dst_cache without holding
     95 * socket lock, we need to use sk_dst_set() here,
     96 * even if we own the socket lock.
     97 */
     98void ip4_datagram_release_cb(struct sock *sk)
     99{
    100	const struct inet_sock *inet = inet_sk(sk);
    101	const struct ip_options_rcu *inet_opt;
    102	__be32 daddr = inet->inet_daddr;
    103	struct dst_entry *dst;
    104	struct flowi4 fl4;
    105	struct rtable *rt;
    106
    107	rcu_read_lock();
    108
    109	dst = __sk_dst_get(sk);
    110	if (!dst || !dst->obsolete || dst->ops->check(dst, 0)) {
    111		rcu_read_unlock();
    112		return;
    113	}
    114	inet_opt = rcu_dereference(inet->inet_opt);
    115	if (inet_opt && inet_opt->opt.srr)
    116		daddr = inet_opt->opt.faddr;
    117	rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr,
    118				   inet->inet_saddr, inet->inet_dport,
    119				   inet->inet_sport, sk->sk_protocol,
    120				   RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
    121
    122	dst = !IS_ERR(rt) ? &rt->dst : NULL;
    123	sk_dst_set(sk, dst);
    124
    125	rcu_read_unlock();
    126}
    127EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);