Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何使用相同的UDP套接字发送和接收数据包?我在这段代码中遗漏了什么?_C_Sockets_Networking_Udp_Port - Fatal编程技术网

C 如何使用相同的UDP套接字发送和接收数据包?我在这段代码中遗漏了什么?

C 如何使用相同的UDP套接字发送和接收数据包?我在这段代码中遗漏了什么?,c,sockets,networking,udp,port,C,Sockets,Networking,Udp,Port,我正在尝试编写一个应用程序,其中客户端应向服务器发送UDP数据包,然后服务器应通过无线接口回复客户端。客户端和服务器都在同一个二进制文件中实现,用户可以使用适当的命令行参数选择模式 我正在使用UDP,但在使客户端和服务器通信时遇到问题。 首先,在这两种情况下,我尝试使用相同的UDP套接字来接收和发送数据包。我认为这是可能的,但我开始有一些怀疑 然后,这是客户端和服务器的相关代码: struct sockaddr_in inaddr; fd=socket(AF_I

我正在尝试编写一个应用程序,其中客户端应向服务器发送UDP数据包,然后服务器应通过无线接口回复客户端。客户端和服务器都在同一个二进制文件中实现,用户可以使用适当的命令行参数选择模式

我正在使用UDP,但在使客户端和服务器通信时遇到问题。 首先,在这两种情况下,我尝试使用相同的UDP套接字来接收和发送数据包。我认为这是可能的,但我开始有一些怀疑

然后,这是客户端和服务器的相关代码:

        struct sockaddr_in inaddr;

        fd=socket(AF_INET,SOCK_DGRAM,0);

        if(fd==-1) {
            perror("socket() error");
            exit(EXIT_FAILURE);
        }

        // Prepare sockaddr_in structure
        bzero(&inaddr,sizeof(inaddr));
        inaddr.sin_family=AF_INET;
        inaddr.sin_port=htons(opts.port); // opts.port is parsed from the command line
        inaddr.sin_addr.s_addr=opts.destIPaddr.s_addr; // opts.destIPaddr is parsed from the command line and already in the correct format

        // Bind to the wireless interface (devname is previusly obtained in a tested piece of code)
        if(setsockopt(sData.descriptor,SOL_SOCKET,SO_BINDTODEVICE,devname,strlen(devname))==-1) {
            perror("setsockopt() for SO_BINDTODEVICE error");
            close(sData.descriptor);
            exit(EXIT_FAILURE);
        }
两者都将使用以下方式进行读写:

sendto(fd,packet,packetsize,0,(struct sockaddr *)&(inaddr),sizeof(inaddr))
以及:

问题是,客户端和服务器无法通信,对于发送的每个数据包,客户端似乎总是收到一个“端口不可访问”ICMP数据包(我可以清楚地看到,在Wireshark中,客户端发送正确的UDP数据包,而服务器以“端口不可访问”拒绝这些数据包)

可能我没有以正确的方式使用UDP套接字:你知道我这里缺少什么吗?我的最终目标是:

  • 将套接字绑定到客户端和服务器端的特定端口,即客户端应以指定端口作为目的地发送数据包,服务器应在同一端口上接收数据包
  • 仅将套接字绑定到无线接口(其名称目前存储在
    devname
    中-但获取其IP地址或MAC地址也不成问题)
  • 使服务器和客户端通过UDP进行通信,客户端发送请求,服务器接收请求并回复客户端,客户端应接收所有回复

尽管问题本身并不清楚,但您的评论似乎表明您没有像@Someprogrammerdude推断的那样将地址绑定到套接字。在这种情况下,重要的是要理解,
bind()
ing的作用与
SO\u BINDTODEVICE
socket选项的作用不同且基本上是正交的,尽管选项名称中使用了“bind”

bind()
函数用于将套接字与地址关联,对于TCP和UDP,该地址包括端口号。
SO\u BINDTODEVICE
是关于将套接字限制为通过特定设备的数据。虽然在实践中,IP地址和网络接口之间通常存在一对一的映射

  • POSIX系统接口并非特定于IP协议套件,它们注意避免假设所有地址族都具有与IP类似的特性

  • 即使对于IP,一个网络接口也可能有多个地址

  • 特别是对于IP,在任何情况下,在系统接受某个端口的入站流量之前,都需要将套接字与该端口相关联。socket选项不能做到这一点,它甚至不能直接将套接字与IP地址相关联。这就是
    bind()
    的角色

  • 在你询问的评论中

    我是否总是需要在中使用不同的
    结构sockaddr\u,一个用于绑定
    和 一个用于发送到?我不能只用一个就得到同样的结果吗 结构

    您可以重用套接字地址结构,但要清楚,对于
    bind()
    sendto()
    ,其内容需要不同。前者需要绑定到本地地址,而后者需要将消息发送到的远程地址。我认为为这些不同的目的使用不同的对象会更干净一些,但这不是必需的


    至于让客户端选择自己的端口,正如我在评论中所说,这是UDP的常用操作模式。事实上,通常在第一次调用
    sendto()
    时,如果尚未绑定套接字。您已经在使用
    recvfrom()
    ,服务器(以及客户端)可以通过它获取发送每条消息的对等方的地址。您应该能够将该地址对象反馈回
    sendto()
    ,以发送响应。因此,应该很容易确保服务器
    bind()
    s以侦听已知的端口号,但客户端不侦听,以便使用系统自动分配的端口号。

    我会亲自将UDP服务器绑定到通配符地址和特定端口,并使用套接字选项获取接口和目的地地址,作为每个分组的辅助消息

    本质上,启用
    IP\u PKTINFO
    socket选项意味着您使用接收到的每个数据包都会收到
    IPPROTO\u IP
    level
    IP\u PKTINFO
    类型

    类似地,在发送响应时,可以使用辅助
    IP\u PKTINFO
    消息中的
    ipi\u ifindex
    ipi\u spec\u dst
    成员来告诉内核如何路由消息

    通过这种方式,您可以只绑定到一个(或者两个,如果您同时使用IPv4和IPv6)通配符套接字,并使用它通过您想要的任何接口接收和发送UDP数据包;特别是,使用客户端用作目标的相同接口和源IP地址。每当有新的接口可用时,服务器端也会立即响应这些接口(尽管根据它们来自的接口,它显然可以将不需要的客户端请求放在地板上)。简单,而且相当健壮

    下面的示例server.c可能更好地说明了这一点:

    #define _POSIX_C_SOURCE  200809L
    #define _GNU_SOURCE
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/udp.h>
    #include <net/if.h>
    #include <netdb.h>
    #include <signal.h>
    #include <string.h>
    #include <stdio.h>
    #include <errno.h>
    
    static volatile sig_atomic_t  done = 0;
    
    static void handle_done(int signum)
    {
        if (!done)
            done = signum;
    }
    
    static int install_done(int signum)
    {
        struct sigaction  act;
    
        memset(&act, 0, sizeof act);
        sigemptyset(&act.sa_mask);
    
        act.sa_handler = handle_done;
        act.sa_flags   = 0;
    
        return sigaction(signum, &act, NULL);
    }
    
    static inline const char *ip4_address(const struct in_addr addr)
    {
        static char    buffer[32];
        char          *p = buffer + sizeof buffer;
        unsigned char  octet[4];
    
        /* in_addr is in network byte order. */
        memcpy(octet, &addr, 4);
    
        /* We build the string in reverse order. */
        *(--p) = '\0';
        do {
            *(--p) = '0' + (octet[3] % 10);
            octet[3] /= 10;
        } while (octet[3]);
        *(--p) = '.';
        do {
            *(--p) = '0' + (octet[2] % 10);
            octet[2] /= 10;
        } while (octet[2]);
        *(--p) = '.';
        do {
            *(--p) = '0' + (octet[1] % 10);
            octet[1] /= 10;
        } while (octet[1]);
        *(--p) = '.';
        do {
            *(--p) = '0' + (octet[0] % 10);
            octet[0] /= 10;
        } while (octet[0]);
    
        return p;
    }
    
    int main(int argc, char *argv[])
    {
        int   ip4fd, ip4port;
        char  dummy;
    
        if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
            fprintf(stderr, "\n");
            fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
            fprintf(stderr, "       %s UDP-PORT-NUMBER\n", argv[0]);
            fprintf(stderr, "\n");
            return EXIT_FAILURE;
        }
        if (sscanf(argv[1], " %d %c", &ip4port, &dummy) != 1 || ip4port < 1 || ip4port > 65535) {
            fprintf(stderr, "%s: Invalid UDP port number.\n", argv[1]);
            return EXIT_FAILURE;
        }
    
        if (install_done(SIGHUP) ||
            install_done(SIGINT) ||
            install_done(SIGTERM)) {
            fprintf(stderr, "Cannot install signal handlers: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        ip4fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (ip4fd == -1) {
            fprintf(stderr, "Cannot create an UDP socket: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        /* Set the IP_PKTINFO socket option, so each received datagram has an
           ancillary message containing a struct in_pktinfo. */
        {
            int  option = 1;
            if (setsockopt(ip4fd, IPPROTO_IP, IP_PKTINFO, &option, sizeof option) == -1) {
                fprintf(stderr, "Cannot set IP_PKTINFO socket option: %s.\n", strerror(errno));
                close(ip4fd);
                return EXIT_FAILURE;
            }
        }
    
        /* Bind to the wildcard address, to receive packets using any network interface. */
        {
            struct sockaddr_in  ip4addr;
    
            ip4addr.sin_family = AF_INET;
            ip4addr.sin_port   = htons(ip4port);
            ip4addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
            if (bind(ip4fd, (const struct sockaddr *)(&ip4addr), sizeof ip4addr) == -1) {
                fprintf(stderr, "Cannot bind to port %d: %s.\n", ip4port, strerror(errno));
                close(ip4fd);
                return EXIT_FAILURE;
            }
        }
    
        printf("Now listening on UDP port %d.\n", ip4port);
        printf("Press CTRL+C, or send HUP, INT, or TERM (pid %ld) to exit.\n",
               (long)getpid());
        fflush(stdout);
    
        /* Receive UDP messages, and describe them. */
        {
            unsigned char        payload[4096], ancillary[1024];
            char                *iface, ifacebuf[IF_NAMESIZE + 1];
            unsigned int         iface_index;
            struct in_addr       iface_addr, dest_addr;
            struct iovec         iov;
            struct msghdr        hdr;
            struct cmsghdr      *cmsg;
            struct sockaddr_in   from;
            struct in_pktinfo   *info;
            ssize_t              len;
            size_t               i;
    
            while (!done) {
    
                iov.iov_base = payload;
                iov.iov_len = sizeof payload;
    
                hdr.msg_name = &from;
                hdr.msg_namelen = sizeof from;
    
                hdr.msg_iov = &iov;
                hdr.msg_iovlen = 1;
    
                hdr.msg_control = ancillary;
                hdr.msg_controllen = sizeof ancillary;
    
                hdr.msg_flags = 0;
    
                /* Receive a new datagram. */
                len = recvmsg(ip4fd, &hdr, 0);
                if (len < 0) {
                    if (len == -1) {
                        if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
                            continue;
                        fprintf(stderr, "Error receiving data: %s.\n", strerror(errno));
                    } else
                        fprintf(stderr, "recvmsg() error: Unexpected return value, %zd.\n", len);
                    close(ip4fd);
                    return EXIT_FAILURE;
                }
    
                /* Report. */
                printf("Received %zu bytes from %s port %d:\n",
                       (size_t)len, ip4_address(from.sin_addr), ntohs(from.sin_port));
    
                /* Check the ancillary data for the pktinfo structure. */
                info = NULL;
                for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&hdr, cmsg))
                    if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
                        info = (void *)CMSG_DATA(cmsg);
    
                if (!info) {
                    fprintf(stderr, "Error: Packet is missing the IP_PKTINFO ancillary information!\n");
                    close(ip4fd);
                    exit(EXIT_FAILURE);
                }
    
                /* info may be unaligned. */
                memcpy(&iface_index, &(info->ipi_ifindex),   sizeof info->ipi_ifindex);
                memcpy(&iface_addr,  &(info->ipi_spec_dst),  sizeof info->ipi_spec_dst);
                memcpy(&dest_addr,   &(info->ipi_addr),      sizeof info->ipi_addr);
    
                iface = if_indextoname(info->ipi_ifindex, ifacebuf);
    
                /* Report the IP_PKTINFO information. */
                if (iface)
                    printf("  Interface: %u (%s)\n", iface_index, iface);
                else
                    printf("  Interface: %u\n", iface_index);
                printf("  Local address: %s port %d\n", ip4_address(iface_addr), ip4port);
                printf("  Real destination: %s port %d\n", ip4_address(dest_addr), ip4port);
    
                for (i = 0; i < (size_t)len; i++) {
                    if (i == 0)
                        printf("  Data: 0x%02x", payload[i]);
                    else
                    if ((i & 15) == 0)
                        printf("\n        0x%02x", payload[i]);
                    else
                        printf(" 0x%02x", payload[i]);
                }
    
                if (len > 0)
                    printf("\n");
    
                fflush(stdout);
    
                /*
                 * Construct a response.
                 */
                payload[0] = 'O';
                payload[1] = 'k';
                payload[2] = '!';
                payload[3] = '\n';
                iov.iov_base = payload;
                iov.iov_len = 4;
    
                /* Keep hdr.msg_name and hdr.msg_namelen intact. */
    
                hdr.msg_iov = &iov;
                hdr.msg_iovlen = 1;
    
                /* Prep the ancillary data. */
                hdr.msg_control = ancillary;
                hdr.msg_controllen = CMSG_SPACE(sizeof (struct in_pktinfo));
    
                cmsg = CMSG_FIRSTHDR(&hdr);
                cmsg->cmsg_level = IPPROTO_IP;
                cmsg->cmsg_type = IP_PKTINFO;
                cmsg->cmsg_len = CMSG_LEN(sizeof (struct in_pktinfo));
                info = (void *)CMSG_DATA(cmsg);
                /* info may be unaligned. */
                memcpy(&(info->ipi_ifindex), &iface_index, sizeof info->ipi_ifindex);
                memcpy(&(info->ipi_spec_dst), &iface_addr, sizeof info->ipi_spec_dst);
                memcpy(&(info->ipi_addr), &from.sin_addr,  sizeof info->ipi_addr);
    
                hdr.msg_flags = 0;
    
                /* Send the response. */
                do {
                    len = sendmsg(ip4fd, &hdr, MSG_NOSIGNAL);
                } while (len == -1 && errno == EINTR);
                if (len == -1) {
                    fprintf(stderr, "Cannot send a response message: %s.\n", strerror(errno));
                    close(ip4fd);
                    return EXIT_FAILURE;
                }
    
                printf("  %zd-byte response sent successfully.\n", len);
                fflush(stdout);
            }
        }
    
        close(ip4fd);
        return EXIT_SUCCESS;
    }
    
    #定义POSIX_C_SOURCE200809L
    #定义GNU源
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    静态易失性sig_原子_t done=0;
    静态无效句柄_done(int signum)
    {
    如果(!完成)
    
    #define _POSIX_C_SOURCE  200809L
    #define _GNU_SOURCE
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/udp.h>
    #include <net/if.h>
    #include <netdb.h>
    #include <signal.h>
    #include <string.h>
    #include <stdio.h>
    #include <errno.h>
    
    static volatile sig_atomic_t  done = 0;
    
    static void handle_done(int signum)
    {
        if (!done)
            done = signum;
    }
    
    static int install_done(int signum)
    {
        struct sigaction  act;
    
        memset(&act, 0, sizeof act);
        sigemptyset(&act.sa_mask);
    
        act.sa_handler = handle_done;
        act.sa_flags   = 0;
    
        return sigaction(signum, &act, NULL);
    }
    
    static inline const char *ip4_address(const struct in_addr addr)
    {
        static char    buffer[32];
        char          *p = buffer + sizeof buffer;
        unsigned char  octet[4];
    
        /* in_addr is in network byte order. */
        memcpy(octet, &addr, 4);
    
        /* We build the string in reverse order. */
        *(--p) = '\0';
        do {
            *(--p) = '0' + (octet[3] % 10);
            octet[3] /= 10;
        } while (octet[3]);
        *(--p) = '.';
        do {
            *(--p) = '0' + (octet[2] % 10);
            octet[2] /= 10;
        } while (octet[2]);
        *(--p) = '.';
        do {
            *(--p) = '0' + (octet[1] % 10);
            octet[1] /= 10;
        } while (octet[1]);
        *(--p) = '.';
        do {
            *(--p) = '0' + (octet[0] % 10);
            octet[0] /= 10;
        } while (octet[0]);
    
        return p;
    }
    
    int main(int argc, char *argv[])
    {
        int   ip4fd, ip4port;
        char  dummy;
    
        if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
            fprintf(stderr, "\n");
            fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
            fprintf(stderr, "       %s UDP-PORT-NUMBER\n", argv[0]);
            fprintf(stderr, "\n");
            return EXIT_FAILURE;
        }
        if (sscanf(argv[1], " %d %c", &ip4port, &dummy) != 1 || ip4port < 1 || ip4port > 65535) {
            fprintf(stderr, "%s: Invalid UDP port number.\n", argv[1]);
            return EXIT_FAILURE;
        }
    
        if (install_done(SIGHUP) ||
            install_done(SIGINT) ||
            install_done(SIGTERM)) {
            fprintf(stderr, "Cannot install signal handlers: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        ip4fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (ip4fd == -1) {
            fprintf(stderr, "Cannot create an UDP socket: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        /* Set the IP_PKTINFO socket option, so each received datagram has an
           ancillary message containing a struct in_pktinfo. */
        {
            int  option = 1;
            if (setsockopt(ip4fd, IPPROTO_IP, IP_PKTINFO, &option, sizeof option) == -1) {
                fprintf(stderr, "Cannot set IP_PKTINFO socket option: %s.\n", strerror(errno));
                close(ip4fd);
                return EXIT_FAILURE;
            }
        }
    
        /* Bind to the wildcard address, to receive packets using any network interface. */
        {
            struct sockaddr_in  ip4addr;
    
            ip4addr.sin_family = AF_INET;
            ip4addr.sin_port   = htons(ip4port);
            ip4addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
            if (bind(ip4fd, (const struct sockaddr *)(&ip4addr), sizeof ip4addr) == -1) {
                fprintf(stderr, "Cannot bind to port %d: %s.\n", ip4port, strerror(errno));
                close(ip4fd);
                return EXIT_FAILURE;
            }
        }
    
        printf("Now listening on UDP port %d.\n", ip4port);
        printf("Press CTRL+C, or send HUP, INT, or TERM (pid %ld) to exit.\n",
               (long)getpid());
        fflush(stdout);
    
        /* Receive UDP messages, and describe them. */
        {
            unsigned char        payload[4096], ancillary[1024];
            char                *iface, ifacebuf[IF_NAMESIZE + 1];
            unsigned int         iface_index;
            struct in_addr       iface_addr, dest_addr;
            struct iovec         iov;
            struct msghdr        hdr;
            struct cmsghdr      *cmsg;
            struct sockaddr_in   from;
            struct in_pktinfo   *info;
            ssize_t              len;
            size_t               i;
    
            while (!done) {
    
                iov.iov_base = payload;
                iov.iov_len = sizeof payload;
    
                hdr.msg_name = &from;
                hdr.msg_namelen = sizeof from;
    
                hdr.msg_iov = &iov;
                hdr.msg_iovlen = 1;
    
                hdr.msg_control = ancillary;
                hdr.msg_controllen = sizeof ancillary;
    
                hdr.msg_flags = 0;
    
                /* Receive a new datagram. */
                len = recvmsg(ip4fd, &hdr, 0);
                if (len < 0) {
                    if (len == -1) {
                        if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
                            continue;
                        fprintf(stderr, "Error receiving data: %s.\n", strerror(errno));
                    } else
                        fprintf(stderr, "recvmsg() error: Unexpected return value, %zd.\n", len);
                    close(ip4fd);
                    return EXIT_FAILURE;
                }
    
                /* Report. */
                printf("Received %zu bytes from %s port %d:\n",
                       (size_t)len, ip4_address(from.sin_addr), ntohs(from.sin_port));
    
                /* Check the ancillary data for the pktinfo structure. */
                info = NULL;
                for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&hdr, cmsg))
                    if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
                        info = (void *)CMSG_DATA(cmsg);
    
                if (!info) {
                    fprintf(stderr, "Error: Packet is missing the IP_PKTINFO ancillary information!\n");
                    close(ip4fd);
                    exit(EXIT_FAILURE);
                }
    
                /* info may be unaligned. */
                memcpy(&iface_index, &(info->ipi_ifindex),   sizeof info->ipi_ifindex);
                memcpy(&iface_addr,  &(info->ipi_spec_dst),  sizeof info->ipi_spec_dst);
                memcpy(&dest_addr,   &(info->ipi_addr),      sizeof info->ipi_addr);
    
                iface = if_indextoname(info->ipi_ifindex, ifacebuf);
    
                /* Report the IP_PKTINFO information. */
                if (iface)
                    printf("  Interface: %u (%s)\n", iface_index, iface);
                else
                    printf("  Interface: %u\n", iface_index);
                printf("  Local address: %s port %d\n", ip4_address(iface_addr), ip4port);
                printf("  Real destination: %s port %d\n", ip4_address(dest_addr), ip4port);
    
                for (i = 0; i < (size_t)len; i++) {
                    if (i == 0)
                        printf("  Data: 0x%02x", payload[i]);
                    else
                    if ((i & 15) == 0)
                        printf("\n        0x%02x", payload[i]);
                    else
                        printf(" 0x%02x", payload[i]);
                }
    
                if (len > 0)
                    printf("\n");
    
                fflush(stdout);
    
                /*
                 * Construct a response.
                 */
                payload[0] = 'O';
                payload[1] = 'k';
                payload[2] = '!';
                payload[3] = '\n';
                iov.iov_base = payload;
                iov.iov_len = 4;
    
                /* Keep hdr.msg_name and hdr.msg_namelen intact. */
    
                hdr.msg_iov = &iov;
                hdr.msg_iovlen = 1;
    
                /* Prep the ancillary data. */
                hdr.msg_control = ancillary;
                hdr.msg_controllen = CMSG_SPACE(sizeof (struct in_pktinfo));
    
                cmsg = CMSG_FIRSTHDR(&hdr);
                cmsg->cmsg_level = IPPROTO_IP;
                cmsg->cmsg_type = IP_PKTINFO;
                cmsg->cmsg_len = CMSG_LEN(sizeof (struct in_pktinfo));
                info = (void *)CMSG_DATA(cmsg);
                /* info may be unaligned. */
                memcpy(&(info->ipi_ifindex), &iface_index, sizeof info->ipi_ifindex);
                memcpy(&(info->ipi_spec_dst), &iface_addr, sizeof info->ipi_spec_dst);
                memcpy(&(info->ipi_addr), &from.sin_addr,  sizeof info->ipi_addr);
    
                hdr.msg_flags = 0;
    
                /* Send the response. */
                do {
                    len = sendmsg(ip4fd, &hdr, MSG_NOSIGNAL);
                } while (len == -1 && errno == EINTR);
                if (len == -1) {
                    fprintf(stderr, "Cannot send a response message: %s.\n", strerror(errno));
                    close(ip4fd);
                    return EXIT_FAILURE;
                }
    
                printf("  %zd-byte response sent successfully.\n", len);
                fflush(stdout);
            }
        }
    
        close(ip4fd);
        return EXIT_SUCCESS;
    }