免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2392 | 回复: 0
打印 上一主题 下一主题

android系统native层的getsockopt调用有错吗 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-09 23:06 |只看该作者 |倒序浏览
本帖最后由 wliang511 于 2011-11-09 23:10 编辑

纠结了很多天了,跟一个问题跟到这里,但是觉得google又不可能犯这么低级的错误...请大家指出我愚蠢的地方吧

android 2.2 froyo版本

在froyo\dalvik\libcore\luni\src\main\native\org_apache_harmony_luni_platform_OSNetworkSystem.cpp中(这里只贴出相关的2个case语句):
我们暂时只看IPV4的部分:
    在case  JAVASOCKOPT_IP_MULTICAST_IF中,getsockopt(...,....,...,&sockval,...)语句之后有sockval.ss_family的引用,因此这个sockval至少是
           一个大小大于4个字节的结构体,从紧接的代码socketAddressToInetAddress()中可以看出内核应该返回的sockval为struct sockaddr_in类型

  在case JAVASOCKOPT_IP_MULTICAST_IF2,AF_INET时,很明显getsockopt(...,....,...,&sockval,...)返回的sockval类型必须是struct ip_mreqn类型

但是从内核代码\kernel\net\ipv4\ip_sockglue.c中
   case IP_MULTICAST_IF中可以看到,getsockopt明明只支持返回类型为struct in_addr的结构体

这,问题究竟在哪里呢?


froyo\dalvik\libcore\luni\src\main\native\org_apache_harmony_luni_platform_OSNetworkSystem.cpp:

  1. static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
  2.         jobject fileDescriptor, jint anOption) {
  3.     // LOGD("ENTER getSocketOptionImpl");

  4.     int intValue = 0;
  5.     socklen_t intSize = sizeof(int);
  6.     int result;
  7.     struct sockaddr_storage sockVal;
  8.     socklen_t sockSize = sizeof(sockVal);

  9.     int handle;
  10.     if (!jniGetFd(env, fileDescriptor, handle)) {
  11.         return 0;
  12.     }

  13.     switch ((int) anOption & 0xffff) {
  14.         case JAVASOCKOPT_IP_MULTICAST_IF: {
  15.             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
  16.                 return NULL;
  17.             }
  18.             result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
  19.                 &sockVal, &sockSize);
  20.             if (result == -1) {
  21.                 jniThrowSocketException(env, errno);
  22.                 return NULL;
  23.             }
  24.             if (sockVal.ss_family != AF_INET) {
  25.                 // Java expects an AF_INET INADDR_ANY, but Linux just returns AF_UNSPEC.
  26.                 jbyteArray inAddrAny = env->NewByteArray(4); // { 0, 0, 0, 0 }
  27.                 return byteArrayToInetAddress(env, inAddrAny);
  28.             }
  29.             return socketAddressToInetAddress(env, &sockVal);
  30.         }

  31.         case JAVASOCKOPT_IP_MULTICAST_IF2: {
  32.             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
  33.                 return NULL;
  34.             }
  35.             struct ip_mreqn multicastRequest;
  36.             int interfaceIndex = 0;
  37.             socklen_t optionLength;
  38.             int addressFamily = getSocketAddressFamily(handle);
  39.             switch (addressFamily) {
  40.                 case AF_INET:
  41.                     optionLength = sizeof(multicastRequest);
  42.                     result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
  43.                                         &multicastRequest, &optionLength);
  44.                     if (result == 0)
  45.                         interfaceIndex = multicastRequest.imr_ifindex;
  46.                     break;
  47.                 case AF_INET6:
  48.                     optionLength = sizeof(interfaceIndex);
  49.                     result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
  50.                                         &interfaceIndex, &optionLength);
  51.                     break;
  52.                 default:
  53.                     jniThrowSocketException(env, EAFNOSUPPORT);
  54.                     return NULL;
  55.             }

  56.             if (0 != result) {
  57.                 jniThrowSocketException(env, errno);
  58.                 return NULL;
  59.             }
  60.             return newJavaLangInteger(env, interfaceIndex);
  61.         }
  62.     }
  63. }
复制代码
但是从内核代码\kernel\net\ipv4\ip_sockglue.c中
case IP_MULTICAST_IF中可以看到,getsockopt明明只支持返回类型为struct in_addr的结构体


kernel\net\ipv4\ip_sockglue.c:


  1. /*
  2. *        Get the options. Note for future reference. The GET of IP options gets the
  3. *        _received_ ones. The set sets the _sent_ ones.
  4. */

  5. static int do_ip_getsockopt(struct sock *sk, int level, int optname,
  6.                             char __user *optval, int __user *optlen)
  7. {
  8.         struct inet_sock *inet = inet_sk(sk);
  9.         int val;
  10.         int len;

  11.         if (level != SOL_IP)
  12.                 return -EOPNOTSUPP;

  13.         if (ip_mroute_opt(optname))
  14.                 return ip_mroute_getsockopt(sk,optname,optval,optlen);

  15.         if (get_user(len,optlen))
  16.                 return -EFAULT;
  17.         if (len < 0)
  18.                 return -EINVAL;

  19.         lock_sock(sk);

  20.         switch (optname) {

  21.               case IP_MULTICAST_IF:
  22.               {
  23.                 struct in_addr addr;
  24.                 len = min_t(unsigned int, len, sizeof(struct in_addr));
  25.                 addr.s_addr = inet->mc_addr;
  26.                 release_sock(sk);

  27.                 if (put_user(len, optlen))
  28.                         return -EFAULT;
  29.                 if (copy_to_user(optval, &addr, len))
  30.                         return -EFAULT;
  31.                 return 0;
  32.               }
  33.                 }
  34. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP