summaryrefslogtreecommitdiff
path: root/mcastseed/src
diff options
context:
space:
mode:
Diffstat (limited to 'mcastseed/src')
-rw-r--r--mcastseed/src/Makefile.am4
-rw-r--r--mcastseed/src/mcastleech.c12
-rw-r--r--mcastseed/src/mcastseed.c14
-rw-r--r--mcastseed/src/msock.c372
-rw-r--r--mcastseed/src/msock.h74
-rw-r--r--mcastseed/src/sockets.c303
-rw-r--r--mcastseed/src/sockets.h27
7 files changed, 346 insertions, 460 deletions
diff --git a/mcastseed/src/Makefile.am b/mcastseed/src/Makefile.am
index 7e30a9f..7af38c9 100644
--- a/mcastseed/src/Makefile.am
+++ b/mcastseed/src/Makefile.am
@@ -10,7 +10,7 @@ AM_CFLAGS =\
bin_PROGRAMS = mcastseed mcastleech random_speed_dd
-mcastseed_SOURCES = mcastseed.c msock.c
-mcastleech_SOURCES = mcastleech.c msock.c dgrambuf.c
+mcastseed_SOURCES = mcastseed.c sockets.c
+mcastleech_SOURCES = mcastleech.c sockets.c dgrambuf.c
random_speed_dd_SOURCES = random_speed_dd.c
diff --git a/mcastseed/src/mcastleech.c b/mcastseed/src/mcastleech.c
index df069ac..263bac4 100644
--- a/mcastseed/src/mcastleech.c
+++ b/mcastseed/src/mcastleech.c
@@ -11,14 +11,14 @@
#include <unistd.h> /* close() */
#include <stdio.h> /* fprintf(), stderr */
#include <stdlib.h> /* EXIT_SUCCESS */
+#include <string.h> /* strncmp() */
#include <fcntl.h> /* fcntl() */
-#include "msock.h"
+#include "sockets.h"
#include "dgrambuf.h"
#define MTU 1500
#define MULTICAST_RECV_BUF (MTU-20-8)
#define MULTICAST_SO_RCVBUF_WANTED 425984
-/*XXX Make it dynamic, with the effective value of so_rcvbuf */
#define MAX_IOVEC (MULTICAST_SO_RCVBUF_WANTED / MULTICAST_RECV_BUF)
#define DGRAM_HEADER_SIZE 8
@@ -31,8 +31,8 @@ char *mcast_ip = NULL;
char *port = NULL;
/* Sockets as global, used everywhere, even in die() */
-SOCKET mcast_sock = (SOCKET) -1; /* Multicast socket for receiving data */
-SOCKET ucast_sock = (SOCKET) -1; /* Unicast socket for give feedback to server */
+int mcast_sock = -1; /* Multicast socket for receiving data */
+int ucast_sock = -1; /* Unicast socket for give feedback to server */
/* Buffer used for earch recvfrom() */
char recvbuf[MULTICAST_RECV_BUF];
@@ -100,7 +100,7 @@ int main(int argc, char* argv[]) {
if ( mcast_sock > 0 ) {
close(mcast_sock);
- mcast_sock = (SOCKET) -1;
+ mcast_sock = -1;
}
dgrambuf_free(&dgrambuf);
@@ -126,7 +126,7 @@ int wait_hello_and_connect_back() {
/* Setup mcast_sock */
if ( mcast_sock > 0 ) {
close(mcast_sock);
- mcast_sock = (SOCKET) -1;
+ mcast_sock = -1;
}
mcast_sock = mcast_recv_socket(mcast_ip, port, MULTICAST_SO_RCVBUF_WANTED);
if(mcast_sock < 0) {
diff --git a/mcastseed/src/mcastseed.c b/mcastseed/src/mcastseed.c
index 6440fc6..796e159 100644
--- a/mcastseed/src/mcastseed.c
+++ b/mcastseed/src/mcastseed.c
@@ -11,7 +11,9 @@
#include <unistd.h> /* close() */
#include <stdio.h> /* fprintf(), stderr */
#include <stdlib.h> /* atoi(), EXIT_SUCCESS */
-#include "msock.h"
+#include <string.h> /* strlen() */
+#include <sys/select.h> /* select(), FD_ZERO(), FD_SET() */
+#include "sockets.h"
#define READ_BUF_LEN 256
#define MAX_PENDING_CONNECTIONS 256
@@ -28,13 +30,13 @@ char *port = NULL;
int mcast_ttl = 0;
/* Sockets as global, used everywhere, even in die() */
-SOCKET mcast_sock = (SOCKET) -1; /* Multicast socket for sending data */
-SOCKET ucast_sock = (SOCKET) -1; /* Unicast socket for havee feedback from clients */
+int mcast_sock = -1; /* Multicast socket for sending data */
+int ucast_sock = -1; /* Unicast socket for havee feedback from clients */
/* Socket related data */
struct addrinfo *mcast_addr = NULL;
struct client {
- SOCKET sock;
+ int sock;
struct sockaddr addr;
int state;
} clients[MAX_CLIENTS];
@@ -197,7 +199,7 @@ int start_job() {
ssize_t nread, nwrite;
int all_ready, all_non_dead_ready;
int i, res;
- SOCKET client_sock;
+ int client_sock;
const char *payload = "start";
int paylen = strlen(payload);
@@ -316,7 +318,7 @@ int wait_all_finalize_job() {
ssize_t nread, nwrite;
int all_non_dead_done;
int i, res;
- SOCKET client_sock;
+ int client_sock;
char buf[] = "end:XXXX";
int paylen = strlen(buf);
diff --git a/mcastseed/src/msock.c b/mcastseed/src/msock.c
deleted file mode 100644
index 191611d..0000000
--- a/mcastseed/src/msock.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- msock.c - multicast socket creation routines
-
- (C) 2016 Christian Beier <dontmind@sdf.org>
-
-*/
-
-#ifndef __MINGW32__
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "msock.h"
-
-SOCKET mcast_send_socket(char* multicastIP, char* multicastPort, int multicastTTL, struct addrinfo **multicastAddr) {
-
- SOCKET sock;
- struct addrinfo hints = { 0 }; /* Hints for name lookup */
- int status;
-
-
-#ifdef WIN32
- WSADATA trash;
- if(WSAStartup(MAKEWORD(2,0),&trash)!=0)
- DieWithError("Couldn't init Windows Sockets\n");
-#endif
-
-
- /*
- Resolve destination address for multicast datagrams
- */
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_NUMERICHOST;
- if ((status = getaddrinfo(multicastIP, multicastPort, &hints, multicastAddr)) != 0 )
- {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
- return -1;
- }
-
-
-
- /*
- Create socket for sending multicast datagrams
- */
- if ( (sock = socket((*multicastAddr)->ai_family, (*multicastAddr)->ai_socktype, 0)) < 0 ) {
- perror("socket() failed");
- freeaddrinfo(*multicastAddr);
- return -1;
- }
-
- /*
- Set TTL of multicast packet
- */
- if ( setsockopt(sock,
- (*multicastAddr)->ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP,
- (*multicastAddr)->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL,
- (char*) &multicastTTL, sizeof(multicastTTL)) != 0 ) {
- perror("setsockopt() failed");
- freeaddrinfo(*multicastAddr);
- return -1;
- }
-
-
- /*
- set the sending interface
- */
- if((*multicastAddr)->ai_family == PF_INET) {
- in_addr_t iface = INADDR_ANY; /* well, yeah, any */
- if(setsockopt (sock,
- IPPROTO_IP,
- IP_MULTICAST_IF,
- (char*)&iface, sizeof(iface)) != 0) {
- perror("interface setsockopt() sending interface");
- freeaddrinfo(*multicastAddr);
- return -1;
- }
-
- }
- if((*multicastAddr)->ai_family == PF_INET6) {
- unsigned int ifindex = 0; /* 0 means 'default interface'*/
- if(setsockopt (sock,
- IPPROTO_IPV6,
- IPV6_MULTICAST_IF,
- (char*)&ifindex, sizeof(ifindex)) != 0) {
- perror("interface setsockopt() sending interface");
- freeaddrinfo(*multicastAddr);
- return -1;
- }
-
- }
-
-
- return sock;
-
-}
-
-
-
-SOCKET mcast_recv_socket(char* multicastIP, char* multicastPort, int multicastRecvBufSize) {
-
- SOCKET sock;
- struct addrinfo hints = { 0 }; /* Hints for name lookup */
- struct addrinfo* localAddr = 0; /* Local address to bind to */
- struct addrinfo* multicastAddr = 0; /* Multicast Address */
- int yes=1;
- int status, optval;
- socklen_t optval_len;
- int dfltrcvbuf;
-
-#ifdef WIN32
- WSADATA trash;
- if(WSAStartup(MAKEWORD(2,0),&trash)!=0)
- DieWithError("Couldn't init Windows Sockets\n");
-#endif
-
-
- /* Resolve the multicast group address */
- hints.ai_family = PF_UNSPEC;
- hints.ai_flags = AI_NUMERICHOST;
- if ((status = getaddrinfo(multicastIP, NULL, &hints, &multicastAddr)) != 0) {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
- goto error;
- }
-
-
- /*
- Get a local address with the same family (IPv4 or IPv6) as our multicast group
- This is for receiving on a certain port.
- */
- hints.ai_family = multicastAddr->ai_family;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_PASSIVE; /* Return an address we can bind to */
- if ( getaddrinfo(NULL, multicastPort, &hints, &localAddr) != 0 ) {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
- goto error;
- }
-
-
- /* Create socket for receiving datagrams */
- if ( (sock = socket(localAddr->ai_family, localAddr->ai_socktype, 0)) < 0 ) {
- perror("socket() failed");
- goto error;
- }
-
-
-
- /*
- * Enable SO_REUSEADDR to allow multiple instances of this
- * application to receive copies of the multicast datagrams.
- */
- if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(int)) == -1) {
- perror("setsockopt");
- goto error;
- }
-
- /* Bind the local address to the multicast port */
- if ( bind(sock, localAddr->ai_addr, localAddr->ai_addrlen) != 0 ) {
- perror("bind() failed");
- goto error;
- }
-
- /* get/set socket receive buffer */
- optval=0;
- optval_len = sizeof(optval);
- if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) !=0) {
- perror("getsockopt");
- goto error;
- }
- dfltrcvbuf = optval;
- optval = multicastRecvBufSize;
- if(setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&optval,sizeof(optval)) != 0) {
- perror("setsockopt");
- goto error;
- }
- if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) != 0) {
- perror("getsockopt");
- goto error;
- }
- fprintf(stderr, "tried to set socket receive buffer from %d to %d, got %d\n",
- dfltrcvbuf, multicastRecvBufSize, optval);
-
-
-
-
- /* Join the multicast group. We do this seperately depending on whether we
- * are using IPv4 or IPv6.
- */
- if ( multicastAddr->ai_family == PF_INET &&
- multicastAddr->ai_addrlen == sizeof(struct sockaddr_in) ) /* IPv4 */
- {
- struct ip_mreq multicastRequest; /* Multicast address join structure */
-
- /* Specify the multicast group */
- memcpy(&multicastRequest.imr_multiaddr,
- &((struct sockaddr_in*)(multicastAddr->ai_addr))->sin_addr,
- sizeof(multicastRequest.imr_multiaddr));
-
- /* Accept multicast from any interface */
- multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
-
- /* Join the multicast address */
- if ( setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) {
- perror("setsockopt() failed");
- goto error;
- }
- }
- else if ( multicastAddr->ai_family == PF_INET6 &&
- multicastAddr->ai_addrlen == sizeof(struct sockaddr_in6) ) /* IPv6 */
- {
- struct ipv6_mreq multicastRequest; /* Multicast address join structure */
-
- /* Specify the multicast group */
- memcpy(&multicastRequest.ipv6mr_multiaddr,
- &((struct sockaddr_in6*)(multicastAddr->ai_addr))->sin6_addr,
- sizeof(multicastRequest.ipv6mr_multiaddr));
-
- /* Accept multicast from any interface */
- multicastRequest.ipv6mr_interface = 0;
-
- /* Join the multicast address */
- if ( setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) {
- perror("setsockopt() failed");
- goto error;
- }
- }
- else {
- perror("Neither IPv4 or IPv6");
- goto error;
- }
-
-
-
- if(localAddr)
- freeaddrinfo(localAddr);
- if(multicastAddr)
- freeaddrinfo(multicastAddr);
-
- return sock;
-
- error:
- if(localAddr)
- freeaddrinfo(localAddr);
- if(multicastAddr)
- freeaddrinfo(multicastAddr);
-
- return -1;
-}
-
-SOCKET ucast_client_socket(char* serverIP, char* serverPort) {
-
- SOCKET sock;
- struct addrinfo *serverAddr;
- struct addrinfo hints = { 0 }; /* Hints for name lookup */
- int status;
-
-
-#ifdef WIN32
- WSADATA trash;
- if(WSAStartup(MAKEWORD(2,0),&trash)!=0)
- DieWithError("Couldn't init Windows Sockets\n");
-#endif
-
-
- /*
- Resolve destination address
- */
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_NUMERICHOST;
- if ((status = getaddrinfo(serverIP, serverPort, &hints, &serverAddr)) != 0 )
- {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
- return -1;
- }
-
- /*
- Create socket
- */
- if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, 0)) < 0 ) {
- perror("socket() failed");
- freeaddrinfo(serverAddr);
- return -1;
- }
-
- /*
- Connect it to the remote server
- */
- if ( connect(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) {
- perror("connect() failed");
- close(sock);
- freeaddrinfo(serverAddr);
- return -1;
- }
-
- freeaddrinfo(serverAddr);
- return sock;
-}
-
-SOCKET ucast_server_socket(char* serverPort, int maxPendingConnections) {
-
- SOCKET sock;
- struct addrinfo *serverAddr;
- struct addrinfo hints = { 0 }; /* Hints for name lookup */
- int status;
-
-
-#ifdef WIN32
- WSADATA trash;
- if(WSAStartup(MAKEWORD(2,0),&trash)!=0)
- DieWithError("Couldn't init Windows Sockets\n");
-#endif
-
-
- /*
- Prepare an addrinfo struct for a local socket
- */
- hints.ai_family = PF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
- if ((status = getaddrinfo(NULL, serverPort, &hints, &serverAddr)) != 0 )
- {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
- return -1;
- }
- /*
- Create socket
- */
- if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol)) < 0 ) {
- perror("socket() failed");
- freeaddrinfo(serverAddr);
- return -1;
- }
-
- /*
- Accepts also IPv4 traffic if the socket is INET6
- */
- if(serverAddr->ai_family == PF_INET6) {
- unsigned int no = 0;
- if(setsockopt (sock,
- IPPROTO_IPV6,
- IPV6_V6ONLY,
- (char*)&no, sizeof(no)) != 0) {
- perror("setsockopt() !IPV6_V6ONLY failed");
- freeaddrinfo(serverAddr);
- return -1;
- }
- }
-
- /*
- Bind socket to local address/port
- */
- if ( bind(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) {
- perror("bind() failed");
- close(sock);
- freeaddrinfo(serverAddr);
- return -1;
- }
-
- freeaddrinfo(serverAddr);
- /*
- Start listening incoming connections
- */
- if ( listen(sock, maxPendingConnections) < 0 ) {
- perror("listen() failed");
- close(sock);
- }
-
- return sock;
-}
diff --git a/mcastseed/src/msock.h b/mcastseed/src/msock.h
deleted file mode 100644
index 07e1fad..0000000
--- a/mcastseed/src/msock.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- msock.h - multicast socket creation routines
-
- (C) 2016 Christian Beier <dontmind@sdf.org>
-
-*/
-
-
-#ifndef MSOCK_H
-#define MSOCK_H
-
-/* this is for windows compat */
-#define SOCKET int
-
-#ifdef __MINGW32__
-#undef SOCKET
-#undef socklen_t
-#define WINVER 0x0501
-#include <ws2tcpip.h>
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define close closesocket
-#define socklen_t int
-typedef unsigned int in_addr_t;
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
-
-/* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */
-#ifndef IPV6_ADD_MEMBERSHIP
-#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
-#endif
-
-
-
-/**
- Creates a socket suitable for sending multicast datagrams via sendto().
-
- On success, a socket is returned and multicastAddr set with the right info for sendto() calls.
- On error, -1 is returned.
-*/
-SOCKET mcast_send_socket(char* multicastIP, char* multicastPort, int multicastTTL, struct addrinfo **multicastAddr);
-
-/**
- Creates a socket suitable for receiving multicast datagrams via recvfrom(). Also sets socket recv buffer.
-
- On success, returns socket.
- On fail, returns -1.
- */
-SOCKET mcast_recv_socket(char* multicastIP, char* multicastPort, int multicastRecvBufSize);
-
-/**
- Creates a TCP socket that connects to serverIP:serverPort.
- Meant to give feedback to a mcast sender.
-
- On success, returns socket.
- On error, -1 is returned.
- */
-SOCKET ucast_client_socket(char* serverIP, char* serverPort);
-
-/**
- Creates a TCP socket that binds locally serverPort.
- Meant to receive feedback to a mcast sender.
-
- On success, returns socket.
- On error, -1 is returned.
- */
-SOCKET ucast_server_socket(char* serverPort, int maxPendingConnections);
-
-#endif
diff --git a/mcastseed/src/sockets.c b/mcastseed/src/sockets.c
new file mode 100644
index 0000000..85abb1f
--- /dev/null
+++ b/mcastseed/src/sockets.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2016 by Ludovic Pouzenc <ludovic@pouzenc.fr>
+ *
+ * Greatly inspired from msock.h written by Christian Beier <dontmind@sdf.org>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "sockets.h"
+
+int mcast_recv_socket(char *mcast_ip, char *port, int wanted_so_rcvbuf) {
+
+ int sock;
+ struct addrinfo hints = { 0 }; /* Hints for name lookup */
+ struct addrinfo *ai_local = NULL; /* Local address to bind to */
+ struct addrinfo *mcast_ai = NULL; /* Multicast Address */
+ int yes=1;
+ int status, optval;
+ socklen_t optval_len;
+ int dfltrcvbuf;
+
+ /* Resolve the multicast group address */
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((status = getaddrinfo(mcast_ip, NULL, &hints, &mcast_ai)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
+ goto error;
+ }
+
+ /*
+ * Get a local address with the same family (IPv4 or IPv6) as our multicast group
+ * This is for receiving on a certain port.
+ */
+ hints.ai_family = mcast_ai->ai_family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE; /* Return an address we can bind to */
+ if ( getaddrinfo(NULL, port, &hints, &ai_local) != 0 ) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
+ goto error;
+ }
+
+ /* Create socket for receiving datagrams */
+ if ( (sock = socket(ai_local->ai_family, ai_local->ai_socktype, 0)) < 0 ) {
+ perror("socket() failed");
+ goto error;
+ }
+
+ /*
+ * Enable SO_REUSEADDR to allow multiple instances of this
+ * application to receive copies of the multicast datagrams.
+ */
+ if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(int)) == -1) {
+ perror("setsockopt");
+ goto error;
+ }
+
+ /* Bind the local address to the multicast port */
+ if ( bind(sock, ai_local->ai_addr, ai_local->ai_addrlen) != 0 ) {
+ perror("bind() failed");
+ goto error;
+ }
+
+ /* get/set socket receive buffer */
+ optval=0;
+ optval_len = sizeof(optval);
+ if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) !=0) {
+ perror("getsockopt");
+ goto error;
+ }
+ dfltrcvbuf = optval;
+ optval = wanted_so_rcvbuf;
+ if(setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&optval,sizeof(optval)) != 0) {
+ perror("setsockopt");
+ goto error;
+ }
+ if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) != 0) {
+ perror("getsockopt");
+ goto error;
+ }
+ fprintf(stderr, "tried to set socket receive buffer from %d to %d, got %d\n",
+ dfltrcvbuf, wanted_so_rcvbuf, optval);
+
+
+ /* Join the multicast group. We do this seperately depending on whether we
+ * are using IPv4 or IPv6.
+ */
+ if ( mcast_ai->ai_family == PF_INET &&
+ mcast_ai->ai_addrlen == sizeof(struct sockaddr_in) ) /* IPv4 */
+ {
+ struct ip_mreq multicastRequest; /* Multicast address join structure */
+
+ /* Specify the multicast group */
+ memcpy(&multicastRequest.imr_multiaddr,
+ &((struct sockaddr_in*)(mcast_ai->ai_addr))->sin_addr,
+ sizeof(multicastRequest.imr_multiaddr));
+
+ /* Accept multicast from any interface */
+ multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
+
+ /* Join the multicast address */
+ if ( setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) {
+ perror("setsockopt() failed");
+ goto error;
+ }
+ }
+ else if ( mcast_ai->ai_family == PF_INET6 &&
+ mcast_ai->ai_addrlen == sizeof(struct sockaddr_in6) ) /* IPv6 */
+ {
+ struct ipv6_mreq multicastRequest; /* Multicast address join structure */
+
+ /* Specify the multicast group */
+ memcpy(&multicastRequest.ipv6mr_multiaddr,
+ &((struct sockaddr_in6*)(mcast_ai->ai_addr))->sin6_addr,
+ sizeof(multicastRequest.ipv6mr_multiaddr));
+
+ /* Accept multicast from any interface */
+ multicastRequest.ipv6mr_interface = 0;
+
+ /* Join the multicast address */
+ if ( setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) {
+ perror("setsockopt() failed");
+ goto error;
+ }
+ }
+ else {
+ perror("Neither IPv4 or IPv6");
+ goto error;
+ }
+
+
+ if(ai_local)
+ freeaddrinfo(ai_local);
+ if(mcast_ai)
+ freeaddrinfo(mcast_ai);
+
+ return sock;
+
+error:
+ if(ai_local)
+ freeaddrinfo(ai_local);
+ if(mcast_ai)
+ freeaddrinfo(mcast_ai);
+
+ return -1;
+}
+
+
+int mcast_send_socket(char* mcast_ip, char* port, int multicastTTL, struct addrinfo **mcast_ai) {
+
+ int sock;
+ struct addrinfo hints = { 0 }; /* Hints for name lookup */
+ int status;
+
+
+ /* Resolve destination address for multicast datagrams */
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((status = getaddrinfo(mcast_ip, port, &hints, mcast_ai)) != 0 )
+ {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
+ return -1;
+ }
+
+ /* Create socket for sending multicast datagrams */
+ if ( (sock = socket((*mcast_ai)->ai_family, (*mcast_ai)->ai_socktype, 0)) < 0 ) {
+ perror("socket() failed");
+ freeaddrinfo(*mcast_ai);
+ return -1;
+ }
+
+ /* Set TTL of multicast packet */
+ if ( setsockopt(sock,
+ (*mcast_ai)->ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP,
+ (*mcast_ai)->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL,
+ (char*) &multicastTTL, sizeof(multicastTTL)) != 0 ) {
+ perror("setsockopt() failed");
+ freeaddrinfo(*mcast_ai);
+ return -1;
+ }
+
+ /* set the sending interface */
+ if((*mcast_ai)->ai_family == PF_INET) {
+ in_addr_t iface = INADDR_ANY; /* well, yeah, any */
+ if(setsockopt (sock,
+ IPPROTO_IP,
+ IP_MULTICAST_IF,
+ (char*)&iface, sizeof(iface)) != 0) {
+ perror("interface setsockopt() sending interface");
+ freeaddrinfo(*mcast_ai);
+ return -1;
+ }
+
+ }
+ if((*mcast_ai)->ai_family == PF_INET6) {
+ unsigned int ifindex = 0; /* 0 means 'default interface'*/
+ if(setsockopt (sock,
+ IPPROTO_IPV6,
+ IPV6_MULTICAST_IF,
+ (char*)&ifindex, sizeof(ifindex)) != 0) {
+ perror("interface setsockopt() sending interface");
+ freeaddrinfo(*mcast_ai);
+ return -1;
+ }
+
+ }
+
+ return sock;
+}
+
+
+int ucast_server_socket(char* port, int max_pending_conn) {
+
+ int sock;
+ struct addrinfo *serverAddr;
+ struct addrinfo hints = { 0 }; /* Hints for name lookup */
+ int status;
+
+
+ /* Prepare an addrinfo struct for a local socket */
+ hints.ai_family = PF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ if ((status = getaddrinfo(NULL, port, &hints, &serverAddr)) != 0 )
+ {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
+ return -1;
+ }
+ /* Create socket */
+ if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol)) < 0 ) {
+ perror("socket() failed");
+ freeaddrinfo(serverAddr);
+ return -1;
+ }
+
+ /* Accepts also IPv4 traffic if the socket is INET6 */
+ if(serverAddr->ai_family == PF_INET6) {
+ unsigned int no = 0;
+ if(setsockopt (sock,
+ IPPROTO_IPV6,
+ IPV6_V6ONLY,
+ (char*)&no, sizeof(no)) != 0) {
+ perror("setsockopt() !IPV6_V6ONLY failed");
+ freeaddrinfo(serverAddr);
+ return -1;
+ }
+ }
+
+ /* Bind socket to local address/port */
+ if ( bind(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) {
+ perror("bind() failed");
+ close(sock);
+ freeaddrinfo(serverAddr);
+ return -1;
+ }
+
+ freeaddrinfo(serverAddr);
+
+ /* Start listening incoming connections */
+ if ( listen(sock, max_pending_conn) < 0 ) {
+ perror("listen() failed");
+ close(sock);
+ }
+
+ return sock;
+}
+
+int ucast_client_socket(char* server_ip, char* port) {
+
+ int sock;
+ struct addrinfo *serverAddr;
+ struct addrinfo hints = { 0 }; /* Hints for name lookup */
+ int status;
+
+ /* Resolve destination address */
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((status = getaddrinfo(server_ip, port, &hints, &serverAddr)) != 0 )
+ {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
+ return -1;
+ }
+
+ /* Create socket */
+ if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, 0)) < 0 ) {
+ perror("socket() failed");
+ freeaddrinfo(serverAddr);
+ return -1;
+ }
+
+ /* Connect it to the remote server */
+ if ( connect(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) {
+ perror("connect() failed");
+ close(sock);
+ freeaddrinfo(serverAddr);
+ return -1;
+ }
+
+ freeaddrinfo(serverAddr);
+ return sock;
+}
+
diff --git a/mcastseed/src/sockets.h b/mcastseed/src/sockets.h
new file mode 100644
index 0000000..86f7c5b
--- /dev/null
+++ b/mcastseed/src/sockets.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 by Ludovic Pouzenc <ludovic@pouzenc.fr>
+ *
+ * Greatly inspired from msock.h written by Christian Beier <dontmind@sdf.org>
+ */
+
+#ifndef SOCKETS_H
+#define SOCKETS_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+/*
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+*/
+int mcast_recv_socket(char *mcast_ip, char *port, int wanted_so_rcvbuf);
+int mcast_send_socket(char *mcast_ip, char *port, int mcast_ttl, struct addrinfo **mcast_ai);
+
+int ucast_server_socket(char *port, int max_pending_conn);
+int ucast_client_socket(char *server_ip, char *port);
+
+#endif /*SOCKETS_H*/