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

TOMOYO Linux Cross Reference
Linux/arch/um/drivers/umcast_user.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
  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 
 22 static 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 
 41 static 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 
 54 static 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 
 64 static 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 
148 static 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 
168 int 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 
175 const 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 };
185 

~ [ 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