#include <linux/random.h>
#include <net/sock.h>
#include <net/netfilter/nf_log.h>
+#include <net/netfilter/nfnetlink_log.h>
#include <asm/atomic.h>
#endif
#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
-#define NFULNL_TIMEOUT_DEFAULT HZ /* every second */
+#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */
__build_packet_message(struct nfulnl_instance *inst,
const struct sk_buff *skb,
unsigned int data_len,
- unsigned int pf,
+ u_int8_t pf,
unsigned int hooknum,
const struct net_device *indev,
const struct net_device *outdev,
}
}
+ if (indev && skb_mac_header_was_set(skb)) {
+ NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type));
+ NLA_PUT_BE16(inst->skb, NFULA_HWLEN,
+ htons(skb->dev->hard_header_len));
+ NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
+ skb_mac_header(skb));
+ }
+
if (skb->tstamp.tv64) {
struct nfulnl_msg_packet_timestamp ts;
struct timeval tv = ktime_to_timeval(skb->tstamp);
if (skb->sk) {
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
- __be32 uid = htonl(skb->sk->sk_socket->file->f_uid);
- __be32 gid = htons(skb->sk->sk_socket->file->f_gid);
+ struct file *file = skb->sk->sk_socket->file;
+ __be32 uid = htonl(file->f_cred->fsuid);
+ __be32 gid = htonl(file->f_cred->fsgid);
/* need to unlock here since NLA_PUT may goto */
read_unlock_bh(&skb->sk->sk_callback_lock);
NLA_PUT_BE32(inst->skb, NFULA_UID, uid);
};
/* log handler for internal netfilter logging api */
-static void
-nfulnl_log_packet(unsigned int pf,
+void
+nfulnl_log_packet(u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
/* FIXME: do we want to make the size calculation conditional based on
* what is actually present? way more branches and checks, but more
* memory efficient... */
- size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ size = NLMSG_SPACE(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
+ if (in && skb_mac_header_was_set(skb)) {
+ size += nla_total_size(skb->dev->hard_header_len)
+ + nla_total_size(sizeof(u_int16_t)) /* hwtype */
+ + nla_total_size(sizeof(u_int16_t)); /* hwlen */
+ }
+
spin_lock_bh(&inst->lock);
if (inst->flags & NFULNL_CFG_F_SEQ)
qthreshold = inst->qthreshold;
/* per-rule qthreshold overrides per-instance */
- if (qthreshold > li->u.ulog.qthreshold)
- qthreshold = li->u.ulog.qthreshold;
+ if (li->u.ulog.qthreshold)
+ if (qthreshold > li->u.ulog.qthreshold)
+ qthreshold = li->u.ulog.qthreshold;
+
switch (inst->copy_mode) {
case NFULNL_COPY_META:
/* FIXME: statistics */
goto unlock_and_release;
}
+EXPORT_SYMBOL_GPL(nfulnl_log_packet);
static int
nfulnl_rcv_nl_event(struct notifier_block *this,
{
struct netlink_notify *n = ptr;
- if (event == NETLINK_URELEASE &&
- n->protocol == NETLINK_NETFILTER && n->pid) {
+ if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
int i;
/* destroy all instances for this pid */
struct hlist_head *head = &instance_table[i];
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
- if ((n->net == &init_net) &&
+ if ((net_eq(n->net, &init_net)) &&
(n->pid == inst->peer_pid))
__instance_destroy(inst);
}
static int
nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nlattr *nfqa[])
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const nfqa[])
{
return -ENOTSUPP;
}
-static const struct nf_logger nfulnl_logger = {
+static struct nf_logger nfulnl_logger __read_mostly = {
.name = "nfnetlink_log",
.logfn = &nfulnl_log_packet,
.me = THIS_MODULE,
static int
nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nlattr *nfula[])
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const nfula[])
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t group_num = ntohs(nfmsg->res_id);
struct nfulnl_instance *inst;
+ struct nfulnl_msg_config_cmd *cmd = NULL;
int ret = 0;
+ if (nfula[NFULA_CFG_CMD]) {
+ u_int8_t pf = nfmsg->nfgen_family;
+ cmd = nla_data(nfula[NFULA_CFG_CMD]);
+
+ /* Commands without queue context */
+ switch (cmd->command) {
+ case NFULNL_CFG_CMD_PF_BIND:
+ return nf_log_bind_pf(pf, &nfulnl_logger);
+ case NFULNL_CFG_CMD_PF_UNBIND:
+ nf_log_unbind_pf(pf);
+ return 0;
+ }
+ }
+
inst = instance_lookup_get(group_num);
if (inst && inst->peer_pid != NETLINK_CB(skb).pid) {
ret = -EPERM;
goto out_put;
}
- if (nfula[NFULA_CFG_CMD]) {
- u_int8_t pf = nfmsg->nfgen_family;
- struct nfulnl_msg_config_cmd *cmd;
-
- cmd = nla_data(nfula[NFULA_CFG_CMD]);
-
+ if (cmd != NULL) {
switch (cmd->command) {
case NFULNL_CFG_CMD_BIND:
if (inst) {
instance_destroy(inst);
goto out;
- case NFULNL_CFG_CMD_PF_BIND:
- ret = nf_log_register(pf, &nfulnl_logger);
- break;
- case NFULNL_CFG_CMD_PF_UNBIND:
- /* This is a bug and a feature. We cannot unregister
- * other handlers, like nfnetlink_inst can */
- nf_log_unregister_pf(pf);
- break;
default:
ret = -ENOTSUPP;
break;
}
static void *seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(instances_lock)
{
read_lock_bh(&instances_lock);
return get_idx(seq->private, *pos);
}
static void seq_stop(struct seq_file *s, void *v)
+ __releases(instances_lock)
{
read_unlock_bh(&instances_lock);
}
static int __init nfnetlink_log_init(void)
{
int i, status = -ENOMEM;
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc_nful;
-#endif
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
goto cleanup_netlink_notifier;
}
-#ifdef CONFIG_PROC_FS
- proc_nful = create_proc_entry("nfnetlink_log", 0440,
- proc_net_netfilter);
- if (!proc_nful)
+ status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
+ if (status < 0) {
+ printk(KERN_ERR "log: failed to register logger\n");
goto cleanup_subsys;
- proc_nful->proc_fops = &nful_file_ops;
+ }
+
+#ifdef CONFIG_PROC_FS
+ if (!proc_create("nfnetlink_log", 0440,
+ proc_net_netfilter, &nful_file_ops))
+ goto cleanup_logger;
#endif
return status;
#ifdef CONFIG_PROC_FS
+cleanup_logger:
+ nf_log_unregister(&nfulnl_logger);
+#endif
cleanup_subsys:
nfnetlink_subsys_unregister(&nfulnl_subsys);
-#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
return status;