int SendTo(int sock, const uint8_t *buffer, int len, const address &from, const address &to) { #ifdef IPV6_PKTINFO if (from.family() == AF_INET6) { uint8_t ctlbuf[CMSG_SPACE(sizeof(in6_pktinfo))]; cmsghdr *chdr = (cmsghdr *)ctlbuf; chdr->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); chdr->cmsg_level = IPPROTO_IPV6; chdr->cmsg_type = IPV6_PKTINFO; in6_pktinfo *info = (in6_pktinfo *)CMSG_DATA(chdr); info->ipi6_addr = from.v6()->sin6_addr; info->ipi6_ifindex = 0; msghdr msg; iovec iov; msg.msg_name = (char *)to.saddr(); msg.msg_namelen = to.addrlen(); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = (char *)ctlbuf; msg.msg_controllen = sizeof(ctlbuf); msg.msg_flags = 0; iov.iov_base = (char *)buffer; iov.iov_len = len; return sendmsg(sock, &msg, 0); } #endif return sendto(sock, buffer, len, 0, to.saddr(), to.addrlen()); }
static bool set_address(sockaddr_storage &t, const address &addr) { if (addr.family() == AF_INET) memcpy(&t, addr.v4(), addr.addrlen()); else if (addr.family() == AF_INET6) memcpy(&t, addr.v6(), addr.addrlen()); else return false; return true; }
bool address::is_equal(const address &a) const { if (stor.ss_family != a.stor.ss_family) return false; if (stor.ss_family == AF_INET6) return memcmp(&v6()->sin6_addr, &a.v6()->sin6_addr, sizeof(in6_addr)) == 0; else if (stor.ss_family == AF_INET) return v4()->sin_addr.s_addr == a.v4()->sin_addr.s_addr; return false; }
bool address::copy_address(const address &source) { if (family() != source.family()) return false; if (stor.ss_family == AF_INET6) v6()->sin6_addr = source.v6()->sin6_addr; else v4()->sin_addr = source.v4()->sin_addr; return true; }
int _McastListenOldAPI(int sock, const address &grpaddr) { if (grpaddr.family() == AF_INET6) { ipv6_mreq mreq; mreq.ipv6mr_interface = mcastInterface; mreq.ipv6mr_multiaddr = grpaddr.v6()->sin6_addr; return setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); } else { ip_mreq mreq; memset(&mreq, 0, sizeof(mreq)); // Specifying the interface doesn't work, there's ip_mreqn in linux.. // but what about other OSs? -hugo mreq.imr_multiaddr = grpaddr.v4()->sin_addr; return setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); } }
int RecvMsg(int sock, address &from, address &to, uint8_t *buffer, int buflen, int &ttl, uint64_t &ts) { int len; struct msghdr msg; struct iovec iov; uint8_t ctlbuf[64]; from.set_family(beaconUnicastAddr.family()); msg.msg_name = (char *)from.saddr(); msg.msg_namelen = from.addrlen(); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = (char *)ctlbuf; msg.msg_controllen = sizeof(ctlbuf); msg.msg_flags = 0; iov.iov_base = (char *)buffer; iov.iov_len = buflen; len = recvmsg(sock, &msg, 0); if (len < 0) return len; ts = 0; ttl = 127; to = beaconUnicastAddr; if (msg.msg_controllen > 0) { for (cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { if (hdr->cmsg_level == IPPROTO_IPV6 && hdr->cmsg_type == IPV6_HOPLIMIT) { ttl = *(int *)CMSG_DATA(hdr); #ifdef IPV6_PKTINFO } else if (hdr->cmsg_level == IPPROTO_IPV6 && hdr->cmsg_type == IPV6_PKTINFO) { if (hdr->cmsg_len == CMSG_LEN(sizeof(in6_pktinfo))) { in6_pktinfo *pktinfo = (in6_pktinfo *)CMSG_DATA(hdr); to.set_family(AF_INET6); to.v6()->sin6_addr = pktinfo->ipi6_addr; } #endif #ifdef IP_RECVTTL } else if (hdr->cmsg_level == IPPROTO_IP && hdr->cmsg_type == IP_RECVTTL) { ttl = *(uint8_t *)CMSG_DATA(hdr); #endif } else if (hdr->cmsg_level == IPPROTO_IP && hdr->cmsg_type == IP_TTL) { ttl = *(int *)CMSG_DATA(hdr); #ifdef SO_TIMESTAMP } else if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SO_TIMESTAMP) { timeval *tv = (timeval *)CMSG_DATA(hdr); ts = tv->tv_sec; ts *= 1000; ts += tv->tv_usec / 1000; #endif } } } if (!ts) { ts = get_time_of_day(); } return len; }