cachesyncd/multicast.c

128 lines
4.1 KiB
C
Raw Normal View History

2006-06-23 22:02:31 +02:00
/***************************************************************************
* Copyright (C) 06/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "configfile.h"
#include "logging.h"
2006-07-27 17:26:11 +02:00
#define DEFAULT_DEVICE "eth0"
#define DEFAULT_GROUP "224.0.0.1"
#define DEFAULT_PORT 2000
2006-06-23 22:02:31 +02:00
static struct sockaddr_in dest_addr;
int mcast_init()
{
struct ip_mreq multiaddr;
struct ifreq ifr;
// open socket
2006-07-27 17:26:11 +02:00
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
2006-06-23 22:02:31 +02:00
log_print(LOG_ERROR, "mcast_init: socket()");
return -1;
}
// get device flags
2006-07-27 17:26:11 +02:00
char *mcastdev = config_get_string("global", "mcastdev", DEFAULT_DEVICE);
2006-06-23 22:02:31 +02:00
strncpy(ifr.ifr_name, mcastdev, sizeof(ifr.ifr_name));
2006-07-27 17:26:11 +02:00
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) != 0) {
2006-06-23 22:02:31 +02:00
log_print(LOG_WARN, "mcast_init: ioctl(SIOCGIFFLAGS)");
2006-07-27 17:26:11 +02:00
close(sockfd);
2006-06-23 22:02:31 +02:00
return -1;
}
// check device flags
if ((ifr.ifr_flags & (IFF_UP | IFF_MULTICAST)) != (IFF_UP | IFF_MULTICAST)) {
log_print(LOG_WARN, "mcast_init: device %s not up");
2006-07-27 17:26:11 +02:00
close(sockfd);
2006-06-23 22:02:31 +02:00
return -1;
}
2006-07-27 17:26:11 +02:00
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, sizeof(ifr.ifr_name)) < 0) {
2006-06-23 22:02:31 +02:00
log_print(LOG_WARN, "mcast_init: setsockopt(SO_BINDTODEVICE)");
2006-07-27 17:26:11 +02:00
// close(sockfd);
2006-06-23 22:02:31 +02:00
// return -1;
}
2006-07-27 17:26:11 +02:00
char *mcastgroup = config_get_string("global", "mcastgroup", DEFAULT_GROUP);
int mcastport = config_get_int("global", "mcastport", DEFAULT_PORT);
2006-06-23 22:02:31 +02:00
dest_addr.sin_family = AF_INET;
inet_aton(mcastgroup, &dest_addr.sin_addr);
dest_addr.sin_port = htons(mcastport);
2006-07-27 17:26:11 +02:00
if (bind(sockfd, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
2006-06-23 22:02:31 +02:00
log_print(LOG_WARN, "mcast_init: bind()");
2006-07-27 17:26:11 +02:00
close(sockfd);
2006-06-23 22:02:31 +02:00
return -1;
}
// get interface address
2006-07-27 17:26:11 +02:00
if (ioctl(sockfd, SIOCGIFADDR, &ifr) != 0) {
2006-06-23 22:02:31 +02:00
log_print(LOG_WARN, "mcast_init: ioctl(SIOCGIFADDR)");
2006-07-27 17:26:11 +02:00
close(sockfd);
2006-06-23 22:02:31 +02:00
return -1;
}
// check address family
if (ifr.ifr_addr.sa_family != AF_INET) {
log_print(LOG_WARN, "mcast_init: unknown address family");
2006-07-27 17:26:11 +02:00
close(sockfd);
2006-06-23 22:02:31 +02:00
return -1;
}
2006-10-04 21:45:18 +02:00
char loop = 0;
2006-07-27 18:53:57 +02:00
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))) {
log_print(LOG_WARN, "mcast_init: setsockopt(IP_MULTICAST_LOOP)");
close(sockfd);
return -1;
}
2006-06-23 22:02:31 +02:00
inet_aton(mcastgroup, &multiaddr.imr_multiaddr);
multiaddr.imr_interface.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
2006-07-27 17:26:11 +02:00
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
2006-06-23 22:02:31 +02:00
&multiaddr, sizeof(multiaddr)) == -1) {
log_print(LOG_WARN, "mcast_init: setsockopt(IP_ADD_MEMBERSHIP)");
2006-07-27 17:26:11 +02:00
close(sockfd);
2006-06-23 22:02:31 +02:00
return -1;
}
2006-07-27 17:26:11 +02:00
return sockfd;
2006-06-23 22:02:31 +02:00
}
int mcast_send(int sock, char *buf, int len)
{
return sendto(sock, buf, len, MSG_NOSIGNAL, (const struct sockaddr*)&dest_addr, sizeof(dest_addr));
}
void msock_close(int sock)
{
close(sock);
}