~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to arch/um/drivers/mcast_user.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 "kern_constants.h"
19
 
#include "mcast.h"
20
 
#include "net_user.h"
21
 
#include "um_malloc.h"
22
 
#include "user.h"
23
 
 
24
 
static struct sockaddr_in *new_addr(char *addr, unsigned short port)
25
 
{
26
 
        struct sockaddr_in *sin;
27
 
 
28
 
        sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
29
 
        if (sin == NULL) {
30
 
                printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
31
 
                       "failed\n");
32
 
                return NULL;
33
 
        }
34
 
        sin->sin_family = AF_INET;
35
 
        sin->sin_addr.s_addr = in_aton(addr);
36
 
        sin->sin_port = htons(port);
37
 
        return sin;
38
 
}
39
 
 
40
 
static int mcast_user_init(void *data, void *dev)
41
 
{
42
 
        struct mcast_data *pri = data;
43
 
 
44
 
        pri->mcast_addr = new_addr(pri->addr, pri->port);
45
 
        pri->dev = dev;
46
 
        return 0;
47
 
}
48
 
 
49
 
static void mcast_remove(void *data)
50
 
{
51
 
        struct mcast_data *pri = data;
52
 
 
53
 
        kfree(pri->mcast_addr);
54
 
        pri->mcast_addr = NULL;
55
 
}
56
 
 
57
 
static int mcast_open(void *data)
58
 
{
59
 
        struct mcast_data *pri = data;
60
 
        struct sockaddr_in *sin = pri->mcast_addr;
61
 
        struct ip_mreq mreq;
62
 
        int fd, yes = 1, err = -EINVAL;
63
 
 
64
 
 
65
 
        if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
66
 
                goto out;
67
 
 
68
 
        fd = socket(AF_INET, SOCK_DGRAM, 0);
69
 
 
70
 
        if (fd < 0) {
71
 
                err = -errno;
72
 
                printk(UM_KERN_ERR "mcast_open : data socket failed, "
73
 
                       "errno = %d\n", errno);
74
 
                goto out;
75
 
        }
76
 
 
77
 
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
78
 
                err = -errno;
79
 
                printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, "
80
 
                       "errno = %d\n", errno);
81
 
                goto out_close;
82
 
        }
83
 
 
84
 
        /* set ttl according to config */
85
 
        if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
86
 
                       sizeof(pri->ttl)) < 0) {
87
 
                err = -errno;
88
 
                printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, "
89
 
                       "error = %d\n", errno);
90
 
                goto out_close;
91
 
        }
92
 
 
93
 
        /* set LOOP, so data does get fed back to local sockets */
94
 
        if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
95
 
                err = -errno;
96
 
                printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, "
97
 
                       "error = %d\n", errno);
98
 
                goto out_close;
99
 
        }
100
 
 
101
 
        /* bind socket to mcast address */
102
 
        if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
103
 
                err = -errno;
104
 
                printk(UM_KERN_ERR "mcast_open : data bind failed, "
105
 
                       "errno = %d\n", errno);
106
 
                goto out_close;
107
 
        }
108
 
 
109
 
        /* subscribe to the multicast group */
110
 
        mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
111
 
        mreq.imr_interface.s_addr = 0;
112
 
        if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
113
 
                       &mreq, sizeof(mreq)) < 0) {
114
 
                err = -errno;
115
 
                printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, "
116
 
                       "error = %d\n", errno);
117
 
                printk(UM_KERN_ERR "There appears not to be a multicast-"
118
 
                       "capable network interface on the host.\n");
119
 
                printk(UM_KERN_ERR "eth0 should be configured in order to use "
120
 
                       "the multicast transport.\n");
121
 
                goto out_close;
122
 
        }
123
 
 
124
 
        return fd;
125
 
 
126
 
 out_close:
127
 
        close(fd);
128
 
 out:
129
 
        return err;
130
 
}
131
 
 
132
 
static void mcast_close(int fd, void *data)
133
 
{
134
 
        struct ip_mreq mreq;
135
 
        struct mcast_data *pri = data;
136
 
        struct sockaddr_in *sin = pri->mcast_addr;
137
 
 
138
 
        mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
139
 
        mreq.imr_interface.s_addr = 0;
140
 
        if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
141
 
                       &mreq, sizeof(mreq)) < 0) {
142
 
                printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, "
143
 
                       "error = %d\n", errno);
144
 
        }
145
 
 
146
 
        close(fd);
147
 
}
148
 
 
149
 
int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
150
 
{
151
 
        struct sockaddr_in *data_addr = pri->mcast_addr;
152
 
 
153
 
        return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
154
 
}
155
 
 
156
 
const struct net_user_info mcast_user_info = {
157
 
        .init           = mcast_user_init,
158
 
        .open           = mcast_open,
159
 
        .close          = mcast_close,
160
 
        .remove         = mcast_remove,
161
 
        .add_address    = NULL,
162
 
        .delete_address = NULL,
163
 
        .mtu            = ETH_MAX_PACKET,
164
 
        .max_packet     = ETH_MAX_PACKET + ETH_HEADER_OTHER,
165
 
};