#include #include #include #include #include #include #include #include #include #include #define SENDSIZE 2000 #define SENDPORT 1234 int main(int argc, char **argv) { struct addrinfo hints, *res; struct sockaddr_in6 sa6; struct msghdr msg; struct iovec iov; struct timeval tv; struct ip6_mtuinfo *minfo; struct cmsghdr *cmsg; fd_set fd; int s6, ret, v; char *buf, ctrl[CMSG_SPACE(sizeof(struct ip6_mtuinfo))]; if (argc < 2) errx(1, "Usage: %s \n", argv[0]); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; ret = getaddrinfo(argv[1], NULL, &hints, &res); if (ret != 0) errx(1, "getaddrinfo(%s): %s", argv[1], gai_strerror(ret)); s6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s6 < 0) err(1, "socket()"); v = 1; ret = setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPATHMTU, &v, sizeof(v)); if (ret < 0) err(1, "setsockopt(IPV6_RECVPATHMTU)"); v = 1; ret = setsockopt(s6, IPPROTO_IPV6, IPV6_DONTFRAG, &v, sizeof(v)); if (ret < 0) err(1, "setsockopt(IPV6_DONTFRAG)"); buf = calloc(1, SENDSIZE); if (buf == NULL) err(1, "calloc()"); sa6 = *(struct sockaddr_in6 *)res->ai_addr; sa6.sin6_port = htons(SENDPORT); ret = sendto(s6, buf, SENDSIZE, 0, (struct sockaddr *)&sa6, sizeof(sa6)); if (ret != SENDSIZE) warn("sendto()"); FD_ZERO(&fd); FD_SET(s6, &fd); tv.tv_sec = 2; tv.tv_usec = 0; ret = select(s6 + 1, &fd, NULL, NULL, &tv); if (ret <= 0) printf("No ancillary data received\n"); else { memset(&msg, 0, sizeof(msg)); msg.msg_name = &sa6; msg.msg_namelen = sizeof(sa6); msg.msg_control = ctrl; msg.msg_controllen = sizeof(ctrl); msg.msg_iov = &iov; msg.msg_iovlen = 1; iov.iov_base = buf; iov.iov_len = SENDSIZE; cmsg = (struct cmsghdr *)ctrl; ret = recvmsg(s6, &msg, 0); if (ret < 0) warn("recvmsg()"); else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PATHMTU && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { minfo = (struct ip6_mtuinfo *)CMSG_DATA(cmsg); ret = getnameinfo((struct sockaddr *)&minfo->ip6m_addr, sizeof(minfo->ip6m_addr), buf, SENDSIZE, NULL, 0, NI_NUMERICHOST); if (ret == 0) printf("IPV6_PATHMTU ancillary " "data received:\nIPv6 address: %s\n" "MTU: %u\n", buf, minfo->ip6m_mtu); else warnx("getnameinfo(): %s", gai_strerror(ret)); } } free(buf); freeaddrinfo(res); close(s6); return (0); }