📄 ip_conntrack_proto_sctp.c
字号:
return -1; /* Check the verification tag (Sec 8.5) */ if (!test_bit(SCTP_CID_INIT, (void *)map) && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map) && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map) && !test_bit(SCTP_CID_ABORT, (void *)map) && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map) && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) { DEBUGP("Verification tag check failed\n"); return -1; } oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX; for_each_sctp_chunk (skb, sch, _sch, offset, count) { write_lock_bh(&sctp_lock); /* Special cases of Verification tag check (Sec 8.5.1) */ if (sch->type == SCTP_CID_INIT) { /* Sec 8.5.1 (A) */ if (sh->vtag != 0) { write_unlock_bh(&sctp_lock); return -1; } } else if (sch->type == SCTP_CID_ABORT) { /* Sec 8.5.1 (B) */ if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)]) && !(sh->vtag == conntrack->proto.sctp.vtag [1 - CTINFO2DIR(ctinfo)])) { write_unlock_bh(&sctp_lock); return -1; } } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) { /* Sec 8.5.1 (C) */ if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)]) && !(sh->vtag == conntrack->proto.sctp.vtag [1 - CTINFO2DIR(ctinfo)] && (sch->flags & 1))) { write_unlock_bh(&sctp_lock); return -1; } } else if (sch->type == SCTP_CID_COOKIE_ECHO) { /* Sec 8.5.1 (D) */ if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) { write_unlock_bh(&sctp_lock); return -1; } } oldsctpstate = conntrack->proto.sctp.state; newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch->type); /* Invalid */ if (newconntrack == SCTP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n", CTINFO2DIR(ctinfo), sch->type, oldsctpstate); write_unlock_bh(&sctp_lock); return -1; } /* If it is an INIT or an INIT ACK note down the vtag */ if (sch->type == SCTP_CID_INIT || sch->type == SCTP_CID_INIT_ACK) { sctp_inithdr_t _inithdr, *ih; ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t), sizeof(_inithdr), &_inithdr); if (ih == NULL) { write_unlock_bh(&sctp_lock); return -1; } DEBUGP("Setting vtag %x for dir %d\n", ih->init_tag, !CTINFO2DIR(ctinfo)); conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag; } conntrack->proto.sctp.state = newconntrack; if (oldsctpstate != newconntrack) ip_conntrack_event_cache(IPCT_PROTOINFO, skb); write_unlock_bh(&sctp_lock); } ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]); if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY && newconntrack == SCTP_CONNTRACK_ESTABLISHED) { DEBUGP("Setting assured bit\n"); set_bit(IPS_ASSURED_BIT, &conntrack->status); ip_conntrack_event_cache(IPCT_STATUS, skb); } return NF_ACCEPT;}/* Called when a new connection for this protocol found. */static int sctp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb){ enum sctp_conntrack newconntrack; struct iphdr *iph = skb->nh.iph; sctp_sctphdr_t _sctph, *sh; sctp_chunkhdr_t _sch, *sch; u_int32_t offset, count; char map[256 / sizeof (char)] = {0}; DEBUGP(__FUNCTION__); DEBUGP("\n"); sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph); if (sh == NULL) return 0; if (do_basic_checks(conntrack, skb, map) != 0) return 0; /* If an OOTB packet has any of these chunks discard (Sec 8.4) */ if ((test_bit (SCTP_CID_ABORT, (void *)map)) || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)) || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) { return 0; } newconntrack = SCTP_CONNTRACK_MAX; for_each_sctp_chunk (skb, sch, _sch, offset, count) { /* Don't need lock here: this conntrack not in circulation yet */ newconntrack = new_state (IP_CT_DIR_ORIGINAL, SCTP_CONNTRACK_NONE, sch->type); /* Invalid: delete conntrack */ if (newconntrack == SCTP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_sctp: invalid new deleting.\n"); return 0; } /* Copy the vtag into the state info */ if (sch->type == SCTP_CID_INIT) { if (sh->vtag == 0) { sctp_inithdr_t _inithdr, *ih; ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t), sizeof(_inithdr), &_inithdr); if (ih == NULL) return 0; DEBUGP("Setting vtag %x for new conn\n", ih->init_tag); conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = ih->init_tag; } else { /* Sec 8.5.1 (A) */ return 0; } } /* If it is a shutdown ack OOTB packet, we expect a return shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ else { DEBUGP("Setting vtag %x for new conn OOTB\n", sh->vtag); conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; } conntrack->proto.sctp.state = newconntrack; } return 1;}static struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { .proto = IPPROTO_SCTP, .name = "sctp", .pkt_to_tuple = sctp_pkt_to_tuple, .invert_tuple = sctp_invert_tuple, .print_tuple = sctp_print_tuple, .print_conntrack = sctp_print_conntrack, .packet = sctp_packet, .new = sctp_new, .destroy = NULL, .me = THIS_MODULE,#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr, .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,#endif};#ifdef CONFIG_SYSCTLstatic ctl_table ip_ct_sysctl_table[] = { { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED, .procname = "ip_conntrack_sctp_timeout_closed", .data = &ip_ct_sctp_timeout_closed, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT, .procname = "ip_conntrack_sctp_timeout_cookie_wait", .data = &ip_ct_sctp_timeout_cookie_wait, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED, .procname = "ip_conntrack_sctp_timeout_cookie_echoed", .data = &ip_ct_sctp_timeout_cookie_echoed, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED, .procname = "ip_conntrack_sctp_timeout_established", .data = &ip_ct_sctp_timeout_established, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT, .procname = "ip_conntrack_sctp_timeout_shutdown_sent", .data = &ip_ct_sctp_timeout_shutdown_sent, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD, .procname = "ip_conntrack_sctp_timeout_shutdown_recd", .data = &ip_ct_sctp_timeout_shutdown_recd, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT, .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent", .data = &ip_ct_sctp_timeout_shutdown_ack_sent, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, }, { .ctl_name = 0 }};static ctl_table ip_ct_netfilter_table[] = { { .ctl_name = NET_IPV4_NETFILTER, .procname = "netfilter", .mode = 0555, .child = ip_ct_sysctl_table, }, { .ctl_name = 0 }};static ctl_table ip_ct_ipv4_table[] = { { .ctl_name = NET_IPV4, .procname = "ipv4", .mode = 0555, .child = ip_ct_netfilter_table, }, { .ctl_name = 0 }};static ctl_table ip_ct_net_table[] = { { .ctl_name = CTL_NET, .procname = "net", .mode = 0555, .child = ip_ct_ipv4_table, }, { .ctl_name = 0 }};static struct ctl_table_header *ip_ct_sysctl_header;#endifstatic int __init init(void){ int ret; ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp); if (ret) { printk("ip_conntrack_proto_sctp: protocol register failed\n"); goto out; }#ifdef CONFIG_SYSCTL ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0); if (ip_ct_sysctl_header == NULL) { ret = -ENOMEM; printk("ip_conntrack_proto_sctp: can't register to sysctl.\n"); goto cleanup; }#endif return ret;#ifdef CONFIG_SYSCTL cleanup: ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);#endif out: DEBUGP("SCTP conntrack module loading %s\n", ret ? "failed": "succeeded"); return ret;}static void __exit fini(void){ ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);#ifdef CONFIG_SYSCTL unregister_sysctl_table(ip_ct_sysctl_header);#endif DEBUGP("SCTP conntrack module unloaded\n");}module_init(init);module_exit(fini);MODULE_LICENSE("GPL");MODULE_AUTHOR("Kiran Kumar Immidi");MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -