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

umcast_user.c (4688B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * user-mode-linux networking multicast transport
      4 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
      5 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
      6 *
      7 * based on the existing uml-networking code, which is
      8 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
      9 * James Leu (jleu@mindspring.net).
     10 * Copyright (C) 2001 by various other people who didn't put their name here.
     11 *
     12 *
     13 */
     14
     15#include <unistd.h>
     16#include <errno.h>
     17#include <netinet/in.h>
     18#include "umcast.h"
     19#include <net_user.h>
     20#include <um_malloc.h>
     21
     22static struct sockaddr_in *new_addr(char *addr, unsigned short port)
     23{
     24	struct sockaddr_in *sin;
     25
     26	sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
     27	if (sin == NULL) {
     28		printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
     29		       "failed\n");
     30		return NULL;
     31	}
     32	sin->sin_family = AF_INET;
     33	if (addr)
     34		sin->sin_addr.s_addr = in_aton(addr);
     35	else
     36		sin->sin_addr.s_addr = INADDR_ANY;
     37	sin->sin_port = htons(port);
     38	return sin;
     39}
     40
     41static int umcast_user_init(void *data, void *dev)
     42{
     43	struct umcast_data *pri = data;
     44
     45	pri->remote_addr = new_addr(pri->addr, pri->rport);
     46	if (pri->unicast)
     47		pri->listen_addr = new_addr(NULL, pri->lport);
     48	else
     49		pri->listen_addr = pri->remote_addr;
     50	pri->dev = dev;
     51	return 0;
     52}
     53
     54static void umcast_remove(void *data)
     55{
     56	struct umcast_data *pri = data;
     57
     58	kfree(pri->listen_addr);
     59	if (pri->unicast)
     60		kfree(pri->remote_addr);
     61	pri->listen_addr = pri->remote_addr = NULL;
     62}
     63
     64static int umcast_open(void *data)
     65{
     66	struct umcast_data *pri = data;
     67	struct sockaddr_in *lsin = pri->listen_addr;
     68	struct sockaddr_in *rsin = pri->remote_addr;
     69	struct ip_mreq mreq;
     70	int fd, yes = 1, err = -EINVAL;
     71
     72
     73	if ((!pri->unicast && lsin->sin_addr.s_addr == 0) ||
     74	    (rsin->sin_addr.s_addr == 0) ||
     75	    (lsin->sin_port == 0) || (rsin->sin_port == 0))
     76		goto out;
     77
     78	fd = socket(AF_INET, SOCK_DGRAM, 0);
     79
     80	if (fd < 0) {
     81		err = -errno;
     82		printk(UM_KERN_ERR "umcast_open : data socket failed, "
     83		       "errno = %d\n", errno);
     84		goto out;
     85	}
     86
     87	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
     88		err = -errno;
     89		printk(UM_KERN_ERR "umcast_open: SO_REUSEADDR failed, "
     90		       "errno = %d\n", errno);
     91		goto out_close;
     92	}
     93
     94	if (!pri->unicast) {
     95		/* set ttl according to config */
     96		if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
     97			       sizeof(pri->ttl)) < 0) {
     98			err = -errno;
     99			printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_TTL "
    100			       "failed, error = %d\n", errno);
    101			goto out_close;
    102		}
    103
    104		/* set LOOP, so data does get fed back to local sockets */
    105		if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP,
    106			       &yes, sizeof(yes)) < 0) {
    107			err = -errno;
    108			printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_LOOP "
    109			       "failed, error = %d\n", errno);
    110			goto out_close;
    111		}
    112	}
    113
    114	/* bind socket to the address */
    115	if (bind(fd, (struct sockaddr *) lsin, sizeof(*lsin)) < 0) {
    116		err = -errno;
    117		printk(UM_KERN_ERR "umcast_open : data bind failed, "
    118		       "errno = %d\n", errno);
    119		goto out_close;
    120	}
    121
    122	if (!pri->unicast) {
    123		/* subscribe to the multicast group */
    124		mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr;
    125		mreq.imr_interface.s_addr = 0;
    126		if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
    127			       &mreq, sizeof(mreq)) < 0) {
    128			err = -errno;
    129			printk(UM_KERN_ERR "umcast_open: IP_ADD_MEMBERSHIP "
    130			       "failed, error = %d\n", errno);
    131			printk(UM_KERN_ERR "There appears not to be a "
    132			       "multicast-capable network interface on the "
    133			       "host.\n");
    134			printk(UM_KERN_ERR "eth0 should be configured in order "
    135			       "to use the multicast transport.\n");
    136			goto out_close;
    137		}
    138	}
    139
    140	return fd;
    141
    142 out_close:
    143	close(fd);
    144 out:
    145	return err;
    146}
    147
    148static void umcast_close(int fd, void *data)
    149{
    150	struct umcast_data *pri = data;
    151
    152	if (!pri->unicast) {
    153		struct ip_mreq mreq;
    154		struct sockaddr_in *lsin = pri->listen_addr;
    155
    156		mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr;
    157		mreq.imr_interface.s_addr = 0;
    158		if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
    159			       &mreq, sizeof(mreq)) < 0) {
    160			printk(UM_KERN_ERR "umcast_close: IP_DROP_MEMBERSHIP "
    161			       "failed, error = %d\n", errno);
    162		}
    163	}
    164
    165	close(fd);
    166}
    167
    168int umcast_user_write(int fd, void *buf, int len, struct umcast_data *pri)
    169{
    170	struct sockaddr_in *data_addr = pri->remote_addr;
    171
    172	return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
    173}
    174
    175const struct net_user_info umcast_user_info = {
    176	.init	= umcast_user_init,
    177	.open	= umcast_open,
    178	.close	= umcast_close,
    179	.remove	= umcast_remove,
    180	.add_address	= NULL,
    181	.delete_address = NULL,
    182	.mtu	= ETH_MAX_PACKET,
    183	.max_packet	= ETH_MAX_PACKET + ETH_HEADER_OTHER,
    184};