【问题标题】:Creating socket compatible with IPv4 and IPv6创建与 IPv4 和 IPv6 兼容的套接字
【发布时间】:2013-05-02 13:29:12
【问题描述】:

我正在编写一个程序,它可以读取我在特定网络接口(VLAN:eth0.32)上分配的 IP 地址。我不知道我是否被分配了 IPv4 或 IPv6 地址,因此我尝试将其编写为与协议族无关。

它的工作方式是:使用 for,我在可用网络接口列表中导航,然后在找到我的 VLAN (eth0.32) 的位置停下来读取 IP 地址。无论如何,在这个开发阶段,我只希望它适用于 IPv4,但在我想实现 IPv6 支持时让它准备就绪。

如果我正常创建套接字,程序会工作并读取 IPv4 地址:

sd=socket(PF_INET, SOCK_DGRAM, 0);

但由于我无法使用此套接字系列 (PF_INET=IPv4) 读取 IPv6 地址,所以我这样做:

sd=socket(PF_INET6, SOCK_DGRAM, 0);
setsockopt(sd, SOL_SOCKET, IPV6_V6ONLY, 0, sizeof(int));

问题是使用这个 IPv6 套接字,它无法完成读取 IP 地址的 if 条件:

if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)

更多信息,这是我的全部代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <net/if.h>

int main(int argc, char **argv)
{

    struct ifconf ifc;
    struct ifreq ifr[MAX_NETWORK_INTERFACES];
    int ifc_num, addr, i;
    static uint8 sd=0;

    sd=socket(PF_INET6, SOCK_DGRAM, 0);
    setsockopt(sd, SOL_SOCKET, IPV6_V6ONLY, 0, sizeof(int)); //I change the socket option IPV6_V6ONLY to false, so it should be compatible with IPv4

    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr; //Buffer address

        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);  //Number of network interfaces found

            for (i = 0; i < ifc_num; i++)
            {

                if(ifr[i].ifr_addr.sa_family != AF_INET) //If it is not an IPv4 address, we do nothing
                {
                    continue;
                }

                if (strcmp(ifr[i].ifr_ifrn.ifrn_name,"eth0.32")==0)
                {
                    if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0) // HERE IS WHERE THE IPv6 SOCKET DOESN'T ENTER!!!
                    {
                        addr = ntohl(((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr);

                    }

                    fclose(fp);

                    break;  // end loop
                }
            }
        }
    }
    return addr;

}

提前感谢您的帮助!

【问题讨论】:

标签: c sockets ipv6


【解决方案1】:

您应该使用getifaddrs 而不是ioctl SIOCGIFADDR

【讨论】:

  • 那样的话,(ioctl(sd, SIOCGIFCONF, &amp;ifc) == 0) 也不起作用吗?
  • @Nacao,这些 IOCTl 未包含在任何标准中,并且不可移植。您必须查阅您的操作系统文档 - 或者如果对 SO 提出问题,请告诉我们您使用的是什么操作系统。在 Linux 上使用 rnetlink(7)。在 Windows 上,您可能需要“IP Helper”API msdn.microsoft.com/en-us/library/windows/desktop/…
  • 感谢您的快速答复。我正在使用 Linux。我仅针对 IPv4 地址测试了此代码实现,它运行良好,当我想添加 IPv6 支持时出现上述问题,它再次不适用于 IPv4。
  • @Nacao,Linux 文档说 SIOGIFCONF 只返回 IPv4 地址。见linux.die.net/man/7/rtnetlinklinux.die.net/man/7/ipv6linux.die.net/man/7/netdevice
  • 你是对的。我已经阅读并使用了getifaddrs。现在我有一个网络接口列表,我可以使用 for 进行导航。我希望它通过按名称if (strcmp(ifa-&gt;ifa_name,"eth0.32")==0) 过滤它们来打印我的 VLAN(eth0.32)的 IP 地址,它确实可以打印出 IPv4 地址和 IPv6 地址。这很奇怪,因为我只建立了 IPv4 地址。通过调试它,我意识到有一个名为“eth0.32”和家族AF_INET的网络设备,还有另一个与AF_INET6同名的网络设备。这怎么可能?
猜你喜欢
  • 2012-07-27
  • 1970-01-01
  • 2021-10-15
  • 2014-01-06
  • 2015-03-05
  • 1970-01-01
  • 2014-04-10
  • 2016-09-19
  • 1970-01-01
相关资源
最近更新 更多