IPv6协议保留的组播地址中ff02::1
是local link multicast addressff05::1
是global link multicast address
我在写multicast socket的时候指定了目的地址为ff02::1
,发出去的报文自动使用了源地址为fe80::ade2:616b:a927:5ae5
。
我现在需要将源地址指定成fd53:7cb8:383:f::4:10
,目的地址指定为ff02::1
,该如何修改socket呢?
eth0.3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::ade2:616b:a927:5ae5 prefixlen 64 scopeid 0x20<link>
inet6 fd53:7cb8:383:f::4:10 prefixlen 64 scopeid 0x0<global>
ether dc:a6:32:24:f4:3b txqueuelen 1000 (Ethernet)
RX packets 2 bytes 84 (84.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6 bytes 936 (936.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for usleep() */
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
static void DieWithError(char* errorMessage)
{
fprintf(stderr, "%s\n", errorMessage);
exit(EXIT_FAILURE);
}
int mcast_send_socket(char* multicastIP, char* multicastPort, int multicastTTL, struct addrinfo **multicastAddr) {
int sock;
struct addrinfo hints = { 0 }; /* Hints for name lookup */
/*
Resolve destination address for multicast datagrams
*/
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST;
int status;
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) {
const char *pcIfname = "eth0.3";
unsigned int ifindex = if_nametoindex(pcIfname); /* 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;
}
int main(int argc, char *argv[])
{
int sock;
struct addrinfo *multicastAddr;
char* multicastIP; /* Arg: IP Multicast address */
char* multicastPort; /* Arg: Server port */
int sendStringLen; /* Length of string to multicast */
int multicastTTL; /* Arg: TTL of multicast packets */
int defer_ms; /* miliseconds to defer in between sending */
int i;
char sendString[8] = {0x02, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
multicastIP = "ff02::1"; /* First arg: multicast IP address */
multicastPort = "13400"; /* Second arg: multicast port */
sendStringLen = 8;
defer_ms = 1000;
multicastTTL = 1;
sock = mcast_send_socket(multicastIP, multicastPort, multicastTTL, &multicastAddr);
if (sock == -1 ) {
DieWithError("mcast_send_socket() failed");
}
int nr = 0;
for (;;) /* Run forever */
{
if ( sendto(sock, sendString, sendStringLen, 0, multicastAddr->ai_addr, multicastAddr->ai_addrlen) != sendStringLen ) {
DieWithError("sendto() sent a different number of bytes than expected");
}
fprintf(stderr, "packet %d sent\n", nr);
nr++;
usleep(defer_ms * 1000);
}
return 0;
}