【问题标题】:Not able to receive UDP/IPv6 packets on secondary interface无法在辅助接口上接收 UDP/IPv6 数据包
【发布时间】:2012-01-26 04:12:12
【问题描述】:

我有以下用于 UDP 服务器的 C 代码,它将绑定到辅助接口 tap0 的 ipv6 地址。

context_t *
new_context(const struct sockaddr *listen_addr, size_t addr_size) {
  context_t *c = malloc( sizeof( context_t ) );
  time_t now;
  int reuse = 1;

  if (!listen_addr) {
    fprintf(stderr, "no listen address specified\n");
    return NULL;
  }

  srand( getpid() ^ time(&now) );

  if ( !c ) {
    perror("init: malloc:");
    return NULL;
  }

  memset(c, 0, sizeof( context_t ) );

  c->sockfd = socket(listen_addr->sa_family, SOCK_DGRAM, 0);
  if ( c->sockfd < 0 ) {
    perror("new_context: socket");
    goto onerror;
  }

  if ( setsockopt( c->sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 )
    perror("setsockopt SO_REUSEADDR");

  if ( bind (c->sockfd, listen_addr, addr_size) < 0 ) {
    perror("new_context: bind");
    goto onerror;
  }

  return c;

 onerror:
  if ( c->sockfd >= 0 )
    close ( c->sockfd );
  free( c );
  return NULL;
}



context_t *
get_context(const char *ipaddress, const char *port, unsigned int  scopeId) {
  int s;
  context_t* ctx;
  struct addrinfo hints;
  struct addrinfo *result, *rp;

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
  hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
  hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL;

  s = getaddrinfo(ipaddress, port, &hints, &result);
  if ( s != 0 ) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
    return NULL;
  } 

  /* iterate through results until success */
  for (rp = result; rp != NULL; rp = rp->ai_next) {
    ctx = new_context(rp->ai_addr, rp->ai_addrlen);
    if (ctx) {
      if ( rp->ai_family == PF_INET6 ) {
         struct sockaddr_in6* pSadrIn6 = (struct sockaddr_in6*) rp->ai_addr;
         if ( pSadrIn6->sin6_scope_id == 0 ) {
            pSadrIn6->sin6_scope_id = scopeId;
         }  /* End IF the scope ID wasn't set. */
      }
      goto finish;
    }
  }

  fprintf(stderr, "no context available for interface '%s'\n", node);

 finish:
  freeaddrinfo(result);
  return ctx;
}

设备 tap0 有以下详细信息:

tap0      Link encap:Ethernet  HWaddr ce:23:fc:81:7f:65  
          inet6 addr: fe80::cc23:fcff:fe81:7f65/64 Scope:Link
          inet6 addr: aaaa::1/64 Scope:Global

我使用以下命令运行上述代码:

./server -A aaaa::1

但它无法在 tap0 上监听到地址 aaaa::1 的消息。我可以在 tap0 接口上的 wireshark 转储上看到数据包。有趣的是,从上述命令(和代码)运行的服务器可以通过 localhost 接收消息。因此,如果我执行以下命令,服务器会收到消息:

nc -6 -vvv -u aaaa::1 61616 < /tmp/send_to_node_raw 

上面的命令发送和接收是通过localhost完成的。 有什么方法可以在辅助接口上以编程方式接收 UDP/IPv6 消息?

【问题讨论】:

  • 您设置的scopeId 是什么?是1吗?
  • 这只是一个界面,真的。请注意,bind(2)“绑定”到地址,而不是接口,也就是说,最多会收到 dst addr aaaa::1 的数据包。
  • @Nikolai:我将 scopeId 设置为 tap0。
  • silmor.de/59 -- 这是一个有趣的链接,它解释了在 IPv6 中,寻址到所有本地 IP(链接范围和全局)的数据包如何被循环回自身(设备“lo”)。这是通过本地路由表规则完成的(通过 route -n -6 看到)。如果我删除这些规则,数据包开始进入 tap0 接口,但它们的地址被修改为多播地址;这就是我的案子现在搁置的地方。
  • 啊,我注意到你实际上是在玩 CoAP,对吧?

标签: c udp localhost ipv6


【解决方案1】:

问题一定出在其他地方。使用上面的代码,我可以分别使用 aaaa::1/64 和 aaaa::2/64 作为本地和远程地址成功地接收来自另一个节点的数据包。

尝试绑定到 :: 并查看它是否以这种方式工作。也尝试使用 netcat6 绑定到 aaaa::1 并从另一个 netcat6 实例接收。

【讨论】:

    猜你喜欢
    • 2015-02-17
    • 2013-11-08
    • 1970-01-01
    • 2017-12-24
    • 2014-12-13
    • 1970-01-01
    • 2015-11-26
    • 2011-03-02
    • 1970-01-01
    相关资源
    最近更新 更多