/* * This is free software released under the GPL license. * See the GNU GPL for details. * * (c) Juan-Mariano de Goyeneche. 1998, 1999. * */ #include <stdio.h> /* printf(), snprintf() */ #include <stdlib.h> /* strtol(), exit() */ #include <sys/types.h> #include <sys/socket.h> /* socket(), setsockopt(), bind(), recvfrom(), sendto() */ #include <errno.h> /* perror() */ #include <netinet/in.h> /* IPPROTO_IP, sockaddr_in, htons(), htonl() */ #include <arpa/inet.h> /* inet_addr() */ #include <unistd.h> /* fork(), sleep() */ #include <sys/utsname.h> /* uname() */ #include <string.h> /* memset() */ #define MAXLEN 1024 #define DELAY 2 #define TTL 1 int main(int argc, char* argv[]) { u_char no = 0; u_int yes = 1; /* Used with SO_REUSEADDR. In Linux both u_int */ /* and u_char are valid. */ int send_s, recv_s; /* Sockets for sending and receiving. */ u_char ttl; struct sockaddr_in mcast_group; struct ip_mreq mreq; struct utsname name; if ((argc<3) || (argc>4)) { fprintf(stderr, "Usage: %s mcast_group port [ttl]\n", argv[0]); exit(1); } memset(&mcast_group, 0, sizeof(mcast_group)); mcast_group.sin_family = AF_INET; mcast_group.sin_port = htons((unsigned short int)strtol(argv[2], NULL, 0)); mcast_group.sin_addr.s_addr = inet_addr(argv[1]); if ( (send_s=socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror ("send socket"); exit(1); } /* If ttl supplied, set it */ if (argc == 4) { ttl = strtol(argv[3], NULL, 0); } else { ttl = TTL; } if (setsockopt(send_s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { perror ("ttl setsockopt"); exit(1); } /* Disable Loop-back */ if (setsockopt(send_s, IPPROTO_IP, IP_MULTICAST_LOOP, &no, sizeof(no)) < 0) { perror ("loop setsockopt"); exit(1); } if ( (recv_s=socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror ("recv socket"); exit(1); } if (setsockopt(recv_s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { perror("reuseaddr setsockopt"); exit(1); } if (bind(recv_s, (struct sockaddr*)&mcast_group, sizeof(mcast_group)) < 0) { perror ("bind"); exit(1); } /* Tell the kernel we want to join that multicast group. */ mreq.imr_multiaddr = mcast_group.sin_addr; mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(recv_s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { perror ("add_membership setsockopt"); exit(1); } if (uname(&name) < 0) { perror ("uname"); exit(1); } switch (fork()) { case -1: /* Error fork()ing */ perror("fork"); exit(1); case 0: { /* Child -> receive. */ int n; int len; struct sockaddr_in from; char message [MAXLEN+1]; for (;;) { len=sizeof(from); if ( (n=recvfrom(recv_s, message, MAXLEN, 0, (struct sockaddr*)&from, &len)) < 0) { perror ("recv"); exit(1); } message[n] = '\0'; /* null-terminate string */ printf("%s: Received message from %s, size=%d !!\n", name.nodename, inet_ntoa(from.sin_addr), n); printf("\t%s \n", message); } /* Not reached. */ } default: { /* Parent -> send. */ char message [MAXLEN]; snprintf (message, sizeof(message), "Hi, I'm %s. " "Merry Christmas!\t(TTL==%d)\n", name.nodename, ttl); for (;;) { if (sendto(send_s, message, strlen(message), 0, (struct sockaddr*)&mcast_group, sizeof(mcast_group)) < strlen (message)) { perror("sendto"); exit(1); } sleep(DELAY); } /* Not reached. */ } } /* Not really reached. */ }