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

TOMOYO Linux Cross Reference
Linux/arch/um/drivers/umcast_user.c

Version: ~ [ linux-5.6-rc3 ] ~ [ linux-5.5.6 ] ~ [ linux-5.4.22 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.106 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.171 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.214 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.214 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * user-mode-linux networking multicast transport
  3  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  4  * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
  5  *
  6  * based on the existing uml-networking code, which is
  7  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  8  * James Leu (jleu@mindspring.net).
  9  * Copyright (C) 2001 by various other people who didn't put their name here.
 10  *
 11  * Licensed under the GPL.
 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 | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp