Linux内核--网络栈实现分析(六)--应用层获取数据包(上)

发表于:2012-12-28 09:48

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:闫明    来源:51Testing软件测试网采编

  注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析、”(下)“表示分析是从上向下分析。

  上篇博文分析了传输层从网络层获取数据包后将数据包缓存结构sk_buff挂载到特定的sock结构的接收队列中。

  这里接着分析应用程序是如何从传输层获取网络数据包的。应用层要得到传输层的数据包有两种主要的方式:系统调用和文件操作。

  系统调用:

  Linux下用户程序是通过系统调用来从用户态到内核态,调用内核功能来完成相应的服务。

  网络栈的一些功能是通过系统调用sys_socketcall来完成的

  具体的代码在net/socket.c中,该文件中的函数就相当于一个桥梁,在系统调用和内核网络栈之间。

/*
 * System call vectors. Since I (RIB) want to rewrite sockets as streams,
 * we have this level of indirection. Not a lot of overhead, since more of
 * the work is done via read/write/select directly.
 *
 * I'm now expanding this up to a higher level to separate the assorted
 * kernel/user space manipulations and global assumptions from the protocol
 * layers proper - AC.
 */

asmlinkage int sys_socketcall(int call, unsigned long *args)
{
 int er;
 switch(call)
 {
  case SYS_SOCKET:
   er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
   if(er)
    return er;
   return(sock_socket(get_fs_long(args+0),
    get_fs_long(args+1),
    get_fs_long(args+2)));
  case SYS_BIND:
   er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
   if(er)
    return er;
   return(sock_bind(get_fs_long(args+0),
    (struct sockaddr *)get_fs_long(args+1),
    get_fs_long(args+2)));
  case SYS_CONNECT:
   er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
   if(er)
    return er;
   return(sock_connect(get_fs_long(args+0),
    (struct sockaddr *)get_fs_long(args+1),
    get_fs_long(args+2)));
  case SYS_LISTEN:
   er=verify_area(VERIFY_READ, args, 2 * sizeof(long));
   if(er)
    return er;
   return(sock_listen(get_fs_long(args+0),
    get_fs_long(args+1)));
  case SYS_ACCEPT:
   er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
   if(er)
    return er;
   return(sock_accept(get_fs_long(args+0),
    (struct sockaddr *)get_fs_long(args+1),
    (int *)get_fs_long(args+2)));
  case SYS_GETSOCKNAME:
   er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
   if(er)
    return er;
   return(sock_getsockname(get_fs_long(args+0),
    (struct sockaddr *)get_fs_long(args+1),
    (int *)get_fs_long(args+2)));
  case SYS_GETPEERNAME:
   er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
   if(er)
    return er;
   return(sock_getpeername(get_fs_long(args+0),
    (struct sockaddr *)get_fs_long(args+1),
    (int *)get_fs_long(args+2)));
  case SYS_SOCKETPAIR:
   er=verify_area(VERIFY_READ, args, 4 * sizeof(long));
   if(er)
    return er;
   return(sock_socketpair(get_fs_long(args+0),
    get_fs_long(args+1),
    get_fs_long(args+2),
    (unsigned long *)get_fs_long(args+3)));
  case SYS_SEND:
   er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
   if(er)
    return er;
   return(sock_send(get_fs_long(args+0),
    (void *)get_fs_long(args+1),
    get_fs_long(args+2),
    get_fs_long(args+3)));
  case SYS_SENDTO:
   er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
   if(er)
    return er;
   return(sock_sendto(get_fs_long(args+0),
    (void *)get_fs_long(args+1),
    get_fs_long(args+2),
    get_fs_long(args+3),
    (struct sockaddr *)get_fs_long(args+4),
    get_fs_long(args+5)));
  case SYS_RECV:
   er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
   if(er)
    return er;
   return(sock_recv(get_fs_long(args+0),
    (void *)get_fs_long(args+1),
    get_fs_long(args+2),
    get_fs_long(args+3)));
  case SYS_RECVFROM:
   er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
   if(er)
    return er;
   return(sock_recvfrom(get_fs_long(args+0),
    (void *)get_fs_long(args+1),
    get_fs_long(args+2),
    get_fs_long(args+3),
    (struct sockaddr *)get_fs_long(args+4),
    (int *)get_fs_long(args+5)));
  case SYS_SHUTDOWN:
   er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long));
   if(er)
    return er;
   return(sock_shutdown(get_fs_long(args+0),
    get_fs_long(args+1)));
  case SYS_SETSOCKOPT:
   er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
   if(er)
    return er;
   return(sock_setsockopt(get_fs_long(args+0),
    get_fs_long(args+1),
    get_fs_long(args+2),
    (char *)get_fs_long(args+3),
    get_fs_long(args+4)));
  case SYS_GETSOCKOPT:
   er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
   if(er)
    return er;
   return(sock_getsockopt(get_fs_long(args+0),
    get_fs_long(args+1),
    get_fs_long(args+2),
    (char *)get_fs_long(args+3),
    (int *)get_fs_long(args+4)));
  default:
   return(-EINVAL);
 }
}

41/41234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号