ebt_log.c 6.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 *  ebt_log
 *
 *	Authors:
 *	Bart De Schuymer <bdschuym@pandora.be>
6
 *	Harald Welte <laforge@netfilter.org>
L
Linus Torvalds 已提交
7 8 9 10 11 12
 *
 *  April, 2002
 *
 */
#include <linux/module.h>
#include <linux/ip.h>
13
#include <linux/in.h>
L
Linus Torvalds 已提交
14 15
#include <linux/if_arp.h>
#include <linux/spinlock.h>
16
#include <net/netfilter/nf_log.h>
17 18 19
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <linux/in6.h>
20 21 22 23
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_log.h>
#include <linux/netfilter.h>
L
Linus Torvalds 已提交
24 25 26

static DEFINE_SPINLOCK(ebt_log_lock);

27 28 29 30
static bool
ebt_log_tg_check(const char *table, const void *entry,
		 const struct xt_target *target, void *data,
		 unsigned int hook_mask)
L
Linus Torvalds 已提交
31
{
32
	struct ebt_log_info *info = data;
L
Linus Torvalds 已提交
33 34

	if (info->bitmask & ~EBT_LOG_MASK)
35
		return false;
L
Linus Torvalds 已提交
36
	if (info->loglevel >= 8)
37
		return false;
L
Linus Torvalds 已提交
38
	info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0';
39
	return true;
L
Linus Torvalds 已提交
40 41 42 43
}

struct tcpudphdr
{
A
Al Viro 已提交
44 45
	__be16 src;
	__be16 dst;
L
Linus Torvalds 已提交
46 47 48 49 50 51 52 53 54 55
};

struct arppayload
{
	unsigned char mac_src[ETH_ALEN];
	unsigned char ip_src[4];
	unsigned char mac_dst[ETH_ALEN];
	unsigned char ip_dst[4];
};

56
static void print_MAC(const unsigned char *p)
L
Linus Torvalds 已提交
57 58 59 60 61 62 63
{
	int i;

	for (i = 0; i < ETH_ALEN; i++, p++)
		printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
static void
print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
{
	if (protocol == IPPROTO_TCP ||
	    protocol == IPPROTO_UDP ||
	    protocol == IPPROTO_UDPLITE ||
	    protocol == IPPROTO_SCTP ||
	    protocol == IPPROTO_DCCP) {
		const struct tcpudphdr *pptr;
		struct tcpudphdr _ports;

		pptr = skb_header_pointer(skb, offset,
					  sizeof(_ports), &_ports);
		if (pptr == NULL) {
			printk(" INCOMPLETE TCP/UDP header");
			return;
		}
		printk(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst));
	}
}

L
Linus Torvalds 已提交
85
#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
86
static void
87
ebt_log_packet(u_int8_t pf, unsigned int hooknum,
88 89 90
   const struct sk_buff *skb, const struct net_device *in,
   const struct net_device *out, const struct nf_loginfo *loginfo,
   const char *prefix)
L
Linus Torvalds 已提交
91
{
92
	unsigned int bitmask;
L
Linus Torvalds 已提交
93 94

	spin_lock_bh(&ebt_log_lock);
95 96
	printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level,
	       prefix, in ? in->name : "", out ? out->name : "");
L
Linus Torvalds 已提交
97 98 99 100 101 102 103

	print_MAC(eth_hdr(skb)->h_source);
	printk("MAC dest = ");
	print_MAC(eth_hdr(skb)->h_dest);

	printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));

104 105 106 107 108 109
	if (loginfo->type == NF_LOG_TYPE_LOG)
		bitmask = loginfo->u.log.logflags;
	else
		bitmask = NF_LOG_MASK;

	if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
L
Linus Torvalds 已提交
110
	   htons(ETH_P_IP)){
111 112
		const struct iphdr *ih;
		struct iphdr _iph;
L
Linus Torvalds 已提交
113 114 115 116 117 118

		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
		if (ih == NULL) {
			printk(" INCOMPLETE IP header");
			goto out;
		}
119 120 121
		printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
		       "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
		       NIPQUAD(ih->daddr), ih->tos, ih->protocol);
122 123 124 125
		print_ports(skb, ih->protocol, ih->ihl*4);
		goto out;
	}

R
Randy Dunlap 已提交
126
#if defined(CONFIG_BRIDGE_EBT_IP6) || defined(CONFIG_BRIDGE_EBT_IP6_MODULE)
127 128 129 130 131 132 133 134 135 136 137
	if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto ==
	   htons(ETH_P_IPV6)) {
		const struct ipv6hdr *ih;
		struct ipv6hdr _iph;
		uint8_t nexthdr;
		int offset_ph;

		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
		if (ih == NULL) {
			printk(" INCOMPLETE IPv6 header");
			goto out;
L
Linus Torvalds 已提交
138
		}
139 140 141 142 143 144 145 146 147
		printk(" IPv6 SRC=%x:%x:%x:%x:%x:%x:%x:%x "
		       "IPv6 DST=%x:%x:%x:%x:%x:%x:%x:%x, IPv6 "
		       "priority=0x%01X, Next Header=%d", NIP6(ih->saddr),
		       NIP6(ih->daddr), ih->priority, ih->nexthdr);
		nexthdr = ih->nexthdr;
		offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr);
		if (offset_ph == -1)
			goto out;
		print_ports(skb, nexthdr, offset_ph);
L
Linus Torvalds 已提交
148 149
		goto out;
	}
R
Randy Dunlap 已提交
150
#endif
L
Linus Torvalds 已提交
151

152
	if ((bitmask & EBT_LOG_ARP) &&
L
Linus Torvalds 已提交
153 154
	    ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
	     (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
155 156
		const struct arphdr *ah;
		struct arphdr _arph;
L
Linus Torvalds 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170

		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
		if (ah == NULL) {
			printk(" INCOMPLETE ARP header");
			goto out;
		}
		printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
		       ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
		       ntohs(ah->ar_op));

		/* If it's for Ethernet and the lengths are OK,
		 * then log the ARP payload */
		if (ah->ar_hrd == htons(1) &&
		    ah->ar_hln == ETH_ALEN &&
A
Al Viro 已提交
171
		    ah->ar_pln == sizeof(__be32)) {
172 173
			const struct arppayload *ap;
			struct arppayload _arpp;
L
Linus Torvalds 已提交
174

175
			ap = skb_header_pointer(skb, sizeof(_arph),
L
Linus Torvalds 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
						sizeof(_arpp), &_arpp);
			if (ap == NULL) {
				printk(" INCOMPLETE ARP payload");
				goto out;
			}
			printk(" ARP MAC SRC=");
			print_MAC(ap->mac_src);
			printk(" ARP IP SRC=%u.%u.%u.%u",
			       myNIPQUAD(ap->ip_src));
			printk(" ARP MAC DST=");
			print_MAC(ap->mac_dst);
			printk(" ARP IP DST=%u.%u.%u.%u",
			       myNIPQUAD(ap->ip_dst));
		}
	}
out:
	printk("\n");
	spin_unlock_bh(&ebt_log_lock);
194 195 196

}

197 198 199 200
static unsigned int
ebt_log_tg(struct sk_buff *skb, const struct net_device *in,
	   const struct net_device *out, unsigned int hooknr,
	   const struct xt_target *target, const void *data)
201
{
202
	const struct ebt_log_info *info = data;
203 204 205 206 207 208
	struct nf_loginfo li;

	li.type = NF_LOG_TYPE_LOG;
	li.u.log.level = info->loglevel;
	li.u.log.logflags = info->bitmask;

209
	if (info->bitmask & EBT_LOG_NFLOG)
210
		nf_log_packet(NFPROTO_BRIDGE, hooknr, skb, in, out, &li,
211
			      "%s", info->prefix);
212
	else
213
		ebt_log_packet(NFPROTO_BRIDGE, hooknr, skb, in, out, &li,
214
			       info->prefix);
215
	return EBT_CONTINUE;
L
Linus Torvalds 已提交
216 217 218 219 220
}

static struct ebt_watcher log =
{
	.name		= EBT_LOG_WATCHER,
221 222
	.revision	= 0,
	.family		= NFPROTO_BRIDGE,
223 224
	.target		= ebt_log_tg,
	.checkentry	= ebt_log_tg_check,
225
	.targetsize	= XT_ALIGN(sizeof(struct ebt_log_info)),
L
Linus Torvalds 已提交
226 227 228
	.me		= THIS_MODULE,
};

229
static const struct nf_logger ebt_log_logger = {
230 231 232 233 234
	.name 		= "ebt_log",
	.logfn		= &ebt_log_packet,
	.me		= THIS_MODULE,
};

235
static int __init ebt_log_init(void)
L
Linus Torvalds 已提交
236
{
237 238 239 240 241
	int ret;

	ret = ebt_register_watcher(&log);
	if (ret < 0)
		return ret;
242
	nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger);
243
	return 0;
L
Linus Torvalds 已提交
244 245
}

246
static void __exit ebt_log_fini(void)
L
Linus Torvalds 已提交
247
{
248
	nf_log_unregister(&ebt_log_logger);
L
Linus Torvalds 已提交
249 250 251
	ebt_unregister_watcher(&log);
}

252 253
module_init(ebt_log_init);
module_exit(ebt_log_fini);
254
MODULE_DESCRIPTION("Ebtables: Packet logging to syslog");
L
Linus Torvalds 已提交
255
MODULE_LICENSE("GPL");