128 lines
4.1 KiB
C
128 lines
4.1 KiB
C
/***************************************************************************
|
|
* 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"
|
|
|
|
#define DEFAULT_DEVICE "eth0"
|
|
#define DEFAULT_GROUP "224.0.0.1"
|
|
#define DEFAULT_PORT 2000
|
|
|
|
static struct sockaddr_in dest_addr;
|
|
|
|
int mcast_init()
|
|
{
|
|
struct ip_mreq multiaddr;
|
|
struct ifreq ifr;
|
|
|
|
// open socket
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
if (sockfd == -1) {
|
|
log_print(LOG_ERROR, "mcast_init: socket()");
|
|
return -1;
|
|
}
|
|
|
|
// get device flags
|
|
char *mcastdev = config_get_string("global", "mcastdev", DEFAULT_DEVICE);
|
|
strncpy(ifr.ifr_name, mcastdev, sizeof(ifr.ifr_name));
|
|
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) != 0) {
|
|
log_print(LOG_WARN, "mcast_init: ioctl(SIOCGIFFLAGS)");
|
|
close(sockfd);
|
|
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");
|
|
close(sockfd);
|
|
return -1;
|
|
}
|
|
|
|
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, sizeof(ifr.ifr_name)) < 0) {
|
|
log_print(LOG_WARN, "mcast_init: setsockopt(SO_BINDTODEVICE)");
|
|
// close(sockfd);
|
|
// return -1;
|
|
}
|
|
|
|
char *mcastgroup = config_get_string("global", "mcastgroup", DEFAULT_GROUP);
|
|
int mcastport = config_get_int("global", "mcastport", DEFAULT_PORT);
|
|
|
|
dest_addr.sin_family = AF_INET;
|
|
inet_aton(mcastgroup, &dest_addr.sin_addr);
|
|
dest_addr.sin_port = htons(mcastport);
|
|
|
|
if (bind(sockfd, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
|
|
log_print(LOG_WARN, "mcast_init: bind()");
|
|
close(sockfd);
|
|
return -1;
|
|
}
|
|
|
|
// get interface address
|
|
if (ioctl(sockfd, SIOCGIFADDR, &ifr) != 0) {
|
|
log_print(LOG_WARN, "mcast_init: ioctl(SIOCGIFADDR)");
|
|
close(sockfd);
|
|
return -1;
|
|
}
|
|
|
|
// check address family
|
|
if (ifr.ifr_addr.sa_family != AF_INET) {
|
|
log_print(LOG_WARN, "mcast_init: unknown address family");
|
|
close(sockfd);
|
|
return -1;
|
|
}
|
|
|
|
char loop = 0;
|
|
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;
|
|
}
|
|
|
|
inet_aton(mcastgroup, &multiaddr.imr_multiaddr);
|
|
multiaddr.imr_interface.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
|
|
|
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
&multiaddr, sizeof(multiaddr)) == -1) {
|
|
log_print(LOG_WARN, "mcast_init: setsockopt(IP_ADD_MEMBERSHIP)");
|
|
close(sockfd);
|
|
return -1;
|
|
}
|
|
|
|
return sockfd;
|
|
}
|
|
|
|
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);
|
|
}
|