/* FreeBSD i386 12.0-RELEASE controllen: 100 recvd: 3 bytes controllen is 100 0 len: 16 level: 0 type: 7 msg offsets: [0,16] 1 len: 13 level: 0 type: 65 msg offsets: [16,29] 2 len: 68 level: 0 type: 20 msg offsets: [32,100] FreeBSD AMD64 COMPAT_FREEBSD32 12.0-RELEASE-p3 controllen: 100 recvd: 3 bytes controllen is 97 <-- should have been 100 0 len: 16 level: 0 type: 7 msg offsets: [0,16] 1 len: 13 level: 0 type: 65 msg offsets: [16,29] 2 len: 68 level: 0 type: 20 msg offsets: [32,100] */ #include #include #include #include #include #include #include #include #include #include static struct sockaddr_in loc_addr; static int s; static void alarm_handler(int signo) { char buf[] = {0x1, 0x2, 0x3}; sendto(s, buf, sizeof buf, 0, (struct sockaddr*)&loc_addr, sizeof loc_addr); } int main(int argc, char *argv[]) { memset(&loc_addr, 0, sizeof loc_addr); loc_addr.sin_family = AF_INET; loc_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); loc_addr.sin_port = htons(7777); s = socket(AF_INET, SOCK_DGRAM, 0); bind(s, (struct sockaddr *)&loc_addr, sizeof loc_addr); int enable = 1; setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &enable, sizeof enable); setsockopt(s, IPPROTO_IP, IP_RECVTTL, &enable, sizeof enable); setsockopt(s, IPPROTO_IP, IP_RECVIF, &enable, sizeof enable); struct msghdr h; char buf[16]; struct iovec in[] = {{buf, sizeof buf}}; memset(&h, 0, sizeof h); h.msg_iov = in; h.msg_iovlen = 1; h.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)) /*IP_RECVDSTADDR*/ + CMSG_SPACE(sizeof(u_char)) /*IP_RECVTTL*/ + CMSG_SPACE(sizeof(struct sockaddr_dl)); /*IP_RECVIF*/ h.msg_control = calloc(0, h.msg_controllen); printf("controllen: %d\n", h.msg_controllen); alarm(1); struct sigaction sig = {}; sig.sa_handler = alarm_handler; sig.sa_flags = SA_RESTART; sigaction(SIGALRM, &sig, NULL); ssize_t recvd = recvmsg(s, &h, 0); printf("recvd: %zd bytes controllen is %d\n", recvd, h.msg_controllen); if (recvd < 0) { perror("recvmsg failed:"); exit(-1); } struct cmsghdr* cmsg = NULL; int i = 0; while((cmsg = CMSG_NXTHDR(&h, cmsg)) != NULL) { if (cmsg->cmsg_len == 0) { break; } int first_byte = (void*)cmsg - h.msg_control; int last_byte = first_byte + cmsg->cmsg_len; printf("%d len: %d level: %d type: %d msg offsets: [%d,%d]\n", i++, cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type, first_byte, last_byte); } return 0; }