LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 850|回复: 0

sendMsg调用问题

[复制链接]
发表于 2010-5-27 10:18:44 | 显示全部楼层 |阅读模式
zabra组织写的一段源于ospf的源代码:
int ospf6_sendmsg(struct in6_addr *src, struct in6_addr *dst,unsigned int *ifindex, struct iovec *message) {
    int retval;
    struct msghdr smsghdr;
    struct cmsghdr *scmsgp;
    u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
    struct in6_pktinfo *pktinfo;
    struct sockaddr_in6 dst_sin6;

    assert(dst);
    assert(*ifindex);

    scmsgp = (struct cmsghdr *) cmsgbuf;
    pktinfo = (struct in6_pktinfo *) (CMSG_DATA(scmsgp));
    memset(&dst_sin6, 0, sizeof (struct sockaddr_in6));

    /* source address */
    pktinfo->ipi6_ifindex = *ifindex;
    if (src)
        memcpy(&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));
    else
        memset(&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));

    /* destination address */
    dst_sin6.sin6_family = AF_INET6;
#ifdef SIN6_LEN
    dst_sin6.sin6_len = sizeof (struct sockaddr_in6);
#endif /*SIN6_LEN*/
    memcpy(&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));
#ifdef HAVE_SIN6_SCOPE_ID
    dst_sin6.sin6_scope_id = *ifindex;
#endif

    /* send control msg */
    scmsgp->cmsg_level = IPPROTO_IPV6;
    scmsgp->cmsg_type = IPV6_PKTINFO;
    scmsgp->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo));
    /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */

    /* send msg hdr */
    memset(&smsghdr, 0, sizeof (smsghdr));
    smsghdr.msg_iov = message;
    smsghdr.msg_iovlen = iov_count(message);
    smsghdr.msg_name = (caddr_t) & dst_sin6;
    smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
    smsghdr.msg_control = (caddr_t) cmsgbuf;
    smsghdr.msg_controllen = sizeof (cmsgbuf);

printf("sendmsg: ospf6_sock: %d\n", ospf6_sock);
    retval = sendmsg(ospf6_sock, &smsghdr, 0);
    printf("reval is %d\n", retval);
    if (retval != iov_totallen(message))
        printf("sendmsg failed: ifindex: %d:  (%d)", *ifindex, errno);
    // printf ("sendmsg failed: ifindex: %d: %s (%d)",*ifindex, safe_strerror (errno), errno);
    printf("ospf6_sendmsg(): finished. \n");
    return retval;
}

在solaris以及red hat linux下测试均可成功调用,在Cent OS 5.4测试报错,提示“reval is -1
sendmsg failed: ifindex: 2:  (22)ospf6_sendmsg(): finished. ”
上网查22号错误是Invaild Segment.
后来把“pktinfo->ipi6_ifindex = *ifindex;”以及“smsghdr.msg_controllen = sizeof (cmsgbuf);”这两行代码注释后能正常发包,觉得和ifindex有关系。使用ifindex查看网卡信息,发现red hat linux只有eth0,而Cent除了eth0之外还有peth0,网上对peth0的介绍比较少,想请教一下这是什么东东。
另外在Cent下使用该函数与OSPF路由器通信,正常的情况应该是计算机先组播一个OSPF HELLO(把HELLO包发去ff02::5),然后路由器回应一个OSPF HELLO,计算机从HELLO获取路由器网关IP 然后计算机向该地址发一个OSPF DB Descri.包,然后路由器也会回应一个OSPF DB Descri. 该过程在solaris和red hat下测试均无问题,可是在Cent下发了OSPF DB Descri.路由器就没有回应了。Cent是在虚拟机跑的,在WIN XP安装了WireShark进行抓包,发现DB Descri.包已成功发给路由器,不知道为什么路由器没有回应。
在red hat下进行抓包,发现前几个包各个字段与Cent下是一模一样的。但red hat下路由器有回应DB Descri. 本人做的改动仅仅在于上面所讲的注释了“pktinfo->ipi6_ifindex = *ifindex;”以及“smsghdr.msg_controllen = sizeof (cmsgbuf);”这两行。因此怀疑是这里出了问题。
请各位大侠帮小弟看看问题出了哪里?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表