📄 protocol.c
字号:
/* Socket operations. */struct proto_ops inet_seqpacket_ops = { .family = PF_INET, .owner = THIS_MODULE, .release = inet_release, /* Needs to be wrapped... */ .bind = inet_bind, .connect = inet_dgram_connect, .socketpair = sock_no_socketpair, .accept = inet_accept, .getname = inet_getname, /* Semantics are different. */ .poll = sctp_poll, .ioctl = inet_ioctl, .listen = sctp_inet_listen, .shutdown = inet_shutdown, /* Looks harmless. */ .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem. */ .getsockopt = sock_common_getsockopt, .sendmsg = inet_sendmsg, .recvmsg = sock_common_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage,};/* Registration with AF_INET family. */static struct inet_protosw sctp_seqpacket_protosw = { .type = SOCK_SEQPACKET, .protocol = IPPROTO_SCTP, .prot = &sctp_prot, .ops = &inet_seqpacket_ops, .capability = -1, .no_check = 0, .flags = SCTP_PROTOSW_FLAG};static struct inet_protosw sctp_stream_protosw = { .type = SOCK_STREAM, .protocol = IPPROTO_SCTP, .prot = &sctp_prot, .ops = &inet_seqpacket_ops, .capability = -1, .no_check = 0, .flags = SCTP_PROTOSW_FLAG};/* Register with IP layer. */static struct net_protocol sctp_protocol = { .handler = sctp_rcv, .err_handler = sctp_v4_err, .no_policy = 1,};/* IPv4 address related functions. */struct sctp_af sctp_ipv4_specific = { .sctp_xmit = sctp_v4_xmit, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, .get_dst = sctp_v4_get_dst, .get_saddr = sctp_v4_get_saddr, .copy_addrlist = sctp_v4_copy_addrlist, .from_skb = sctp_v4_from_skb, .from_sk = sctp_v4_from_sk, .to_sk_saddr = sctp_v4_to_sk_saddr, .to_sk_daddr = sctp_v4_to_sk_daddr, .from_addr_param= sctp_v4_from_addr_param, .to_addr_param = sctp_v4_to_addr_param, .dst_saddr = sctp_v4_dst_saddr, .cmp_addr = sctp_v4_cmp_addr, .addr_valid = sctp_v4_addr_valid, .inaddr_any = sctp_v4_inaddr_any, .is_any = sctp_v4_is_any, .available = sctp_v4_available, .scope = sctp_v4_scope, .skb_iif = sctp_v4_skb_iif, .is_ce = sctp_v4_is_ce, .seq_dump_addr = sctp_v4_seq_dump_addr, .net_header_len = sizeof(struct iphdr), .sockaddr_len = sizeof(struct sockaddr_in), .sa_family = AF_INET,};struct sctp_pf *sctp_get_pf_specific(sa_family_t family) { switch (family) { case PF_INET: return sctp_pf_inet_specific; case PF_INET6: return sctp_pf_inet6_specific; default: return NULL; }}/* Register the PF specific function table. */int sctp_register_pf(struct sctp_pf *pf, sa_family_t family){ switch (family) { case PF_INET: if (sctp_pf_inet_specific) return 0; sctp_pf_inet_specific = pf; break; case PF_INET6: if (sctp_pf_inet6_specific) return 0; sctp_pf_inet6_specific = pf; break; default: return 0; } return 1;}static int __init init_sctp_mibs(void){ sctp_statistics[0] = alloc_percpu(struct sctp_mib); if (!sctp_statistics[0]) return -ENOMEM; sctp_statistics[1] = alloc_percpu(struct sctp_mib); if (!sctp_statistics[1]) { free_percpu(sctp_statistics[0]); return -ENOMEM; } return 0;}static void cleanup_sctp_mibs(void){ free_percpu(sctp_statistics[0]); free_percpu(sctp_statistics[1]);}/* Initialize the universe into something sensible. */__init int sctp_init(void){ int i; int status = -EINVAL; unsigned long goal; int order; /* SCTP_DEBUG sanity check. */ if (!sctp_sanity_check()) goto out; status = sk_alloc_slab(&sctp_prot, "sctp_sock"); if (status) goto out; /* Add SCTP to inet_protos hash table. */ status = -EAGAIN; if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) goto err_add_protocol; /* Add SCTP(TCP and UDP style) to inetsw linked list. */ inet_register_protosw(&sctp_seqpacket_protosw); inet_register_protosw(&sctp_stream_protosw); /* Allocate a cache pools. */ status = -ENOBUFS; sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", sizeof(struct sctp_bind_bucket), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!sctp_bucket_cachep) goto err_bucket_cachep; sctp_chunk_cachep = kmem_cache_create("sctp_chunk", sizeof(struct sctp_chunk), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!sctp_chunk_cachep) goto err_chunk_cachep; /* Allocate and initialise sctp mibs. */ status = init_sctp_mibs(); if (status) goto err_init_mibs; /* Initialize proc fs directory. */ status = sctp_proc_init(); if (status) goto err_init_proc; /* Initialize object count debugging. */ sctp_dbg_objcnt_init(); /* Initialize the SCTP specific PF functions. */ sctp_register_pf(&sctp_pf_inet, PF_INET); /* * 14. Suggested SCTP Protocol Parameter Values */ /* The following protocol parameters are RECOMMENDED: */ /* RTO.Initial - 3 seconds */ sctp_rto_initial = SCTP_RTO_INITIAL; /* RTO.Min - 1 second */ sctp_rto_min = SCTP_RTO_MIN; /* RTO.Max - 60 seconds */ sctp_rto_max = SCTP_RTO_MAX; /* RTO.Alpha - 1/8 */ sctp_rto_alpha = SCTP_RTO_ALPHA; /* RTO.Beta - 1/4 */ sctp_rto_beta = SCTP_RTO_BETA; /* Valid.Cookie.Life - 60 seconds */ sctp_valid_cookie_life = 60 * HZ; /* Whether Cookie Preservative is enabled(1) or not(0) */ sctp_cookie_preserve_enable = 1; /* Max.Burst - 4 */ sctp_max_burst = SCTP_MAX_BURST; /* Association.Max.Retrans - 10 attempts * Path.Max.Retrans - 5 attempts (per destination address) * Max.Init.Retransmits - 8 attempts */ sctp_max_retrans_association = 10; sctp_max_retrans_path = 5; sctp_max_retrans_init = 8; /* HB.interval - 30 seconds */ sctp_hb_interval = 30 * HZ; /* Implementation specific variables. */ /* Initialize default stream count setup information. */ sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; /* Initialize handle used for association ids. */ idr_init(&sctp_assocs_id); /* Size and allocate the association hash table. * The methodology is similar to that of the tcp hash tables. */ if (num_physpages >= (128 * 1024)) goal = num_physpages >> (22 - PAGE_SHIFT); else goal = num_physpages >> (24 - PAGE_SHIFT); for (order = 0; (1UL << order) < goal; order++) ; do { sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE / sizeof(struct sctp_hashbucket); if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0) continue; sctp_assoc_hashtable = (struct sctp_hashbucket *) __get_free_pages(GFP_ATOMIC, order); } while (!sctp_assoc_hashtable && --order > 0); if (!sctp_assoc_hashtable) { printk(KERN_ERR "SCTP: Failed association hash alloc.\n"); status = -ENOMEM; goto err_ahash_alloc; } for (i = 0; i < sctp_assoc_hashsize; i++) { sctp_assoc_hashtable[i].lock = RW_LOCK_UNLOCKED; sctp_assoc_hashtable[i].chain = NULL; } /* Allocate and initialize the endpoint hash table. */ sctp_ep_hashsize = 64; sctp_ep_hashtable = (struct sctp_hashbucket *) kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL); if (!sctp_ep_hashtable) { printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); status = -ENOMEM; goto err_ehash_alloc; } for (i = 0; i < sctp_ep_hashsize; i++) { sctp_ep_hashtable[i].lock = RW_LOCK_UNLOCKED; sctp_ep_hashtable[i].chain = NULL; } /* Allocate and initialize the SCTP port hash table. */ do { sctp_port_hashsize = (1UL << order) * PAGE_SIZE / sizeof(struct sctp_bind_hashbucket); if ((sctp_port_hashsize > (64 * 1024)) && order > 0) continue; sctp_port_hashtable = (struct sctp_bind_hashbucket *) __get_free_pages(GFP_ATOMIC, order); } while (!sctp_port_hashtable && --order > 0); if (!sctp_port_hashtable) { printk(KERN_ERR "SCTP: Failed bind hash alloc."); status = -ENOMEM; goto err_bhash_alloc; } for (i = 0; i < sctp_port_hashsize; i++) { sctp_port_hashtable[i].lock = SPIN_LOCK_UNLOCKED; sctp_port_hashtable[i].chain = NULL; } sctp_port_alloc_lock = SPIN_LOCK_UNLOCKED; sctp_port_rover = sysctl_local_port_range[0] - 1; printk(KERN_INFO "SCTP: Hash tables configured " "(established %d bind %d)\n", sctp_assoc_hashsize, sctp_port_hashsize); /* Disable ADDIP by default. */ sctp_addip_enable = 0; /* Enable PR-SCTP by default. */ sctp_prsctp_enable = 1; sctp_sysctl_register(); INIT_LIST_HEAD(&sctp_address_families); sctp_register_af(&sctp_ipv4_specific); status = sctp_v6_init(); if (status) goto err_v6_init; /* Initialize the control inode/socket for handling OOTB packets. */ if ((status = sctp_ctl_sock_init())) { printk (KERN_ERR "SCTP: Failed to initialize the SCTP control sock.\n"); goto err_ctl_sock_init; } /* Initialize the local address list. */ INIT_LIST_HEAD(&sctp_local_addr_list); sctp_local_addr_lock = SPIN_LOCK_UNLOCKED; /* Register notifier for inet address additions/deletions. */ register_inetaddr_notifier(&sctp_inetaddr_notifier); sctp_get_local_addr_list(); __unsafe(THIS_MODULE); status = 0;out: return status;err_add_protocol: sk_free_slab(&sctp_prot);err_ctl_sock_init: sctp_v6_exit();err_v6_init: sctp_sysctl_unregister(); list_del(&sctp_ipv4_specific.list); free_pages((unsigned long)sctp_port_hashtable, get_order(sctp_port_hashsize * sizeof(struct sctp_bind_hashbucket)));err_bhash_alloc: kfree(sctp_ep_hashtable);err_ehash_alloc: free_pages((unsigned long)sctp_assoc_hashtable, get_order(sctp_assoc_hashsize * sizeof(struct sctp_hashbucket)));err_ahash_alloc: sctp_dbg_objcnt_exit();err_init_proc: sctp_proc_exit(); cleanup_sctp_mibs();err_init_mibs: kmem_cache_destroy(sctp_chunk_cachep);err_chunk_cachep: kmem_cache_destroy(sctp_bucket_cachep);err_bucket_cachep: inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_stream_protosw); goto out;}/* Exit handler for the SCTP protocol. */__exit void sctp_exit(void){ /* BUG. This should probably do something useful like clean * up all the remaining associations and all that memory. */ /* Unregister notifier for inet address additions/deletions. */ unregister_inetaddr_notifier(&sctp_inetaddr_notifier); /* Free the local address list. */ sctp_free_local_addr_list(); /* Free the control endpoint. */ sock_release(sctp_ctl_socket); sctp_v6_exit(); sctp_sysctl_unregister(); list_del(&sctp_ipv4_specific.list); free_pages((unsigned long)sctp_assoc_hashtable, get_order(sctp_assoc_hashsize * sizeof(struct sctp_hashbucket))); kfree(sctp_ep_hashtable); free_pages((unsigned long)sctp_port_hashtable, get_order(sctp_port_hashsize * sizeof(struct sctp_bind_hashbucket))); kmem_cache_destroy(sctp_chunk_cachep); kmem_cache_destroy(sctp_bucket_cachep); sctp_dbg_objcnt_exit(); sctp_proc_exit(); cleanup_sctp_mibs(); inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_stream_protosw); sk_free_slab(&sctp_prot);}module_init(sctp_init);module_exit(sctp_exit);MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -