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

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

Version: ~ [ linux-5.9 ] ~ [ linux-5.8.14 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.70 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.150 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.200 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.238 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.238 ] ~ [ 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.85 ] ~ [ 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-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 by Harald Welte <laforge@gnumonks.org>
  4  *
  5  * based on the existing uml-networking code, which is
  6  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 
  7  * James Leu (jleu@mindspring.net).
  8  * Copyright (C) 2001 by various other people who didn't put their name here.
  9  *
 10  * Licensed under the GPL.
 11  *
 12  */
 13 
 14 #include <errno.h>
 15 #include <unistd.h>
 16 #include <linux/inet.h>
 17 #include <sys/socket.h>
 18 #include <sys/un.h>
 19 #include <sys/time.h>
 20 #include <netinet/in.h>
 21 #include "net_user.h"
 22 #include "mcast.h"
 23 #include "kern_util.h"
 24 #include "user_util.h"
 25 #include "user.h"
 26 
 27 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 28 
 29 static struct sockaddr_in *new_addr(char *addr, unsigned short port)
 30 {
 31         struct sockaddr_in *sin;
 32 
 33         sin = um_kmalloc(sizeof(struct sockaddr_in));
 34         if(sin == NULL){
 35                 printk("new_addr: allocation of sockaddr_in failed\n");
 36                 return(NULL);
 37         }
 38         sin->sin_family = AF_INET;
 39         sin->sin_addr.s_addr = in_aton(addr);
 40         sin->sin_port = port;
 41         return(sin);
 42 }
 43 
 44 static void mcast_user_init(void *data, void *dev)
 45 {
 46         struct mcast_data *pri = data;
 47 
 48         pri->mcast_addr = new_addr(pri->addr, pri->port);
 49         pri->dev = dev;
 50 }
 51 
 52 static int mcast_open(void *data)
 53 {
 54         struct mcast_data *pri = data;
 55         struct sockaddr_in *sin = pri->mcast_addr;
 56         struct ip_mreq mreq;
 57         int fd, yes = 1;
 58 
 59 
 60         if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
 61                 fd = -EINVAL;
 62                 goto out;
 63         }
 64 
 65         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
 66                 printk("mcast_open : data socket failed, errno = %d\n", 
 67                        errno);
 68                 fd = -ENOMEM;
 69                 goto out;
 70         }
 71 
 72         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
 73                 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
 74                         errno);
 75                 close(fd);
 76                 fd = -EINVAL;
 77                 goto out;
 78         }
 79 
 80         /* set ttl according to config */
 81         if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
 82                        sizeof(pri->ttl)) < 0) {
 83                 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
 84                         errno);
 85                 close(fd);
 86                 fd = -EINVAL;
 87                 goto out;
 88         }
 89 
 90         /* set LOOP, so data does get fed back to local sockets */
 91         if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
 92                 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
 93                         errno);
 94                 close(fd);
 95                 fd = -EINVAL;
 96                 goto out;
 97         }
 98 
 99         /* bind socket to mcast address */
100         if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
101                 printk("mcast_open : data bind failed, errno = %d\n", errno);
102                 close(fd);
103                 fd = -EINVAL;
104                 goto out;
105         }               
106         
107         /* subscribe to the multicast group */
108         mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
109         mreq.imr_interface.s_addr = 0;
110         if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, 
111                        &mreq, sizeof(mreq)) < 0) {
112                 printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n",
113                         errno);
114                 printk("There appears not to be a multicast-capable network "
115                        "interface on the host.\n");
116                 printk("eth0 should be configured in order to use the "
117                        "multicast transport.\n");
118                 close(fd);
119                 fd = -EINVAL;
120         }
121 
122  out:
123         return(fd);
124 }
125 
126 static void mcast_close(int fd, void *data)
127 {
128         struct ip_mreq mreq;
129         struct mcast_data *pri = data;
130         struct sockaddr_in *sin = pri->mcast_addr;
131 
132         mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
133         mreq.imr_interface.s_addr = 0;
134         if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
135                        &mreq, sizeof(mreq)) < 0) {
136                 printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n",
137                         errno);
138         }
139 
140         close(fd);
141 }
142 
143 int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
144 {
145         struct sockaddr_in *data_addr = pri->mcast_addr;
146 
147         return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)));
148 }
149 
150 static int mcast_set_mtu(int mtu, void *data)
151 {
152         return(mtu);
153 }
154 
155 struct net_user_info mcast_user_info = {
156         .init           = mcast_user_init,
157         .open           = mcast_open,
158         .close          = mcast_close,
159         .remove         = NULL,
160         .set_mtu        = mcast_set_mtu,
161         .add_address    = NULL,
162         .delete_address = NULL,
163         .max_packet     = MAX_PACKET - ETH_HEADER_OTHER
164 };
165 
166 /*
167  * Overrides for Emacs so that we follow Linus's tabbing style.
168  * Emacs will notice this stuff at the end of the file and automatically
169  * adjust the settings for this buffer only.  This must remain at the end
170  * of the file.
171  * ---------------------------------------------------------------------------
172  * Local variables:
173  * c-file-style: "linux"
174  * End:
175  */
176 

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