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

netfilter: log: nf_log_packet() as real unified interface

Before this patch, the nf_loginfo parameter specified the logging
configuration in case the specified default logger was loaded. This
patch updates the semantics of the nf_loginfo parameter in
nf_log_packet() which now indicates the logger that you explicitly
want to use.

Thus, nf_log_packet() is exposed as an unified interface which
internally routes the log message to the corresponding logger type
by family.

The module dependencies are expressed by the new nf_logger_find_get()
and nf_logger_put() functions which bump the logger module refcount.
Thus, you can not remove logger modules that are used by rules anymore.

Another important effect of this change is that the family specific
module is only loaded when required. Therefore, xt_LOG and nft_log
will just trigger the autoload of the nf_log_{ip,ip6} modules
according to the family.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+73 -41
+6 -14
include/net/netfilter/nf_log.h
··· 61 61 const struct nf_logger *logger); 62 62 void nf_log_unbind_pf(struct net *net, u_int8_t pf); 63 63 64 + int nf_logger_find_get(int pf, enum nf_log_type type); 65 + void nf_logger_put(int pf, enum nf_log_type type); 66 + 67 + #define MODULE_ALIAS_NF_LOGGER(family, type) \ 68 + MODULE_ALIAS("nf-logger-" __stringify(family) "-" __stringify(type)) 69 + 64 70 /* Calls the registered backend logging function */ 65 71 __printf(8, 9) 66 72 void nf_log_packet(struct net *net, ··· 83 77 struct nf_log_buf *nf_log_buf_open(void); 84 78 __printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...); 85 79 void nf_log_buf_close(struct nf_log_buf *m); 86 - 87 - void nf_log_ip_packet(struct net *net, u_int8_t pf, 88 - unsigned int hooknum, const struct sk_buff *skb, 89 - const struct net_device *in, 90 - const struct net_device *out, 91 - const struct nf_loginfo *loginfo, 92 - const char *prefix); 93 - 94 - void nf_log_ip6_packet(struct net *net, u_int8_t pf, 95 - unsigned int hooknum, const struct sk_buff *skb, 96 - const struct net_device *in, 97 - const struct net_device *out, 98 - const struct nf_loginfo *loginfo, 99 - const char *prefix); 100 80 101 81 /* common logging functions */ 102 82 int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
+7 -7
net/ipv4/netfilter/nf_log_ipv4.c
··· 306 306 nf_log_buf_add(m, " "); 307 307 } 308 308 309 - void nf_log_ip_packet(struct net *net, u_int8_t pf, 310 - unsigned int hooknum, const struct sk_buff *skb, 311 - const struct net_device *in, 312 - const struct net_device *out, 313 - const struct nf_loginfo *loginfo, 314 - const char *prefix) 309 + static void nf_log_ip_packet(struct net *net, u_int8_t pf, 310 + unsigned int hooknum, const struct sk_buff *skb, 311 + const struct net_device *in, 312 + const struct net_device *out, 313 + const struct nf_loginfo *loginfo, 314 + const char *prefix) 315 315 { 316 316 struct nf_log_buf *m; 317 317 ··· 334 334 335 335 nf_log_buf_close(m); 336 336 } 337 - EXPORT_SYMBOL_GPL(nf_log_ip_packet); 338 337 339 338 static struct nf_logger nf_ip_logger __read_mostly = { 340 339 .name = "nf_log_ipv4", ··· 382 383 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 383 384 MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); 384 385 MODULE_LICENSE("GPL"); 386 + MODULE_ALIAS_NF_LOGGER(AF_INET, 0);
+7 -7
net/ipv6/netfilter/nf_log_ipv6.c
··· 338 338 } 339 339 } 340 340 341 - void nf_log_ip6_packet(struct net *net, u_int8_t pf, 342 - unsigned int hooknum, const struct sk_buff *skb, 343 - const struct net_device *in, 344 - const struct net_device *out, 345 - const struct nf_loginfo *loginfo, 346 - const char *prefix) 341 + static void nf_log_ip6_packet(struct net *net, u_int8_t pf, 342 + unsigned int hooknum, const struct sk_buff *skb, 343 + const struct net_device *in, 344 + const struct net_device *out, 345 + const struct nf_loginfo *loginfo, 346 + const char *prefix) 347 347 { 348 348 struct nf_log_buf *m; 349 349 ··· 366 366 367 367 nf_log_buf_close(m); 368 368 } 369 - EXPORT_SYMBOL_GPL(nf_log_ip6_packet); 370 369 371 370 static struct nf_logger nf_ip6_logger __read_mostly = { 372 371 .name = "nf_log_ipv6", ··· 414 415 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 415 416 MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); 416 417 MODULE_LICENSE("GPL"); 418 + MODULE_ALIAS_NF_LOGGER(AF_INET6, 0);
+40 -1
net/netfilter/nf_log.c
··· 132 132 } 133 133 EXPORT_SYMBOL(nf_log_unbind_pf); 134 134 135 + int nf_logger_find_get(int pf, enum nf_log_type type) 136 + { 137 + struct nf_logger *logger; 138 + int ret = -ENOENT; 139 + 140 + logger = loggers[pf][type]; 141 + if (logger == NULL) 142 + request_module("nf-logger-%u-%u", pf, type); 143 + 144 + rcu_read_lock(); 145 + logger = rcu_dereference(loggers[pf][type]); 146 + if (logger == NULL) 147 + goto out; 148 + 149 + if (logger && try_module_get(logger->me)) 150 + ret = 0; 151 + out: 152 + rcu_read_unlock(); 153 + return ret; 154 + } 155 + EXPORT_SYMBOL_GPL(nf_logger_find_get); 156 + 157 + void nf_logger_put(int pf, enum nf_log_type type) 158 + { 159 + struct nf_logger *logger; 160 + 161 + BUG_ON(loggers[pf][type] == NULL); 162 + 163 + rcu_read_lock(); 164 + logger = rcu_dereference(loggers[pf][type]); 165 + module_put(logger->me); 166 + rcu_read_unlock(); 167 + } 168 + EXPORT_SYMBOL_GPL(nf_logger_put); 169 + 135 170 void nf_log_packet(struct net *net, 136 171 u_int8_t pf, 137 172 unsigned int hooknum, ··· 181 146 const struct nf_logger *logger; 182 147 183 148 rcu_read_lock(); 184 - logger = rcu_dereference(net->nf.nf_loggers[pf]); 149 + if (loginfo != NULL) 150 + logger = rcu_dereference(loggers[pf][loginfo->type]); 151 + else 152 + logger = rcu_dereference(net->nf.nf_loggers[pf]); 153 + 185 154 if (logger) { 186 155 va_start(args, fmt); 187 156 vsnprintf(prefix, sizeof(prefix), fmt, args);
+10 -12
net/netfilter/xt_LOG.c
··· 39 39 li.u.log.level = loginfo->level; 40 40 li.u.log.logflags = loginfo->logflags; 41 41 42 - if (par->family == NFPROTO_IPV4) 43 - nf_log_ip_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in, 44 - par->out, &li, loginfo->prefix); 45 - #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 46 - else if (par->family == NFPROTO_IPV6) 47 - nf_log_ip6_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in, 48 - par->out, &li, loginfo->prefix); 49 - #endif 50 - else 51 - WARN_ON_ONCE(1); 52 - 42 + nf_log_packet(net, par->family, par->hooknum, skb, par->in, par->out, 43 + &li, loginfo->prefix); 53 44 return XT_CONTINUE; 54 45 } 55 46 ··· 61 70 return -EINVAL; 62 71 } 63 72 64 - return 0; 73 + return nf_logger_find_get(par->family, NF_LOG_TYPE_LOG); 74 + } 75 + 76 + static void log_tg_destroy(const struct xt_tgdtor_param *par) 77 + { 78 + nf_logger_put(par->family, NF_LOG_TYPE_LOG); 65 79 } 66 80 67 81 static struct xt_target log_tg_regs[] __read_mostly = { ··· 76 80 .target = log_tg, 77 81 .targetsize = sizeof(struct xt_log_info), 78 82 .checkentry = log_tg_check, 83 + .destroy = log_tg_destroy, 79 84 .me = THIS_MODULE, 80 85 }, 81 86 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) ··· 86 89 .target = log_tg, 87 90 .targetsize = sizeof(struct xt_log_info), 88 91 .checkentry = log_tg_check, 92 + .destroy = log_tg_destroy, 89 93 .me = THIS_MODULE, 90 94 }, 91 95 #endif