首页 > 系统相关 >Linux创建socket

Linux创建socket

时间:2023-06-01 10:35:50浏览次数:41  
标签:protocol socket 创建 prot sk INET Linux answer inet

static const struct net_proto_family inet_family_ops = {
.family = PF_INET,
.create = inet_create,
.owner  = THIS_MODULE,
 }; /*
  * Create an inet socket.
  */


 static int inet_create(struct net *net, struct socket *sock, int protocol,
      int kern)
 {
struct sock *sk;
struct inet_protosw *answer;
struct inet_sock *inet;
struct proto *answer_prot;
unsigned char answer_flags;
int try_loading_module = 0;
int err;


if (protocol < 0 || protocol >= IPPROTO_MAX)
return -EINVAL;


sock->state = SS_UNCONNECTED;


/* Look for the requested type/protocol pair. */
 lookup_protocol:
err = -ESOCKTNOSUPPORT;
rcu_read_lock();
list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {


err = 0;
/* Check the non-wild match. */
if (protocol == answer->protocol) {
if (protocol != IPPROTO_IP)
break;
} else {
/* Check for the two wild cases. */
if (IPPROTO_IP == protocol) {
protocol = answer->protocol;
break;
}
if (IPPROTO_IP == answer->protocol)
break;
}
err = -EPROTONOSUPPORT;
}


if (unlikely(err)) {
if (try_loading_module < 2) {
rcu_read_unlock();
/*
* Be more specific, e.g. net-pf-2-proto-132-type-1
* (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM)
*/
if (++try_loading_module == 1)
request_module("net-pf-%d-proto-%d-type-%d",
      PF_INET, protocol, sock->type);
/*
* Fall back to generic, e.g. net-pf-2-proto-132
* (net-pf-PF_INET-proto-IPPROTO_SCTP)
*/
else
request_module("net-pf-%d-proto-%d",
      PF_INET, protocol);
goto lookup_protocol;
} else
goto out_rcu_unlock;
}


err = -EPERM;
if (sock->type == SOCK_RAW && !kern &&
   !ns_capable(net->user_ns, CAP_NET_RAW))
goto out_rcu_unlock;


sock->ops = answer->ops;
answer_prot = answer->prot;
answer_flags = answer->flags;
rcu_read_unlock();


WARN_ON(!answer_prot->slab);


err = -ENOBUFS;
sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, kern);
if (!sk)
goto out;


err = 0;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = SK_CAN_REUSE;


inet = inet_sk(sk);
inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;


inet->nodefrag = 0;


if (SOCK_RAW == sock->type) {
inet->inet_num = protocol;
if (IPPROTO_RAW == protocol)
inet->hdrincl = 1;
}


if (net->ipv4.sysctl_ip_no_pmtu_disc)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;


inet->inet_id = 0;


sock_init_data(sock, sk);


sk->sk_destruct   = inet_sock_destruct;
sk->sk_protocol   = protocol;
sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;


inet->uc_ttl  = -1;
inet->mc_loop  = 1;
inet->mc_ttl  = 1;
inet->mc_all  = 1;
inet->mc_index = 0;
inet->mc_list  = NULL;
inet->rcv_tos  = 0;


sk_refcnt_debug_inc(sk);


if (inet->inet_num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
* creation time automatically
* shares.
*/
inet->inet_sport = htons(inet->inet_num);
/* Add to protocol hash chains. */
err = sk->sk_prot->hash(sk);
if (err) {
sk_common_release(sk);
goto out;
}
}


if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);
if (err)
sk_common_release(sk);
}
 out:
return err;
 out_rcu_unlock:
rcu_read_unlock();
goto out;
 }
 /* Upon startup we insert all the elements in inetsw_array[] into
  * the linked list inetsw.
  */
 static struct inet_protosw inetsw_array[] =
 {
{
.type =       SOCK_STREAM,
.protocol =   IPPROTO_TCP,
.prot =       &tcp_prot,
.ops =        &inet_stream_ops,
.flags =      INET_PROTOSW_PERMANENT |
     INET_PROTOSW_ICSK,
},


{
.type =       SOCK_DGRAM,
.protocol =   IPPROTO_UDP,
.prot =       &udp_prot,
.ops =        &inet_dgram_ops,
.flags =      INET_PROTOSW_PERMANENT,
        },


        {
.type =       SOCK_DGRAM,
.protocol =   IPPROTO_ICMP,
.prot =       &ping_prot,
.ops =        &inet_dgram_ops,
.flags =      INET_PROTOSW_REUSE,
        },


        {
      .type =       SOCK_RAW,
      .protocol =   IPPROTO_IP, /* wild card */
      .prot =       &raw_prot,
      .ops =        &inet_sockraw_ops,
      .flags =      INET_PROTOSW_REUSE,
        }
 };

标签:protocol,socket,创建,prot,sk,INET,Linux,answer,inet
From: https://blog.51cto.com/u_11860992/6392704

相关文章

  • Linux 内核 net_proto_family
    staticconststructnet_proto_familyinet_family_ops={.family=PF_INET,.create=inet_create,.owner=THIS_MODULE,};(void)sock_register(&inet_family_ops);/***sock_register-addasocketprotocolhandler*@ops:descriptiono......
  • Linux 内核时钟架构之时钟源读取计数
    前面我们讲到,时钟源是给timekeeping使用的,timekeeping会定时更新,这就依赖timekeeping模块需要读取clocksource的计数,计算时间流逝。然后对时间进行叠加,得到当前时间。 ktime_get()--->tk_core.timekeeperclocksource.read()timekeeping_get_ns()--》read()......
  • linux quota命令使用——应用场景 针对不同的用户设置不同的磁盘访问大小
    quota显示磁盘已使用的空间与限制Linuxquota命令语法quota[选项][用户|组群]命令中各选项的含义如表所示。  Linuxquota命令示例显示用户zhangsan的磁盘使用情况和限制[root@rhel~]#su-zhangsan//以用户zhangsan登录系统[zhangsan@rhel~]$quotaDiskquotasforuse......
  • Git分支教程:详解分支创建、合并、删除等操作
    Git是一种强大的分布式版本控制系统,它的分支功能使得团队协作和代码管理变得更加灵活和高效。分支可以让开发人员在不影响主线开发的情况下进行并行开发和实验性工作。本篇博客将详解Git分支的创建、合并、删除等操作,帮助你更好地理解和使用Git的分支功能。分支的基本概念在开......
  • Linux 内核时钟架构之时钟事件设备与tick_device
    每个CPU定义了一个tick_device,其用于对本cpu使用的时钟事件设备跟踪。也就是说,tick_device是有的,但是这里面有没有clock_event_device我们并不清楚,但是内核在启动时候,如果注册clock_event_device设备,那么内核尝试用时钟事件设备与tick_device设备绑定。这样,两则就关联起来了。......
  • Linux 内核时钟架构之时钟事件设备注册
    voidclockevents_register_device(structclock_event_device*dev);voidclockevents_config_and_register(structclock_event_device*dev,u32freq,unsignedlongmin_delta,unsignedlongmax_delta);相关的一个是配置函数voidclocke......
  • Linux 内核时钟之timer初始化
    init_timersvoid__initinit_timers(void){init_timer_cpus();init_timer_stats();open_softirq(TIMER_SOFTIRQ,run_timer_softirq);}staticvoid__initinit_timer_cpu(intcpu){structtimer_base*base;inti;for(i=0;i<NR_BASES;i+......
  • 如何在Java中创建数组列表
    为了在Java中存储动态大小的元素,我们使用了ArrayList。每当添加新元素时,它会自动增加其大小。ArrayList实现Java的List接口和Java的Collection的一部分。由于其功能和灵活性,它被广泛使用。ArrayList的关键点An ArrayList是一个可调整大小的数组,也称为动态数组。它根据新元素增加其......
  • Linux 添加redis守护进程
    1、编写启动服务文件 /lib/systemd/system/redis.service[Unit]Description=Theredis-serverProcessManagerDocumentation=https://redis.io/After=network.target[Service]Type=forking#根据自己的redis路径启动和停止ExecStart=/usr/local/redis/bin/redis-server/usr/l......
  • 走进Linux编程的大门
    随着Linux的不断普及,使用Linux的人也越来越多了。然而在Linux中如何进行程序设计,用什么样的开发工具好呢?本文就以我初学Linux编程的一点心得体会,和大家共同探讨。在Linux中进行程序设计,可以使用各种编程语言和开发工具,以下是一些常用的方法:1、C/C++编程C/C++是Linux系统中......