Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: Add helper array register/unregister functions

Add nf_ct_helper_init(), nf_conntrack_helpers_register() and
nf_conntrack_helpers_unregister() functions to avoid repetitive
opencoded initialization in helpers.

This patch keeps an id parameter for nf_ct_helper_init() not to break
helper matching by name that has been inconsistently exposed to
userspace through ports, eg. ftp-2121, and through an incremental id,
eg. tftp-1.

Signed-off-by: Gao Feng <fgao@ikuai8.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Gao Feng and committed by
Pablo Neira Ayuso
82de0be6 590025a2

+162 -178
+15
include/net/netfilter/nf_conntrack_helper.h
··· 58 58 struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name, 59 59 u16 l3num, 60 60 u8 protonum); 61 + void nf_ct_helper_init(struct nf_conntrack_helper *helper, 62 + u16 l3num, u16 protonum, const char *name, 63 + u16 default_port, u16 spec_port, u32 id, 64 + const struct nf_conntrack_expect_policy *exp_pol, 65 + u32 expect_class_max, u32 data_len, 66 + int (*help)(struct sk_buff *skb, unsigned int protoff, 67 + struct nf_conn *ct, 68 + enum ip_conntrack_info ctinfo), 69 + int (*from_nlattr)(struct nlattr *attr, 70 + struct nf_conn *ct), 71 + struct module *module); 61 72 62 73 int nf_conntrack_helper_register(struct nf_conntrack_helper *); 63 74 void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); 75 + 76 + int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int); 77 + void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *, 78 + unsigned int); 64 79 65 80 struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, 66 81 struct nf_conntrack_helper *helper,
+17 -39
net/netfilter/nf_conntrack_ftp.c
··· 572 572 return 0; 573 573 } 574 574 575 - static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; 575 + static struct nf_conntrack_helper ftp[MAX_PORTS * 2] __read_mostly; 576 576 577 577 static const struct nf_conntrack_expect_policy ftp_exp_policy = { 578 578 .max_expected = 1, ··· 582 582 /* don't make this __exit, since it's called from __init ! */ 583 583 static void nf_conntrack_ftp_fini(void) 584 584 { 585 - int i, j; 586 - for (i = 0; i < ports_c; i++) { 587 - for (j = 0; j < 2; j++) { 588 - if (ftp[i][j].me == NULL) 589 - continue; 590 - 591 - pr_debug("unregistering helper for pf: %d port: %d\n", 592 - ftp[i][j].tuple.src.l3num, ports[i]); 593 - nf_conntrack_helper_unregister(&ftp[i][j]); 594 - } 595 - } 596 - 585 + nf_conntrack_helpers_unregister(ftp, ports_c * 2); 597 586 kfree(ftp_buffer); 598 587 } 599 588 600 589 static int __init nf_conntrack_ftp_init(void) 601 590 { 602 - int i, j = -1, ret = 0; 591 + int i, ret = 0; 603 592 604 593 ftp_buffer = kmalloc(65536, GFP_KERNEL); 605 594 if (!ftp_buffer) ··· 600 611 /* FIXME should be configurable whether IPv4 and IPv6 FTP connections 601 612 are tracked or not - YK */ 602 613 for (i = 0; i < ports_c; i++) { 603 - ftp[i][0].tuple.src.l3num = PF_INET; 604 - ftp[i][1].tuple.src.l3num = PF_INET6; 605 - for (j = 0; j < 2; j++) { 606 - ftp[i][j].data_len = sizeof(struct nf_ct_ftp_master); 607 - ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]); 608 - ftp[i][j].tuple.dst.protonum = IPPROTO_TCP; 609 - ftp[i][j].expect_policy = &ftp_exp_policy; 610 - ftp[i][j].me = THIS_MODULE; 611 - ftp[i][j].help = help; 612 - ftp[i][j].from_nlattr = nf_ct_ftp_from_nlattr; 613 - if (ports[i] == FTP_PORT) 614 - sprintf(ftp[i][j].name, "ftp"); 615 - else 616 - sprintf(ftp[i][j].name, "ftp-%d", ports[i]); 614 + nf_ct_helper_init(&ftp[2 * i], AF_INET, IPPROTO_TCP, "ftp", 615 + FTP_PORT, ports[i], ports[i], &ftp_exp_policy, 616 + 0, sizeof(struct nf_ct_ftp_master), help, 617 + nf_ct_ftp_from_nlattr, THIS_MODULE); 618 + nf_ct_helper_init(&ftp[2 * i + 1], AF_INET6, IPPROTO_TCP, "ftp", 619 + FTP_PORT, ports[i], ports[i], &ftp_exp_policy, 620 + 0, sizeof(struct nf_ct_ftp_master), help, 621 + nf_ct_ftp_from_nlattr, THIS_MODULE); 622 + } 617 623 618 - pr_debug("registering helper for pf: %d port: %d\n", 619 - ftp[i][j].tuple.src.l3num, ports[i]); 620 - ret = nf_conntrack_helper_register(&ftp[i][j]); 621 - if (ret) { 622 - pr_err("failed to register helper for pf: %d port: %d\n", 623 - ftp[i][j].tuple.src.l3num, ports[i]); 624 - ports_c = i; 625 - nf_conntrack_ftp_fini(); 626 - return ret; 627 - } 628 - } 624 + ret = nf_conntrack_helpers_register(ftp, ports_c * 2); 625 + if (ret < 0) { 626 + pr_err("failed to register helpers\n"); 627 + kfree(ftp_buffer); 628 + return ret; 629 629 } 630 630 631 631 return 0;
+57
net/netfilter/nf_conntrack_helper.c
··· 465 465 } 466 466 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); 467 467 468 + void nf_ct_helper_init(struct nf_conntrack_helper *helper, 469 + u16 l3num, u16 protonum, const char *name, 470 + u16 default_port, u16 spec_port, u32 id, 471 + const struct nf_conntrack_expect_policy *exp_pol, 472 + u32 expect_class_max, u32 data_len, 473 + int (*help)(struct sk_buff *skb, unsigned int protoff, 474 + struct nf_conn *ct, 475 + enum ip_conntrack_info ctinfo), 476 + int (*from_nlattr)(struct nlattr *attr, 477 + struct nf_conn *ct), 478 + struct module *module) 479 + { 480 + helper->tuple.src.l3num = l3num; 481 + helper->tuple.dst.protonum = protonum; 482 + helper->tuple.src.u.all = htons(spec_port); 483 + helper->expect_policy = exp_pol; 484 + helper->expect_class_max = expect_class_max; 485 + helper->data_len = data_len; 486 + helper->help = help; 487 + helper->from_nlattr = from_nlattr; 488 + helper->me = module; 489 + 490 + if (spec_port == default_port) 491 + snprintf(helper->name, sizeof(helper->name), "%s", name); 492 + else 493 + snprintf(helper->name, sizeof(helper->name), "%s-%u", name, id); 494 + } 495 + EXPORT_SYMBOL_GPL(nf_ct_helper_init); 496 + 497 + int nf_conntrack_helpers_register(struct nf_conntrack_helper *helper, 498 + unsigned int n) 499 + { 500 + unsigned int i; 501 + int err = 0; 502 + 503 + for (i = 0; i < n; i++) { 504 + err = nf_conntrack_helper_register(&helper[i]); 505 + if (err < 0) 506 + goto err; 507 + } 508 + 509 + return err; 510 + err: 511 + if (i > 0) 512 + nf_conntrack_helpers_unregister(helper, i); 513 + return err; 514 + } 515 + EXPORT_SYMBOL_GPL(nf_conntrack_helpers_register); 516 + 517 + void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *helper, 518 + unsigned int n) 519 + { 520 + while (n-- > 0) 521 + nf_conntrack_helper_unregister(&helper[n]); 522 + } 523 + EXPORT_SYMBOL_GPL(nf_conntrack_helpers_unregister); 524 + 468 525 static struct nf_ct_ext_type helper_extend __read_mostly = { 469 526 .len = sizeof(struct nf_conn_help), 470 527 .align = __alignof__(struct nf_conn_help),
+12 -24
net/netfilter/nf_conntrack_irc.c
··· 255 255 ports[ports_c++] = IRC_PORT; 256 256 257 257 for (i = 0; i < ports_c; i++) { 258 - irc[i].tuple.src.l3num = AF_INET; 259 - irc[i].tuple.src.u.tcp.port = htons(ports[i]); 260 - irc[i].tuple.dst.protonum = IPPROTO_TCP; 261 - irc[i].expect_policy = &irc_exp_policy; 262 - irc[i].me = THIS_MODULE; 263 - irc[i].help = help; 264 - 265 - if (ports[i] == IRC_PORT) 266 - sprintf(irc[i].name, "irc"); 267 - else 268 - sprintf(irc[i].name, "irc-%u", i); 269 - 270 - ret = nf_conntrack_helper_register(&irc[i]); 271 - if (ret) { 272 - pr_err("failed to register helper for pf: %u port: %u\n", 273 - irc[i].tuple.src.l3num, ports[i]); 274 - ports_c = i; 275 - nf_conntrack_irc_fini(); 276 - return ret; 277 - } 258 + nf_ct_helper_init(&irc[i], AF_INET, IPPROTO_TCP, "irc", 259 + IRC_PORT, ports[i], i, &irc_exp_policy, 260 + 0, 0, help, NULL, THIS_MODULE); 278 261 } 262 + 263 + ret = nf_conntrack_helpers_register(&irc[0], ports_c); 264 + if (ret) { 265 + pr_err("failed to register helpers\n"); 266 + kfree(irc_buffer); 267 + return ret; 268 + } 269 + 279 270 return 0; 280 271 } 281 272 ··· 274 283 * it is needed by the init function */ 275 284 static void nf_conntrack_irc_fini(void) 276 285 { 277 - int i; 278 - 279 - for (i = 0; i < ports_c; i++) 280 - nf_conntrack_helper_unregister(&irc[i]); 286 + nf_conntrack_helpers_unregister(irc, ports_c); 281 287 kfree(irc_buffer); 282 288 } 283 289
+19 -36
net/netfilter/nf_conntrack_sane.c
··· 166 166 return ret; 167 167 } 168 168 169 - static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly; 169 + static struct nf_conntrack_helper sane[MAX_PORTS * 2] __read_mostly; 170 170 171 171 static const struct nf_conntrack_expect_policy sane_exp_policy = { 172 172 .max_expected = 1, ··· 176 176 /* don't make this __exit, since it's called from __init ! */ 177 177 static void nf_conntrack_sane_fini(void) 178 178 { 179 - int i, j; 180 - 181 - for (i = 0; i < ports_c; i++) { 182 - for (j = 0; j < 2; j++) { 183 - pr_debug("unregistering helper for pf: %d port: %d\n", 184 - sane[i][j].tuple.src.l3num, ports[i]); 185 - nf_conntrack_helper_unregister(&sane[i][j]); 186 - } 187 - } 188 - 179 + nf_conntrack_helpers_unregister(sane, ports_c * 2); 189 180 kfree(sane_buffer); 190 181 } 191 182 192 183 static int __init nf_conntrack_sane_init(void) 193 184 { 194 - int i, j = -1, ret = 0; 185 + int i, ret = 0; 195 186 196 187 sane_buffer = kmalloc(65536, GFP_KERNEL); 197 188 if (!sane_buffer) ··· 194 203 /* FIXME should be configurable whether IPv4 and IPv6 connections 195 204 are tracked or not - YK */ 196 205 for (i = 0; i < ports_c; i++) { 197 - sane[i][0].tuple.src.l3num = PF_INET; 198 - sane[i][1].tuple.src.l3num = PF_INET6; 199 - for (j = 0; j < 2; j++) { 200 - sane[i][j].data_len = sizeof(struct nf_ct_sane_master); 201 - sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); 202 - sane[i][j].tuple.dst.protonum = IPPROTO_TCP; 203 - sane[i][j].expect_policy = &sane_exp_policy; 204 - sane[i][j].me = THIS_MODULE; 205 - sane[i][j].help = help; 206 - if (ports[i] == SANE_PORT) 207 - sprintf(sane[i][j].name, "sane"); 208 - else 209 - sprintf(sane[i][j].name, "sane-%d", ports[i]); 206 + nf_ct_helper_init(&sane[2 * i], AF_INET, IPPROTO_TCP, "sane", 207 + SANE_PORT, ports[i], ports[i], 208 + &sane_exp_policy, 0, 209 + sizeof(struct nf_ct_sane_master), help, NULL, 210 + THIS_MODULE); 211 + nf_ct_helper_init(&sane[2 * i + 1], AF_INET6, IPPROTO_TCP, "sane", 212 + SANE_PORT, ports[i], ports[i], 213 + &sane_exp_policy, 0, 214 + sizeof(struct nf_ct_sane_master), help, NULL, 215 + THIS_MODULE); 216 + } 210 217 211 - pr_debug("registering helper for pf: %d port: %d\n", 212 - sane[i][j].tuple.src.l3num, ports[i]); 213 - ret = nf_conntrack_helper_register(&sane[i][j]); 214 - if (ret) { 215 - pr_err("failed to register helper for pf: %d port: %d\n", 216 - sane[i][j].tuple.src.l3num, ports[i]); 217 - ports_c = i; 218 - nf_conntrack_sane_fini(); 219 - return ret; 220 - } 221 - } 218 + ret = nf_conntrack_helpers_register(sane, ports_c * 2); 219 + if (ret < 0) { 220 + pr_err("failed to register helpers\n"); 221 + kfree(sane_buffer); 222 + return ret; 222 223 } 223 224 224 225 return 0;
+28 -47
net/netfilter/nf_conntrack_sip.c
··· 1589 1589 return process_sip_msg(skb, ct, protoff, dataoff, &dptr, &datalen); 1590 1590 } 1591 1591 1592 - static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; 1592 + static struct nf_conntrack_helper sip[MAX_PORTS * 4] __read_mostly; 1593 1593 1594 1594 static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { 1595 1595 [SIP_EXPECT_SIGNALLING] = { ··· 1616 1616 1617 1617 static void nf_conntrack_sip_fini(void) 1618 1618 { 1619 - int i, j; 1620 - 1621 - for (i = 0; i < ports_c; i++) { 1622 - for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { 1623 - if (sip[i][j].me == NULL) 1624 - continue; 1625 - nf_conntrack_helper_unregister(&sip[i][j]); 1626 - } 1627 - } 1619 + nf_conntrack_helpers_unregister(sip, ports_c * 4); 1628 1620 } 1629 1621 1630 1622 static int __init nf_conntrack_sip_init(void) 1631 1623 { 1632 - int i, j, ret; 1624 + int i, ret; 1633 1625 1634 1626 if (ports_c == 0) 1635 1627 ports[ports_c++] = SIP_PORT; ··· 1629 1637 for (i = 0; i < ports_c; i++) { 1630 1638 memset(&sip[i], 0, sizeof(sip[i])); 1631 1639 1632 - sip[i][0].tuple.src.l3num = AF_INET; 1633 - sip[i][0].tuple.dst.protonum = IPPROTO_UDP; 1634 - sip[i][0].help = sip_help_udp; 1635 - sip[i][1].tuple.src.l3num = AF_INET; 1636 - sip[i][1].tuple.dst.protonum = IPPROTO_TCP; 1637 - sip[i][1].help = sip_help_tcp; 1640 + nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP, "sip", 1641 + SIP_PORT, ports[i], i, sip_exp_policy, 1642 + SIP_EXPECT_MAX, 1643 + sizeof(struct nf_ct_sip_master), sip_help_udp, 1644 + NULL, THIS_MODULE); 1645 + nf_ct_helper_init(&sip[4 * i + 1], AF_INET, IPPROTO_TCP, "sip", 1646 + SIP_PORT, ports[i], i, sip_exp_policy, 1647 + SIP_EXPECT_MAX, 1648 + sizeof(struct nf_ct_sip_master), sip_help_tcp, 1649 + NULL, THIS_MODULE); 1650 + nf_ct_helper_init(&sip[4 * i + 2], AF_INET6, IPPROTO_UDP, "sip", 1651 + SIP_PORT, ports[i], i, sip_exp_policy, 1652 + SIP_EXPECT_MAX, 1653 + sizeof(struct nf_ct_sip_master), sip_help_udp, 1654 + NULL, THIS_MODULE); 1655 + nf_ct_helper_init(&sip[4 * i + 3], AF_INET6, IPPROTO_TCP, "sip", 1656 + SIP_PORT, ports[i], i, sip_exp_policy, 1657 + SIP_EXPECT_MAX, 1658 + sizeof(struct nf_ct_sip_master), sip_help_tcp, 1659 + NULL, THIS_MODULE); 1660 + } 1638 1661 1639 - sip[i][2].tuple.src.l3num = AF_INET6; 1640 - sip[i][2].tuple.dst.protonum = IPPROTO_UDP; 1641 - sip[i][2].help = sip_help_udp; 1642 - sip[i][3].tuple.src.l3num = AF_INET6; 1643 - sip[i][3].tuple.dst.protonum = IPPROTO_TCP; 1644 - sip[i][3].help = sip_help_tcp; 1645 - 1646 - for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { 1647 - sip[i][j].data_len = sizeof(struct nf_ct_sip_master); 1648 - sip[i][j].tuple.src.u.udp.port = htons(ports[i]); 1649 - sip[i][j].expect_policy = sip_exp_policy; 1650 - sip[i][j].expect_class_max = SIP_EXPECT_MAX; 1651 - sip[i][j].me = THIS_MODULE; 1652 - 1653 - if (ports[i] == SIP_PORT) 1654 - sprintf(sip[i][j].name, "sip"); 1655 - else 1656 - sprintf(sip[i][j].name, "sip-%u", i); 1657 - 1658 - pr_debug("port #%u: %u\n", i, ports[i]); 1659 - 1660 - ret = nf_conntrack_helper_register(&sip[i][j]); 1661 - if (ret) { 1662 - pr_err("failed to register helper for pf: %u port: %u\n", 1663 - sip[i][j].tuple.src.l3num, ports[i]); 1664 - ports_c = i; 1665 - nf_conntrack_sip_fini(); 1666 - return ret; 1667 - } 1668 - } 1662 + ret = nf_conntrack_helpers_register(sip, ports_c * 4); 1663 + if (ret < 0) { 1664 + pr_err("failed to register helpers\n"); 1665 + return ret; 1669 1666 } 1670 1667 return 0; 1671 1668 }
+14 -32
net/netfilter/nf_conntrack_tftp.c
··· 97 97 return ret; 98 98 } 99 99 100 - static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly; 100 + static struct nf_conntrack_helper tftp[MAX_PORTS * 2] __read_mostly; 101 101 102 102 static const struct nf_conntrack_expect_policy tftp_exp_policy = { 103 103 .max_expected = 1, ··· 106 106 107 107 static void nf_conntrack_tftp_fini(void) 108 108 { 109 - int i, j; 110 - 111 - for (i = 0; i < ports_c; i++) { 112 - for (j = 0; j < 2; j++) 113 - nf_conntrack_helper_unregister(&tftp[i][j]); 114 - } 109 + nf_conntrack_helpers_unregister(tftp, ports_c * 2); 115 110 } 116 111 117 112 static int __init nf_conntrack_tftp_init(void) 118 113 { 119 - int i, j, ret; 114 + int i, ret; 120 115 121 116 if (ports_c == 0) 122 117 ports[ports_c++] = TFTP_PORT; 123 118 124 119 for (i = 0; i < ports_c; i++) { 125 - memset(&tftp[i], 0, sizeof(tftp[i])); 120 + nf_ct_helper_init(&tftp[2 * i], AF_INET, IPPROTO_UDP, "tftp", 121 + TFTP_PORT, ports[i], i, &tftp_exp_policy, 122 + 0, 0, tftp_help, NULL, THIS_MODULE); 123 + nf_ct_helper_init(&tftp[2 * i + 1], AF_INET6, IPPROTO_UDP, "tftp", 124 + TFTP_PORT, ports[i], i, &tftp_exp_policy, 125 + 0, 0, tftp_help, NULL, THIS_MODULE); 126 + } 126 127 127 - tftp[i][0].tuple.src.l3num = AF_INET; 128 - tftp[i][1].tuple.src.l3num = AF_INET6; 129 - for (j = 0; j < 2; j++) { 130 - tftp[i][j].tuple.dst.protonum = IPPROTO_UDP; 131 - tftp[i][j].tuple.src.u.udp.port = htons(ports[i]); 132 - tftp[i][j].expect_policy = &tftp_exp_policy; 133 - tftp[i][j].me = THIS_MODULE; 134 - tftp[i][j].help = tftp_help; 135 - 136 - if (ports[i] == TFTP_PORT) 137 - sprintf(tftp[i][j].name, "tftp"); 138 - else 139 - sprintf(tftp[i][j].name, "tftp-%u", i); 140 - 141 - ret = nf_conntrack_helper_register(&tftp[i][j]); 142 - if (ret) { 143 - pr_err("failed to register helper for pf: %u port: %u\n", 144 - tftp[i][j].tuple.src.l3num, ports[i]); 145 - ports_c = i; 146 - nf_conntrack_tftp_fini(); 147 - return ret; 148 - } 149 - } 128 + ret = nf_conntrack_helpers_register(tftp, ports_c * 2); 129 + if (ret < 0) { 130 + pr_err("failed to register helpers\n"); 131 + return ret; 150 132 } 151 133 return 0; 152 134 }