/* * Send to an UDP socket with a pad destination option. * * Francis Dupont January 2020 */ #include #include #ifdef __APPLE__ #define __APPLE_USE_RFC_3542 #endif #include #include #include #include #include #include #include #include #include struct sockaddr_in6 sin6; int s; socklen_t slen; char src[INET6_ADDRSTRLEN]; uint8_t dstopt[8]; struct ip6_opt *opt; uint8_t pack[8000]; int cc; int main(int argc, char *argv[]) { if (argc != 2) errx(1, "usage: %s ", argv[0]); memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; #ifdef BSD sin6.sin6_len = sizeof(sin6); #endif sin6.sin6_port = htons(12345); if (inet_pton(AF_INET6, argv[1], &sin6.sin6_addr) != 1) err(1, "inet_pton(%s)", argv[1]); s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) err(1, "socket"); if (connect(s, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) err(1, "connect"); memset(&sin6, 0, sizeof(sin6)); slen = sizeof(sin6); if (getsockname(s, (struct sockaddr *)&sin6, &slen) < 0) err(1, "getsockname"); if (sin6.sin6_family != AF_INET6) errx(1, "bad family %d", (int)sin6.sin6_family); if (inet_ntop(sin6.sin6_family, &sin6.sin6_addr, src, sizeof(src)) == NULL) err(1, "inet_ntop"); memset(&dstopt, 0, sizeof(dstopt)); opt = (struct ip6_opt *)&dstopt[sizeof(struct ip6_ext)]; opt->ip6o_type = IP6OPT_PADN; opt->ip6o_len = 4; if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, dstopt, sizeof(dstopt)) < 0) err(1, "setsockopt(IPV6_DSTOPTS)"); for (;;) { memset(pack, 0, sizeof(pack)); printf("send %s -> %s:\n", src, argv[1]); cc = read(0, pack, sizeof(pack)); if (cc < 0) err(1, "read"); if (cc == 0) exit(0); if (send(s, pack, cc, 0) < 0) err(1, "send"); } errx(1, "exit loop"); }