int OpenSendSock(u_int32_t addr, u_short port, unsigned char* ttl) { int fd; struct sockaddr_in sin; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); exit(1); } nonblock(fd); memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = port; sin.sin_addr.s_addr = addr; if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("connect"); exit(1); } if (IN_CLASSD(ntohl(addr))) { #ifdef IP_ADD_MEMBERSHIP if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { perror("IP_MULTICAST_TTL"); exit(1); } #else fprintf(stderr, "\ not compiled with support for IP multicast\n\ you must specify a unicast destination\n"); exit(1); #endif } return (fd); } int OpenRcvSock(u_int32_t addr, u_short port, const struct sockaddr_in* local) { int fd; int on = 1; struct sockaddr_in sin; struct ip_mreq mr; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); exit(1); } nonblock(fd); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { perror("SO_REUSEADDR"); } #ifdef SO_REUSEPORT on = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on)) < 0) { perror("SO_REUSEPORT"); exit(1); } #endif memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = port; #ifdef IP_ADD_MEMBERSHIP if (IN_CLASSD(ntohl(addr))) { /* * Try to bind the multicast address as the socket * dest address. On many systems this won't work * so fall back to a destination of INADDR_ANY if * the first bind fails. */ sin.sin_addr.s_addr = addr; if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { sin.sin_addr.s_addr = INADDR_ANY; if (bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { perror("bind"); exit(1); } } /* * XXX This is bogus multicast setup that really * shouldn't have to be done (group membership should be * implicit in the IP class D address, route should contain * ttl & no loopback flag, etc.). Steve Deering has promised * to fix this for the 4.4bsd release. We're all waiting * with bated breath. */ mr.imr_multiaddr.s_addr = addr; mr.imr_interface.s_addr = INADDR_ANY; if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) { perror("IP_ADD_MEMBERSHIP"); exit(1); } } else #endif { sin.sin_addr.s_addr = local->sin_addr.s_addr; if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); exit(1); } sin.sin_port = 0; sin.sin_addr.s_addr = addr; connect(fd, (struct sockaddr *)&sin, sizeof(sin)); return (fd); } }