int main() { int n=-1; mh.msg_name=&sa4; mh.msg_namelen=sizeof(sa4); mh.msg_iov=&iv; mh.msg_iovlen=1; iv.iov_base=buf; iv.iov_len=PKGSIZE; mh.msg_control=abuf; mh.msg_controllen=sizeof(abuf); if (gethostname(myhostname,64)==-1) { perror("gethostname"); return 1; } namelen=strlen(myhostname); init_sockets(&s6,&s4,5353,"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfb","\xe0\x00\x00\xfb"); init_sockets(&ls6,&ls4,5355,"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x03","\xe0\x00\x00\xfc"); pfd[0].events=pfd[1].events=pfd[2].events=pfd[3].events=POLLIN; if (s6!=-1) pfd[++n].fd=s6; if (s4!=-1) pfd[++n].fd=s4; if (ls6!=-1) pfd[++n].fd=ls6; if (ls4!=-1) pfd[++n].fd=ls4; if (!++n) return 2; for (;;) { int i; switch (poll(pfd,n,5*1000)) { case -1: if (errno==EINTR) continue; perror("poll"); return 1; case 0: continue; } for (i=0; i<n; ++i) if (pfd[i].revents & POLLIN) { if (pfd[i].fd==s6 || pfd[i].fd==ls6) recv6(pfd[i].fd); else recv4(pfd[i].fd); } } return 0; }
int main() { mh.msg_name=&sa4; mh.msg_namelen=sizeof(sa4); mh.msg_iov=&iv; mh.msg_iovlen=1; iv.iov_base=buf; iv.iov_len=PKGSIZE; mh.msg_control=abuf; mh.msg_controllen=sizeof(abuf); if (gethostname(myhostname,64)==-1) { perror("gethostname"); return 1; } namelen=strlen(myhostname); s6=socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP); s4=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); if (s4==-1 && s6==-1) { perror("socket"); return 2; } if (s6!=-1) { memset(&sa6,0,sizeof(sa6)); sa6.sin6_family=PF_INET6; sa6.sin6_port=htons(5353); if (bind(s6,(struct sockaddr*)&sa6,sizeof(struct sockaddr_in6))==-1) { perror("bind IPv6"); close(s6); s6=-1; } } if (s4!=-1) { memset(&sa4,0,sizeof(sa4)); sa4.sin_family=PF_INET; sa4.sin_port=htons(5353); if (bind(s4,(struct sockaddr*)&sa4,sizeof(struct sockaddr_in))==-1) { if (errno!=EADDRINUSE || s6==-1) perror("bind IPv4"); close(s4); s4=-1; } } if (s4==-1 && s6==-1) return 2; { int val=255; int one=1; if (s6!=-1) { struct ipv6_mreq opt; setsockopt(s6,IPPROTO_IPV6,IPV6_UNICAST_HOPS,&val,sizeof(val)); setsockopt(s6,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,&one,sizeof(one)); memcpy(&opt.ipv6mr_multiaddr,"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfb",16); opt.ipv6mr_interface=0; setsockopt(s6,IPPROTO_IPV6,IPV6_ADD_MEMBERSHIP,&opt,sizeof opt); // setsockopt(s6,IPPROTO_IPV6,IPV6_PKTINFO,&one,sizeof one); } { struct ip_mreq opt; int s=(s4==-1?s6:s4); setsockopt(s,SOL_IP,IP_TTL,&val,sizeof(val)); memcpy(&opt.imr_multiaddr.s_addr,"\xe0\x00\x00\xfb",4); opt.imr_interface.s_addr=0; setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&opt,sizeof(opt)); setsockopt(s,SOL_IP,IP_PKTINFO,&one,sizeof one); } } for (;;) { /* 1500 is the MTU for UDP, I figure we won't longer packets */ /* add 1 to be able to add \0 */ int len; int interface=0; if (s4!=-1 && s6!=-1) { if (s4!=-1) { recv4(); #if 0 if ((len=recvmsg(s4,&mh,0))==-1) { perror("recvmsg"); return 3; } peer=(struct sockaddr*)&sa4; sl=sizeof(sa4); for (x=CMSG_FIRSTHDR(&mh); x; x=CMSG_NXTHDR(&mh,x)) if (x->cmsg_level==SOL_IP && x->cmsg_type==IP_PKTINFO) { struct in_pktinfo* y=(struct in_pktinfo*)(CMSG_DATA(x)); interface=y->ipi_ifindex; break; } handle(s4,buf,len,interface); #endif } else { recv6(); #if 0 sl=sizeof(sa6); if ((len=recvfrom(s6,buf,PKGSIZE,0,(struct sockaddr*)&sa6,&sl))==-1) { perror("recvfrom"); return 3; } peer=(struct sockaddr*)&sa6; handle(s6,buf,len,sa6.sin6_scope_id); #endif } } else { pfd[0].fd=s4; pfd[0].events=POLLIN; pfd[1].fd=s6; pfd[1].events=POLLIN; switch (poll(pfd,2,5*1000)) { case -1: if (errno==EINTR) continue; perror("poll"); return 1; case 0: continue; } if (pfd[0].revents & POLLIN) { recv4(); #if 0 if ((len=recvmsg(s4,&mh,0))==-1) { perror("recvmsg"); return 3; } peer=(struct sockaddr*)&sa4; sl=sizeof(sa4); for (x=CMSG_FIRSTHDR(&mh); x; x=CMSG_NXTHDR(&mh,x)) if (x->cmsg_level==SOL_IP && x->cmsg_type==IP_PKTINFO) { struct in_pktinfo* y=(struct in_pktinfo*)(CMSG_DATA(x)); interface=y->ipi_ifindex; break; } handle(s4,buf,len,interface); #endif } if (pfd[1].revents & POLLIN) { recv6(); #if 0 sl=sizeof(sa6); if ((len=recvfrom(s6,buf,sizeof(buf),0,(struct sockaddr*)&sa6,&sl))==-1) { perror("recvfrom"); return 3; } peer=(struct sockaddr*)&sa6; handle(s6,buf,len,sa6.sin6_scope_id); #endif } } } return 0; }