Created
December 8, 2020 11:45
-
-
Save pamaury/3f363050c35a7f492f9967e4b20bc0ef to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <time.h> | |
#if !defined(_WIN32) | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#include <arpa/inet.h> | |
#include <net/if.h> | |
#endif | |
#if defined(_WIN32) | |
#define WINVER 0x0A00 | |
#define _WIN32_WINNT 0x0A00 | |
#include <winsock2.h> | |
#include <windows.h> | |
#include <netioapi.h> | |
#include <ws2tcpip.h> | |
#endif | |
#if defined(_WIN32) | |
void die(const char *msg) { | |
char *wsa_message = NULL; | |
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, | |
NULL, | |
WSAGetLastError(), | |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
(LPSTR)&wsa_message, | |
0, | |
NULL); | |
printf("%s : %s\n", msg, wsa_message); | |
LocalFree(wsa_message); | |
exit(1); | |
} | |
#else | |
void die(const char *msg) { | |
perror(msg); | |
exit(1); | |
} | |
#endif | |
int main(int argc, char **argv) { | |
#if defined (_WIN32) | |
WSADATA WSAData; | |
WSAStartup(MAKEWORD(2,2), &WSAData); | |
#endif | |
/* premier argument: nom de l'interface */ | |
if(argc == 1) { | |
printf("usage: %s intf\n", argv[0]); | |
printf("Interfaces:\n"); | |
for(int i = 0; i < 10; i++) { | |
char ifname[IF_NAMESIZE]; | |
if(if_indextoname(i, ifname)) | |
printf("- %s\n", ifname); | |
} | |
return 1; | |
} | |
const char *intfname = argv[1]; | |
/* socket IPv6 UDP */ | |
int s = socket(AF_INET6, SOCK_DGRAM, 0); | |
if(s < 0) die("impossible de créer la socket"); | |
/* seulement IPv6 */ | |
int value = 1; | |
int rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value)); | |
if(rc < 0) die("impossible de mettre l'option IPV6_V6ONLY"); | |
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); | |
if(rc < 0) die("impossible de mettre l'option SO_REUSEADDR"); | |
/* bind sur le port 4242 */ | |
struct sockaddr_in6 server; | |
memset(&server, 0, sizeof(server)); | |
server.sin6_family = AF_INET6; | |
server.sin6_port = htons(4242); | |
rc = bind(s, (struct sockaddr*)&server, sizeof(server)); | |
if(rc < 0) die("bind() a échoué"); | |
/* abonnement au groupe */ | |
unsigned char maddr[16]; | |
rc = inet_pton(AF_INET6, "ff02::4242:4242", maddr); | |
if(rc < 1) die("impossible de convertir l'adresse"); | |
int ifindex = if_nametoindex(intfname); | |
if(ifindex <= 0) { | |
printf("l'interface %s n'existe pas\n", intfname); | |
return 1; | |
} | |
struct ipv6_mreq mreq; | |
memset(&mreq, 0, sizeof(mreq)); | |
memcpy(&mreq.ipv6mr_multiaddr, maddr, 16); | |
mreq.ipv6mr_interface = ifindex; | |
rc = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); | |
if(rc < 0) die("impossible de s'abonner au groupe"); | |
/* on écoute les messages */ | |
while(1) { | |
char msg[1024]; | |
char from[256]; | |
struct sockaddr_in6 sin6; | |
socklen_t sin_size = sizeof(sin6); | |
ssize_t size = recvfrom(s, msg, sizeof(msg) - 1, 0, (struct sockaddr *)&sin6, &sin_size); | |
if(size == 0) | |
continue; | |
if(size < 0) | |
die("impossible de recevoir"); | |
from[0] = 0; | |
inet_ntop(AF_INET6, &sin6, from, sizeof(from)); | |
msg[size] = 0; // ajoute un zéro, on a soustrait 1 à la taille au dessus pour être sûr d'avoir la place | |
printf("message de %s: %s\n", from, msg); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment