1/*
2 * Copyright 2010, Atis Elsts, the.kfx@gmail.com
3 * Distributed under the terms of the MIT license.
4 */
5
6
7#include <unistd.h>
8#include <memory.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#include <errno.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15
16const unsigned short TEST_PORT = 40000;
17
18
19int
20main(int argc, char *argv[])
21{
22	int socketFamily = AF_INET;
23
24	int i = 1;
25	if (argc > i) {
26		if (!strcmp(argv[i], "-4")) {
27			i++;
28			socketFamily = AF_INET;
29		} else if (!strcmp(argv[i], "-6")) {
30			i++;
31			socketFamily = AF_INET6;
32		}
33	}
34	in_addr multicastSource;
35	multicastSource.s_addr = 0;
36	if (argc > i) {
37		if (!strcmp(argv[i], "-s")) {
38			++i;
39			if (inet_aton(argv[i], &multicastSource) == 0) {
40				fprintf(stderr, "IPv4 source address expected");
41				return -1;
42			}
43			++i;
44		}
45	}
46
47	int fd = socket(socketFamily, SOCK_DGRAM, 0);
48	if (fd < 0) {
49		perror("socket");
50		return -1;
51	}
52
53	sockaddr_storage saddr;
54	memset(&saddr, 0, sizeof(saddr));
55	if (socketFamily == AF_INET) {
56		sockaddr_in *sa = (sockaddr_in *) &saddr;
57		sa->sin_family = AF_INET;
58		sa->sin_port = htons(TEST_PORT);
59		sa->sin_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
60	} else {
61		sockaddr_in6 *sa = (sockaddr_in6 *) &saddr;
62		sa->sin6_family = AF_INET6;
63		sa->sin6_port = htons(TEST_PORT);
64		// ff01::1 (all nodes multicast)
65		sa->sin6_addr.s6_addr[0] = 0xff;
66		sa->sin6_addr.s6_addr[1] = 0x01;
67		sa->sin6_addr.s6_addr[15] = 0x01;
68	}
69
70	if (multicastSource.s_addr) {
71		if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
72				&multicastSource, sizeof(multicastSource)) < 0) {
73			perror("setsockopt IP_MULTICAST_IF");
74			return -1;
75		}
76	}
77
78	const char *buffer = "hello world";
79	unsigned length = strlen(buffer);
80	int status = sendto(fd, buffer, length, 0, (sockaddr *) &saddr,
81		socketFamily == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));
82	if (status < length) {
83		if (status < 0)
84			perror("sendto");
85		else if (status == 0)
86			printf("no data sent!\n");
87		else
88			printf("not all data sent!\n");
89	} else
90		printf("send(): success\n");
91
92	close(fd);
93	return 0;
94}
95