~ubuntu-branches/ubuntu/karmic/conntrack/karmic

« back to all changes in this revision

Viewing changes to src/mcast.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Rodriguez
  • Date: 2009-06-18 18:27:31 UTC
  • mfrom: (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090618182731-xlunt56xusrrif92
Tags: 1:0.9.12-1ubuntu1
* Merge from debian unstable (LP: #380358), remaining changes:
  - Error on fwrite failure in src/read_config_lex.c.
  - Patch from Kees Cook to not ignore return value of chdir call.
* debian/copyright: Updated download site.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
 
2
 * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
3
3
 * 
4
4
 * This program is free software; you can redistribute it and/or modify
5
5
 * it under the terms of the GNU General Public License as published by
19
19
 */
20
20
 
21
21
#include "mcast.h"
22
 
#include "debug.h"
23
22
 
24
23
#include <stdio.h>
25
24
#include <stdlib.h>
29
28
#include <sys/ioctl.h>
30
29
#include <net/if.h>
31
30
#include <errno.h>
 
31
#include <limits.h>
 
32
#include <libnfnetlink/libnfnetlink.h>
32
33
 
33
34
struct mcast_sock *mcast_server_create(struct mcast_conf *conf)
34
35
{
71
72
        }
72
73
 
73
74
        if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) {
74
 
                debug("mcast_sock_server_create:socket");
75
75
                free(m);
76
76
                return NULL;
77
77
        }
78
78
 
79
 
        if(conf->iface[0]) {
80
 
                struct ifreq ifr;
81
 
 
82
 
                strncpy(ifr.ifr_name, conf->iface, sizeof(ifr.ifr_name));
83
 
 
84
 
                if (ioctl(m->fd, SIOCGIFMTU, &ifr) == -1) {
85
 
                        debug("ioctl");
86
 
                        close(m->fd);
87
 
                        free(m);
88
 
                        return NULL;
89
 
                }
90
 
                conf->mtu = ifr.ifr_mtu;
91
 
        }
92
 
 
93
79
        if (setsockopt(m->fd, SOL_SOCKET, SO_REUSEADDR, &yes, 
94
80
                                sizeof(int)) == -1) {
95
 
                debug("mcast_sock_server_create:setsockopt1");
96
81
                close(m->fd);
97
82
                free(m);
98
83
                return NULL;
107
92
                                sizeof(int)) == -1) {
108
93
                /* not supported in linux kernel < 2.6.14 */
109
94
                if (errno != ENOPROTOOPT) {
110
 
                        debug("mcast_sock_server_create:setsockopt2");
111
95
                        close(m->fd);
112
96
                        free(m);
113
97
                        return NULL;
117
101
        getsockopt(m->fd, SOL_SOCKET, SO_RCVBUF, &conf->rcvbuf, &socklen);
118
102
 
119
103
        if (bind(m->fd, (struct sockaddr *) &m->addr, m->sockaddr_len) == -1) {
120
 
                debug("mcast_sock_server_create:bind");
121
104
                close(m->fd);
122
105
                free(m);
123
106
                return NULL;
127
110
        case AF_INET:
128
111
                if (setsockopt(m->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
129
112
                               &mreq.ipv4, sizeof(mreq.ipv4)) < 0) {
130
 
                        debug("mcast_sock_server_create:setsockopt2");
131
113
                        close(m->fd);
132
114
                        free(m);
133
115
                        return NULL;
136
118
        case AF_INET6:
137
119
                if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
138
120
                               &mreq.ipv6, sizeof(mreq.ipv6)) < 0) {
139
 
                        debug("mcast_sock_server_create:setsockopt2");
140
121
                        close(m->fd);
141
122
                        free(m);
142
123
                        return NULL;
165
146
 
166
147
        if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no,
167
148
                       sizeof(int)) < 0) {
168
 
                debug("mcast_sock_client_create:setsockopt2");
169
149
                close(m->fd);
170
150
                return -1;
171
151
        }
173
153
        if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_IF,
174
154
                       &conf->ifa.interface_addr,
175
155
                       sizeof(struct in_addr)) == -1) {
176
 
                debug("mcast_sock_client_create:setsockopt3");
177
156
                close(m->fd);
178
157
                return -1;
179
158
        }
195
174
 
196
175
        if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no,
197
176
                       sizeof(int)) < 0) {
198
 
                debug("mcast_sock_client_create:setsockopt2");
199
177
                close(m->fd);
200
178
                return -1;
201
179
        }
203
181
        if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
204
182
                       &conf->ifa.interface_index6,
205
183
                       sizeof(unsigned int)) == -1) {
206
 
                debug("mcast_sock_client_create:setsockopt3");
207
184
                close(m->fd);
208
185
                return -1;
209
186
        }
223
200
        memset(m, 0, sizeof(struct mcast_sock));
224
201
 
225
202
        if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) {
226
 
                debug("mcast_sock_client_create:socket");
227
203
                free(m);
228
204
                return NULL;
229
205
        }
230
206
 
231
207
        if (setsockopt(m->fd, SOL_SOCKET, SO_NO_CHECK, &conf->checksum, 
232
208
                                sizeof(int)) == -1) {
233
 
                debug("mcast_sock_client_create:setsockopt1");
234
209
                close(m->fd);
235
210
                free(m);
236
211
                return NULL;
245
220
                                sizeof(int)) == -1) {
246
221
                /* not supported in linux kernel < 2.6.14 */
247
222
                if (errno != ENOPROTOOPT) {
248
 
                        debug("mcast_sock_server_create:setsockopt2");
249
223
                        close(m->fd);
250
224
                        free(m);
251
225
                        return NULL;
281
255
        free(m);
282
256
}
283
257
 
284
 
ssize_t mcast_send(struct mcast_sock *m, void *data, int size)
 
258
ssize_t mcast_send(struct mcast_sock *m, const void *data, int size)
285
259
{
286
260
        ssize_t ret;
287
261
        
292
266
                     (struct sockaddr *) &m->addr,
293
267
                     m->sockaddr_len);
294
268
        if (ret == -1) {
295
 
                debug("mcast_sock_send");
296
269
                m->stats.error++;
297
270
                return ret;
298
271
        }
315
288
                       (struct sockaddr *)&m->addr,
316
289
                       &sin_size);
317
290
        if (ret == -1) {
318
 
                debug("mcast_sock_recv");
319
291
                m->stats.error++;
320
292
                return ret;
321
293
        }
326
298
        return ret;
327
299
}
328
300
 
329
 
struct mcast_stats *mcast_get_stats(struct mcast_sock *m)
330
 
{
331
 
        return &m->stats;
332
 
}
333
 
 
334
 
void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r)
335
 
{
336
 
        char buf[512];
337
 
        int size;
338
 
 
339
 
        size = sprintf(buf, "multicast traffic:\n"
340
 
                            "%20llu Bytes sent "
341
 
                            "%20llu Bytes recv\n"
342
 
                            "%20llu Pckts sent "
343
 
                            "%20llu Pckts recv\n"
344
 
                            "%20llu Error send "
345
 
                            "%20llu Error recv\n\n",
346
 
                            (unsigned long long)s->stats.bytes,
347
 
                            (unsigned long long)r->stats.bytes,
348
 
                            (unsigned long long)s->stats.messages,
349
 
                            (unsigned long long)r->stats.messages,
350
 
                            (unsigned long long)s->stats.error,
351
 
                            (unsigned long long)r->stats.error);
352
 
 
353
 
        send(fd, buf, size, 0);
 
301
int mcast_get_fd(struct mcast_sock *m)
 
302
{
 
303
        return m->fd;
 
304
}
 
305
 
 
306
int
 
307
mcast_snprintf_stats(char *buf, size_t buflen, char *ifname,
 
308
                     struct mcast_stats *s, struct mcast_stats *r)
 
309
{
 
310
        size_t size;
 
311
 
 
312
        size = snprintf(buf, buflen, "multicast traffic (active device=%s):\n"
 
313
                                     "%20llu Bytes sent "
 
314
                                     "%20llu Bytes recv\n"
 
315
                                     "%20llu Pckts sent "
 
316
                                     "%20llu Pckts recv\n"
 
317
                                     "%20llu Error send "
 
318
                                     "%20llu Error recv\n\n",
 
319
                                     ifname,
 
320
                                     (unsigned long long)s->bytes,
 
321
                                     (unsigned long long)r->bytes,
 
322
                                     (unsigned long long)s->messages,
 
323
                                     (unsigned long long)r->messages,
 
324
                                     (unsigned long long)s->error,
 
325
                                     (unsigned long long)r->error);
 
326
        return size;
 
327
}
 
328
 
 
329
int
 
330
mcast_snprintf_stats2(char *buf, size_t buflen, const char *ifname, 
 
331
                      const char *status, int active,
 
332
                      struct mcast_stats *s, struct mcast_stats *r)
 
333
{
 
334
        size_t size;
 
335
 
 
336
        size = snprintf(buf, buflen, 
 
337
                        "multicast traffic device=%s status=%s role=%s:\n"
 
338
                        "%20llu Bytes sent "
 
339
                        "%20llu Bytes recv\n"
 
340
                        "%20llu Pckts sent "
 
341
                        "%20llu Pckts recv\n"
 
342
                        "%20llu Error send "
 
343
                        "%20llu Error recv\n\n",
 
344
                        ifname, status, active ? "ACTIVE" : "BACKUP",
 
345
                        (unsigned long long)s->bytes,
 
346
                        (unsigned long long)r->bytes,
 
347
                        (unsigned long long)s->messages,
 
348
                        (unsigned long long)r->messages,
 
349
                        (unsigned long long)s->error,
 
350
                        (unsigned long long)r->error);
 
351
        return size;
354
352
}