Chinaunix首页 | 论坛 | 博客
  • 博客访问: 745104
  • 博文数量: 215
  • 博客积分: 291
  • 博客等级: 二等列兵
  • 技术积分: 1031
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-12 18:17
文章分类

全部博文(215)

文章存档

2016年(16)

2015年(16)

2014年(123)

2013年(60)

分类: 嵌入式

2013-09-25 11:41:10

背景:
    我们这个项目需要做软件的网络地址转换NAT,由于是嵌入式产品,且只需要操作NAT表,且SDK中没有提供NAT相关的库。
    故没有考虑使用现成的库,该用直接使用socket接口操作kernel的NAT表。
     
    socketId = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    getsockopt(g_IptableSocketId, IPPROTO_IP, IPT_SO_GET_REVISION_MATCH, &g_stUdpMatchRevision, &dwOptLen);
     
现象:
   程序交叉编译后,下到目标板运行时,上述的getsockopt返回失败,errno=92.   why?
    
原因分析:
   1.当socket()创建socket时,
   SYSCALL_DEFINE3(socket) --->sock_create()--->__sock_create()--(AF_INET)-> inet_create()
    
   inet_create()
   {
         //关注该函数所挂载在socket上的ops和prot。在我的程序里,这里挂载的分别是inet_sockraw_ops和raw_prot
   }
    
   2.当getsockopt()时,
   SYSCALL_DEFINE5(getsockopt)--->sock_common_getsockopt()--->raw_getsockopt()
    
   static int raw_getsockopt(struct sock *sk, int level, int optname,
              char __user *optval, int __user *optlen)
    {
        if (level != SOL_RAW)
            return ip_getsockopt(sk, level, optname, optval, optlen);
        return do_raw_getsockopt(sk, level, optname, optval, optlen);
    }
    
    我们的level是IPROTO_IP,故这里进入ip_getsockopt()
    
    int ip_getsockopt(struct sock *sk, int level,
          int optname, char __user *optval, int __user *optlen)
 {
     int err;
 
     err = do_ip_getsockopt(sk, level, optname, optval, optlen);
 #ifdef CONFIG_NETFILTER
     /* we need to exclude all possible ENOPROTOOPTs except default case */
     if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
            !ip_mroute_opt(optname)) {
        int len;
 
        if (get_user(len, optlen))
            return -EFAULT;
 
        lock_sock(sk);
        err = nf_getsockopt(sk, PF_INET, optname, optval,
                &len);
        release_sock(sk);
        if (err >= 0)
            err = put_user(len, optlen);
        return err;
      }
  #endif
    return err;
 }
 
 函数do_ip_getsockopt()的switch...case中没有我们的IPT_SO_GET_REVISION_MATCH,故进入default后会返回-ENOPROTOOPT(92)。
 假设我们打开了CONFIG_NETFILTER,则会进入nf_getsockopt()去处理我们的IPT_SO_GET_REVISION_MATCH请求。
 
 所以,基本上已经看出来了问题所在。很可能就是kernel的CONFIG_NETFILTER没有配置。
 于是返回linux kernel source中查看.config文件。果然,这个CONFIG_NETFILTER没有配置。
 
 至此,该问题已经解决。
阅读(1156) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~