Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * INET An implementation of the TCP/IP protocol suite for the LINUX 4 : : * operating system. INET is implemented using the BSD Socket 5 : : * interface as the means of communication with the user level. 6 : : * 7 : : * Pseudo-driver for the loopback interface. 8 : : * 9 : : * Version: @(#)loopback.c 1.0.4b 08/16/93 10 : : * 11 : : * Authors: Ross Biro 12 : : * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 13 : : * Donald Becker, <becker@scyld.com> 14 : : * 15 : : * Alan Cox : Fixed oddments for NET3.014 16 : : * Alan Cox : Rejig for NET3.029 snap #3 17 : : * Alan Cox : Fixed NET3.029 bugs and sped up 18 : : * Larry McVoy : Tiny tweak to double performance 19 : : * Alan Cox : Backed out LMV's tweak - the linux mm 20 : : * can't take it... 21 : : * Michael Griffith: Don't bother computing the checksums 22 : : * on packets received on the loopback 23 : : * interface. 24 : : * Alexey Kuznetsov: Potential hang under some extreme 25 : : * cases removed. 26 : : */ 27 : : #include <linux/kernel.h> 28 : : #include <linux/jiffies.h> 29 : : #include <linux/module.h> 30 : : #include <linux/interrupt.h> 31 : : #include <linux/fs.h> 32 : : #include <linux/types.h> 33 : : #include <linux/string.h> 34 : : #include <linux/socket.h> 35 : : #include <linux/errno.h> 36 : : #include <linux/fcntl.h> 37 : : #include <linux/in.h> 38 : : 39 : : #include <linux/uaccess.h> 40 : : #include <linux/io.h> 41 : : 42 : : #include <linux/inet.h> 43 : : #include <linux/netdevice.h> 44 : : #include <linux/etherdevice.h> 45 : : #include <linux/skbuff.h> 46 : : #include <linux/ethtool.h> 47 : : #include <net/sock.h> 48 : : #include <net/checksum.h> 49 : : #include <linux/if_ether.h> /* For the statistics structure. */ 50 : : #include <linux/if_arp.h> /* For ARPHRD_ETHER */ 51 : : #include <linux/ip.h> 52 : : #include <linux/tcp.h> 53 : : #include <linux/percpu.h> 54 : : #include <linux/net_tstamp.h> 55 : : #include <net/net_namespace.h> 56 : : #include <linux/u64_stats_sync.h> 57 : : 58 : : /* blackhole_netdev - a device used for dsts that are marked expired! 59 : : * This is global device (instead of per-net-ns) since it's not needed 60 : : * to be per-ns and gets initialized at boot time. 61 : : */ 62 : : struct net_device *blackhole_netdev; 63 : : EXPORT_SYMBOL(blackhole_netdev); 64 : : 65 : : /* The higher levels take care of making this non-reentrant (it's 66 : : * called with bh's disabled). 67 : : */ 68 : 1 : static netdev_tx_t loopback_xmit(struct sk_buff *skb, 69 : : struct net_device *dev) 70 : : { 71 : : struct pcpu_lstats *lb_stats; 72 : : int len; 73 : : 74 : 1 : skb_tx_timestamp(skb); 75 : : 76 : : /* do not fool net_timestamp_check() with various clock bases */ 77 : 1 : skb->tstamp = 0; 78 : : 79 : 1 : skb_orphan(skb); 80 : : 81 : : /* Before queueing this packet to netif_rx(), 82 : : * make sure dst is refcounted. 83 : : */ 84 : 1 : skb_dst_force(skb); 85 : : 86 : 1 : skb->protocol = eth_type_trans(skb, dev); 87 : : 88 : : /* it's OK to use per_cpu_ptr() because BHs are off */ 89 : 1 : lb_stats = this_cpu_ptr(dev->lstats); 90 : : 91 : 1 : len = skb->len; 92 : 1 : if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { 93 : : u64_stats_update_begin(&lb_stats->syncp); 94 : 1 : lb_stats->bytes += len; 95 : 1 : lb_stats->packets++; 96 : : u64_stats_update_end(&lb_stats->syncp); 97 : : } 98 : : 99 : 1 : return NETDEV_TX_OK; 100 : : } 101 : : 102 : 3 : static void loopback_get_stats64(struct net_device *dev, 103 : : struct rtnl_link_stats64 *stats) 104 : : { 105 : : u64 bytes = 0; 106 : : u64 packets = 0; 107 : : int i; 108 : : 109 : 3 : for_each_possible_cpu(i) { 110 : : const struct pcpu_lstats *lb_stats; 111 : : u64 tbytes, tpackets; 112 : : unsigned int start; 113 : : 114 : 3 : lb_stats = per_cpu_ptr(dev->lstats, i); 115 : : do { 116 : : start = u64_stats_fetch_begin_irq(&lb_stats->syncp); 117 : 3 : tbytes = lb_stats->bytes; 118 : 3 : tpackets = lb_stats->packets; 119 : 3 : } while (u64_stats_fetch_retry_irq(&lb_stats->syncp, start)); 120 : 3 : bytes += tbytes; 121 : 3 : packets += tpackets; 122 : : } 123 : 3 : stats->rx_packets = packets; 124 : 3 : stats->tx_packets = packets; 125 : 3 : stats->rx_bytes = bytes; 126 : 3 : stats->tx_bytes = bytes; 127 : 3 : } 128 : : 129 : 0 : static u32 always_on(struct net_device *dev) 130 : : { 131 : 0 : return 1; 132 : : } 133 : : 134 : : static const struct ethtool_ops loopback_ethtool_ops = { 135 : : .get_link = always_on, 136 : : .get_ts_info = ethtool_op_get_ts_info, 137 : : }; 138 : : 139 : 3 : static int loopback_dev_init(struct net_device *dev) 140 : : { 141 : 3 : dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats); 142 : 3 : if (!dev->lstats) 143 : : return -ENOMEM; 144 : 3 : return 0; 145 : : } 146 : : 147 : 1 : static void loopback_dev_free(struct net_device *dev) 148 : : { 149 : 1 : dev_net(dev)->loopback_dev = NULL; 150 : 1 : free_percpu(dev->lstats); 151 : 1 : } 152 : : 153 : : static const struct net_device_ops loopback_ops = { 154 : : .ndo_init = loopback_dev_init, 155 : : .ndo_start_xmit = loopback_xmit, 156 : : .ndo_get_stats64 = loopback_get_stats64, 157 : : .ndo_set_mac_address = eth_mac_addr, 158 : : }; 159 : : 160 : : static void gen_lo_setup(struct net_device *dev, 161 : : unsigned int mtu, 162 : : const struct ethtool_ops *eth_ops, 163 : : const struct header_ops *hdr_ops, 164 : : const struct net_device_ops *dev_ops, 165 : : void (*dev_destructor)(struct net_device *dev)) 166 : : { 167 : 3 : dev->mtu = mtu; 168 : 3 : dev->hard_header_len = ETH_HLEN; /* 14 */ 169 : 3 : dev->min_header_len = ETH_HLEN; /* 14 */ 170 : 3 : dev->addr_len = ETH_ALEN; /* 6 */ 171 : 3 : dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ 172 : 3 : dev->flags = IFF_LOOPBACK; 173 : 3 : dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; 174 : : netif_keep_dst(dev); 175 : 3 : dev->hw_features = NETIF_F_GSO_SOFTWARE; 176 : 3 : dev->features = NETIF_F_SG | NETIF_F_FRAGLIST 177 : : | NETIF_F_GSO_SOFTWARE 178 : : | NETIF_F_HW_CSUM 179 : : | NETIF_F_RXCSUM 180 : : | NETIF_F_SCTP_CRC 181 : : | NETIF_F_HIGHDMA 182 : : | NETIF_F_LLTX 183 : : | NETIF_F_NETNS_LOCAL 184 : : | NETIF_F_VLAN_CHALLENGED 185 : : | NETIF_F_LOOPBACK; 186 : 3 : dev->ethtool_ops = eth_ops; 187 : 3 : dev->header_ops = hdr_ops; 188 : 3 : dev->netdev_ops = dev_ops; 189 : 3 : dev->needs_free_netdev = true; 190 : 3 : dev->priv_destructor = dev_destructor; 191 : : } 192 : : 193 : : /* The loopback device is special. There is only one instance 194 : : * per network namespace. 195 : : */ 196 : 3 : static void loopback_setup(struct net_device *dev) 197 : : { 198 : : gen_lo_setup(dev, (64 * 1024), &loopback_ethtool_ops, ð_header_ops, 199 : : &loopback_ops, loopback_dev_free); 200 : 3 : } 201 : : 202 : : /* Setup and register the loopback device. */ 203 : 3 : static __net_init int loopback_net_init(struct net *net) 204 : : { 205 : : struct net_device *dev; 206 : : int err; 207 : : 208 : : err = -ENOMEM; 209 : 3 : dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup); 210 : 3 : if (!dev) 211 : : goto out; 212 : : 213 : : dev_net_set(dev, net); 214 : 3 : err = register_netdev(dev); 215 : 3 : if (err) 216 : : goto out_free_netdev; 217 : : 218 : 3 : BUG_ON(dev->ifindex != LOOPBACK_IFINDEX); 219 : 3 : net->loopback_dev = dev; 220 : 3 : return 0; 221 : : 222 : : out_free_netdev: 223 : 0 : free_netdev(dev); 224 : : out: 225 : 0 : if (net_eq(net, &init_net)) 226 : 0 : panic("loopback: Failed to register netdevice: %d\n", err); 227 : : return err; 228 : : } 229 : : 230 : : /* Registered in net/core/dev.c */ 231 : : struct pernet_operations __net_initdata loopback_net_ops = { 232 : : .init = loopback_net_init, 233 : : }; 234 : : 235 : : /* blackhole netdevice */ 236 : 0 : static netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb, 237 : : struct net_device *dev) 238 : : { 239 : 0 : kfree_skb(skb); 240 : 0 : net_warn_ratelimited("%s(): Dropping skb.\n", __func__); 241 : 0 : return NETDEV_TX_OK; 242 : : } 243 : : 244 : : static const struct net_device_ops blackhole_netdev_ops = { 245 : : .ndo_start_xmit = blackhole_netdev_xmit, 246 : : }; 247 : : 248 : : /* This is a dst-dummy device used specifically for invalidated 249 : : * DSTs and unlike loopback, this is not per-ns. 250 : : */ 251 : 3 : static void blackhole_netdev_setup(struct net_device *dev) 252 : : { 253 : : gen_lo_setup(dev, ETH_MIN_MTU, NULL, NULL, &blackhole_netdev_ops, NULL); 254 : 3 : } 255 : : 256 : : /* Setup and register the blackhole_netdev. */ 257 : 3 : static int __init blackhole_netdev_init(void) 258 : : { 259 : 3 : blackhole_netdev = alloc_netdev(0, "blackhole_dev", NET_NAME_UNKNOWN, 260 : : blackhole_netdev_setup); 261 : 3 : if (!blackhole_netdev) 262 : : return -ENOMEM; 263 : : 264 : 3 : rtnl_lock(); 265 : 3 : dev_init_scheduler(blackhole_netdev); 266 : 3 : dev_activate(blackhole_netdev); 267 : 3 : rtnl_unlock(); 268 : : 269 : 3 : blackhole_netdev->flags |= IFF_UP | IFF_RUNNING; 270 : : dev_net_set(blackhole_netdev, &init_net); 271 : : 272 : 3 : return 0; 273 : : } 274 : : 275 : : device_initcall(blackhole_netdev_init);