3 Copyright (C) 2014 Proxmox Server Solutions GmbH
5 This software is written by Proxmox Server Solutions GmbH <support@proxmox.com>
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Affero General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Affero General Public License for more details.
17 You should have received a copy of the GNU Affero General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Author: Dietmar Maurer <dietmar@proxmox.com>
32 #include <sys/signalfd.h>
33 #include <sys/types.h>
37 #include <arpa/inet.h>
38 #include <sys/socket.h>
40 #include <linux/netlink.h>
41 #include <libnfnetlink/libnfnetlink.h>
42 #include <libnetfilter_log/libnetfilter_log.h>
43 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
44 #include <netinet/ip.h>
45 #include <netinet/ip_icmp.h>
46 #include <netinet/ip6.h>
47 #include <netinet/icmp6.h>
48 #include <netinet/udp.h>
49 #include <netinet/tcp.h>
50 #include <netinet/if_ether.h>
55 static struct nflog_handle
*logh
= NULL
;
56 static struct nlif_handle
*nlifh
= NULL
;
57 static struct nfct_handle
*nfcth
= NULL
;
60 gboolean foreground
= FALSE
;
61 gboolean debug
= FALSE
;
62 gboolean conntrack
= FALSE
;
68 Special care was taken to allow fast parsing (and filer messages for a singl VM).
70 <VMID> <LOGLEVEL> <CHAIN> <TIME> <TIMEZONE> <MSG>
74 117 6 tap117i0-IN 14/Mar/2014:12:47:07 +0100 policy REJECT: IN=vmbr1 ...
78 #define LOGFILE "/var/log/pve-firewall.log"
80 #define LOCKFILE "/var/lock/pvefw-logger.lck"
81 #define PIDFILE "/var/run/pvefw-logger.pid"
82 #define LOG_CONNTRACK_FILE "/var/lib/pve-firewall/log_nf_conntrack"
85 #define LE_MAX (512 - 4) // try to fit into 512 bytes
87 #define MAX_CHAIN_LEN 28
90 guint32 len
; // max LE_MAX chars
94 #define STATIC_ASSERT(cond) \
95 extern void pve_static_assert(int test[(cond) ? 1 : -1])
97 STATIC_ASSERT(sizeof(struct log_entry
) == 512);
101 gboolean terminate_threads
= FALSE
;
103 static gboolean
write_pidfile(pid_t pid
)
107 char *strpid
= g_strdup_printf("%d\n", pid
);
108 res
= g_file_set_contents(PIDFILE
, strpid
, strlen(strpid
), NULL
);
114 static GAsyncQueue
*queue
;
117 safe_write(int fd
, char *buf
, size_t count
)
122 n
= write(fd
, buf
, count
);
123 } while (n
< 0 && errno
== EINTR
);
129 log_writer_thread(gpointer data
)
132 struct log_entry
*le
= (struct log_entry
*)g_async_queue_timeout_pop(queue
, 250000);
134 if (terminate_threads
) {
140 if (debug
) fputs(le
->buf
, stdout
);
142 int res
= safe_write(outfd
, le
->buf
, le
->len
);
147 syslog(3, "writing log failed, stopping daemon - %s", strerror (errno
));
148 g_main_loop_quit(main_loop
);
156 static int skipped_logs
= 0;
158 static void log_status_message(guint loglevel
, const char *fmt
, ...);
161 queue_log_entry(struct log_entry
*le
)
163 gint len
= g_async_queue_length(queue
);
165 if (skipped_logs
> 0) {
166 if (len
>= (LQ_LEN
- 1)) {
169 int skip_tmp
= skipped_logs
;
170 skipped_logs
= 0; // clear before calling log_status_message()
171 log_status_message(3, "skipped %d log entries (queue full)", skip_tmp
);
172 g_async_queue_push(queue
, le
);
178 g_async_queue_push(queue
, le
);
184 #define LEPRINTF(format, ...) \
186 if (le->len < LE_MAX) \
187 le->len += snprintf(le->buf + le->len, LE_MAX - le->len, format, ##__VA_ARGS__); \
189 #define LEPRINTTIME(sec) \
191 time_t tmp_sec = sec; \
192 if (le->len < (LE_MAX - 30)) \
193 le->len += strftime(le->buf + le->len, LE_MAX - le->len, "%d/%b/%Y:%H:%M:%S %z ", localtime(&tmp_sec)); \
197 log_status_message(guint loglevel
, const char *fmt
, ...)
201 if (loglevel
> 7 ) loglevel
= 7; // syslog defines level 0-7
203 struct log_entry
*le
= g_new0(struct log_entry
, 1);
205 LEPRINTF("0 %d - ", loglevel
);
207 LEPRINTTIME(time(NULL
));
211 le
->len
+= vsnprintf(le
->buf
+ le
->len
, LE_MAX
- le
->len
, fmt
, ap
);
218 // also log to syslog
220 vsyslog(loglevel
, fmt
, ap2
);
225 print_tcp(struct log_entry
*le
, struct tcphdr
*h
, int payload_len
)
227 LEPRINTF("PROTO=TCP ");
229 if (payload_len
< sizeof(struct tcphdr
)) {
230 LEPRINTF("LEN=%d ", payload_len
);
231 LEPRINTF("INVALID=LEN ");
235 LEPRINTF("SPT=%u DPT=%u ", ntohs(h
->source
), ntohs(h
->dest
));
236 LEPRINTF("SEQ=%u ACK=%u ", ntohl(h
->seq
), ntohl(h
->ack_seq
));
237 LEPRINTF("WINDOW=%u ", ntohs(h
->window
));
239 if (h
->urg
) LEPRINTF("URG ");
240 if (h
->ack
) LEPRINTF("ACK ");
241 if (h
->psh
) LEPRINTF("PSH ");
242 if (h
->rst
) LEPRINTF("RST ");
243 if (h
->syn
) LEPRINTF("SYN ");
244 if (h
->fin
) LEPRINTF("FIN ");
246 if (h
->urg
) LEPRINTF("URGP=%u ",ntohs(h
->urg_ptr
));
252 print_udp(struct log_entry
*le
, struct udphdr
*h
, int payload_len
)
254 LEPRINTF("PROTO=UDP ");
256 if (payload_len
< sizeof(struct udphdr
)) {
257 LEPRINTF("LEN=%d ", payload_len
);
258 LEPRINTF("INVALID=LEN ");
262 LEPRINTF("SPT=%u DPT=%u LEN=%u", ntohs(h
->source
), ntohs(h
->dest
), ntohs(h
->len
));
268 print_icmp(struct log_entry
*le
, struct icmphdr
*h
, int payload_len
)
270 char tmp
[INET_ADDRSTRLEN
];
273 LEPRINTF("PROTO=ICMP ");
275 if (payload_len
< sizeof(struct icmphdr
)) {
276 LEPRINTF("LEN=%d ", payload_len
);
277 LEPRINTF("INVALID=LEN ");
281 LEPRINTF("TYPE=%u CODE=%u ", h
->type
, h
->code
);
286 LEPRINTF("ID=%u SEQ=%u ", ntohs(h
->un
.echo
.id
), ntohs(h
->un
.echo
.sequence
));
288 case ICMP_PARAMETERPROB
:
289 LEPRINTF("PARAMETER=%u ", ntohl(h
->un
.gateway
) >> 24);
292 gateway
= ntohl(h
->un
.gateway
);
293 inet_ntop(AF_INET
, &gateway
, tmp
, sizeof(tmp
));
294 LEPRINTF("GATEWAY=%s ", tmp
);
296 case ICMP_DEST_UNREACH
:
297 if (h
->code
== ICMP_FRAG_NEEDED
) {
298 LEPRINTF("MTU=%u ", ntohs(h
->un
.frag
.mtu
));
306 /* Section 3.1. SCTP Common Header Format */
307 typedef struct sctphdr
{
312 } __attribute__((packed
)) sctp_sctphdr_t
;
315 print_sctp(struct log_entry
*le
, struct sctphdr
*h
, int payload_len
)
317 LEPRINTF("PROTO=SCTP ");
319 if (payload_len
< sizeof(struct sctphdr
)) {
320 LEPRINTF("LEN=%d ", payload_len
);
321 LEPRINTF("INVALID=LEN ");
325 LEPRINTF("SPT=%u DPT=%u ", ntohs(h
->source
), ntohs(h
->dest
));
331 print_ipproto(struct log_entry
*le
, char * nexthdr
, int payload_len
, u_int8_t proto
)
335 print_tcp(le
, (struct tcphdr
*)nexthdr
, payload_len
);
338 print_udp(le
, (struct udphdr
*)nexthdr
, payload_len
);
341 print_icmp(le
, (struct icmphdr
*)nexthdr
, payload_len
);
344 print_sctp(le
, (struct sctphdr
*)nexthdr
, payload_len
);
347 LEPRINTF("PROTO=AH ");
350 LEPRINTF("PROTO=ESP ");
353 LEPRINTF("PROTO=IGMP ");
362 print_iphdr(struct log_entry
*le
, char * payload
, int payload_len
)
364 if (payload_len
< sizeof(struct iphdr
)) {
365 LEPRINTF("LEN=%d ", payload_len
);
366 LEPRINTF("INVALID=LEN ");
370 struct iphdr
*h
= (struct iphdr
*)payload
;
372 if (payload_len
<= (u_int32_t
)(h
->ihl
* 4)) {
373 LEPRINTF("INVALID=IHL ");
377 char tmp
[INET_ADDRSTRLEN
];
379 inet_ntop(AF_INET
, &h
->saddr
, tmp
, sizeof(tmp
));
380 LEPRINTF("SRC=%s ", tmp
);
381 inet_ntop(AF_INET
, &h
->daddr
, tmp
, sizeof(tmp
));
382 LEPRINTF("DST=%s ", tmp
);
384 LEPRINTF("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
385 ntohs(h
->tot_len
), h
->tos
& IPTOS_TOS_MASK
,
386 h
->tos
& IPTOS_PREC_MASK
, h
->ttl
, ntohs(h
->id
));
388 short ip_off
= ntohs(h
->frag_off
);
389 if (ip_off
& IP_OFFMASK
)
390 LEPRINTF("FRAG=%u ", ip_off
& IP_OFFMASK
);
392 if (ip_off
& IP_DF
) LEPRINTF("DF ");
393 if (ip_off
& IP_MF
) LEPRINTF("MF ");
395 void *nexthdr
= (u_int32_t
*)h
+ h
->ihl
;
396 payload_len
-= h
->ihl
* 4;
398 if (print_ipproto(le
, nexthdr
, payload_len
, h
->protocol
) < 0) {
399 LEPRINTF("PROTO=%u ", h
->protocol
);
406 print_routing(struct log_entry
*le
, struct ip6_rthdr
*rthdr
, int payload_len
)
408 char tmp
[INET6_ADDRSTRLEN
];
409 LEPRINTF("TYPE=%u SEGMENTS=%u", rthdr
->ip6r_type
, rthdr
->ip6r_segleft
);
411 if (payload_len
< sizeof(*rthdr
) || payload_len
< rthdr
->ip6r_len
*8) {
412 LEPRINTF("LEN=%d ", payload_len
);
413 LEPRINTF("INVALID=LEN ");
417 if (rthdr
->ip6r_type
== 0) {
418 /* Route via waypoints (deprecated), this contains a list of waypoints
419 * to visit. (RFC2460 (4.4))
421 struct ip6_rthdr0
*h
= (struct ip6_rthdr0
*)rthdr
;
422 if (rthdr
->ip6r_len
*8 < sizeof(*h
) + rthdr
->ip6r_segleft
* sizeof(struct in6_addr
)) {
423 LEPRINTF("INVALID=SEGMENTS ");
427 } else if (rthdr
->ip6r_type
== 1) {
428 /* nimrod routing (RFC1992) */
430 } else if (rthdr
->ip6r_type
== 2) {
431 /* RFC3375 (6.4), the layout is like type-0 but with exactly 1 address */
432 struct ip6_rthdr0
*h
= (struct ip6_rthdr0
*)rthdr
;
433 if (rthdr
->ip6r_len
*8 < sizeof(*h
) + sizeof(struct in6_addr
)) {
434 LEPRINTF("LEN=%d ", payload_len
);
435 LEPRINTF("INVALID=LEN ");
438 inet_ntop(AF_INET6
, &h
->ip6r0_addr
[0], tmp
, sizeof(tmp
));
439 LEPRINTF("HOME=%s ", tmp
);
447 print_fragment(struct log_entry
*le
, struct ip6_frag
*frag
, int payload_len
)
451 if (payload_len
< sizeof(*frag
)) {
452 LEPRINTF("LEN=%d ", payload_len
);
453 LEPRINTF("INVALID=LEN ");
457 offlg
= ntohs(frag
->ip6f_offlg
);
458 LEPRINTF("FRAG=%d ID=%d ", (offlg
&0x2FFF), ntohl(frag
->ip6f_ident
));
466 print_icmp6(struct log_entry
*le
, struct icmp6_hdr
*h
, int payload_len
)
468 struct nd_router_advert
*ra
;
469 struct nd_neighbor_advert
*na
;
470 struct nd_redirect
*re
;
471 char tmp
[INET6_ADDRSTRLEN
];
473 if (payload_len
< sizeof(struct icmp6_hdr
)) {
474 LEPRINTF("LEN=%d ", payload_len
);
475 LEPRINTF("INVALID=LEN ");
479 LEPRINTF("TYPE=%u CODE=%u ", h
->icmp6_type
, h
->icmp6_code
);
481 switch (h
->icmp6_type
) {
482 case ICMP6_ECHO_REQUEST
:
483 case ICMP6_ECHO_REPLY
:
484 LEPRINTF("ID=%u SEQ=%u ", ntohs(h
->icmp6_id
), ntohs(h
->icmp6_seq
));
487 case ND_ROUTER_SOLICIT
:
488 /* can be followed by options, otherwise nothing to print */
491 case ND_ROUTER_ADVERT
:
492 ra
= (struct nd_router_advert
*)h
;
493 LEPRINTF("HOPLIMIT=%d ", ra
->nd_ra_curhoplimit
);
494 /* nd_ra_flags_reserved is only 8 bit, so no swapping here as
495 * opposed to the neighbor advertisement flags (see below).
497 LEPRINTF("RA=%02x LIFETIME=%d REACHABLE=%d RETRANSMIT=%d ",
498 ra
->nd_ra_flags_reserved
,
499 ntohs(ra
->nd_ra_router_lifetime
),
500 ntohl(ra
->nd_ra_reachable
),
501 ntohl(ra
->nd_ra_retransmit
));
502 /* can be followed by options */
505 case ND_NEIGHBOR_SOLICIT
:
506 /* can be followed by options */
509 case ND_NEIGHBOR_ADVERT
:
510 na
= (struct nd_neighbor_advert
*)h
;
511 LEPRINTF("NA=%08x ", ntohl(na
->nd_na_flags_reserved
));
512 /* can be followed by options */
516 re
= (struct nd_redirect
*)h
;
517 inet_ntop(AF_INET6
, &re
->nd_rd_target
, tmp
, sizeof(tmp
));
518 LEPRINTF("TARGET=%s ", tmp
);
519 inet_ntop(AF_INET6
, &re
->nd_rd_dst
, tmp
, sizeof(tmp
));
520 LEPRINTF("GATEWAY=%s ", tmp
);
521 /* can be followed by options */
524 case ICMP6_DST_UNREACH
:
525 /* CODE shows the type, no extra parameters available in ipv6 */
528 case ICMP6_PACKET_TOO_BIG
:
529 LEPRINTF("MTU=%u ", ntohl(h
->icmp6_mtu
));
532 case ICMP6_TIME_EXCEEDED
:
533 /* CODE shows the type (0 = hop limit, 1 = reassembly timed out) */
536 case ICMP6_PARAM_PROB
:
537 switch (ntohl(h
->icmp6_pptr
)) {
538 case ICMP6_PARAMPROB_HEADER
:
539 LEPRINTF("PARAMETER=HEADER "); /* erroneous header */
541 case ICMP6_PARAMPROB_NEXTHEADER
:
542 LEPRINTF("PARAMETER=NEXTHEADER "); /* bad next-header field */
544 case ICMP6_PARAMPROB_OPTION
:
545 LEPRINTF("PARAMETER=OPTION "); /* bad ipv6 option (hop/dst header?) */
548 LEPRINTF("PARAMETER=%u ", ntohl(h
->icmp6_pptr
)); /* unknown */
558 check_ip6ext(struct log_entry
*le
, struct ip6_ext
*exthdr
, int payload_len
)
560 if (payload_len
< sizeof(*exthdr
) ||
561 payload_len
< exthdr
->ip6e_len
)
563 LEPRINTF("LEN=%d ", payload_len
);
564 LEPRINTF("INVALID=LEN ");
571 print_nexthdr(struct log_entry
*le
, char *hdr
, int payload_len
, u_int8_t proto
)
574 if (print_ipproto(le
, hdr
, payload_len
, proto
) == 0)
577 struct ip6_ext
*exthdr
= (struct ip6_ext
*)hdr
;
581 /* protocols (these return) */
583 LEPRINTF("PROTO=ICMPV6 ");
584 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
586 if (print_icmp6(le
, (struct icmp6_hdr
*)(hdr
+ exthdr
->ip6e_len
),
587 payload_len
- exthdr
->ip6e_len
) < 0)
593 /* extension headers (these break to keep iterating) */
594 case IPPROTO_ROUTING
:
595 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
597 if (print_routing(le
, (struct ip6_rthdr
*)hdr
, payload_len
) < 0)
600 case IPPROTO_FRAGMENT
:
601 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
603 if (print_fragment(le
, (struct ip6_frag
*)hdr
, payload_len
) < 0)
605 ext_len
= sizeof(struct ip6_frag
);
607 case IPPROTO_HOPOPTS
:
608 LEPRINTF("NEXTHDR=HOPOPTS ");
609 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
611 /* do we want to print these? */
613 case IPPROTO_DSTOPTS
:
614 LEPRINTF("NEXTHDR=DSTOPTS ");
615 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
617 /* do we want to print these? */
620 LEPRINTF("NEXTHDR=MH ");
621 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
625 /* unknown protocol */
627 LEPRINTF("PROTO=%u ", proto
);
631 if (check_ip6ext(le
, exthdr
, payload_len
) < 0)
634 ext_len
= (exthdr
->ip6e_len
+1) * 8;
637 payload_len
-= ext_len
;
638 proto
= exthdr
->ip6e_nxt
;
643 print_ip6hdr(struct log_entry
*le
, char * payload
, int payload_len
)
645 if (payload_len
< sizeof(struct ip6_hdr
)) {
646 LEPRINTF("LEN=%d ", payload_len
);
647 LEPRINTF("INVALID=LEN ");
651 struct ip6_hdr
*h
= (struct ip6_hdr
*)payload
;
653 char tmp
[INET6_ADDRSTRLEN
];
654 inet_ntop(AF_INET6
, &h
->ip6_src
, tmp
, sizeof(tmp
));
655 LEPRINTF("SRC=%s ", tmp
);
656 inet_ntop(AF_INET6
, &h
->ip6_dst
, tmp
, sizeof(tmp
));
657 LEPRINTF("DST=%s ", tmp
);
659 LEPRINTF("LEN=%u ", ntohs(h
->ip6_plen
));
661 u_int32_t flow
= ntohl(h
->ip6_flow
);
662 LEPRINTF("TC=%d FLOWLBL=%d ", (flow
>>20)&0xFF, flow
&0xFFFFF);
664 LEPRINTF("HOPLIMIT=%d ", h
->ip6_hlim
);
666 return print_nexthdr(le
, (char *)(h
+1), payload_len
- sizeof(*h
), h
->ip6_nxt
);
669 // ebtables -I FORWARD --nflog --nflog-group 0
671 print_arp(struct log_entry
*le
, struct ether_arp
*h
, int payload_len
)
673 if (payload_len
< sizeof(struct ether_arp
)) {
674 LEPRINTF("LEN=%d ", payload_len
);
675 LEPRINTF("INVALID=LEN ");
679 LEPRINTF("SRC=%u.%u.%u.%u ", h
->arp_spa
[0], h
->arp_spa
[1],
680 h
->arp_spa
[2], h
->arp_spa
[3]);
682 LEPRINTF("DST=%u.%u.%u.%u ", h
->arp_tpa
[0], h
->arp_tpa
[1],
683 h
->arp_tpa
[2], h
->arp_tpa
[3]);
685 LEPRINTF("PROTO=ARP ");
687 unsigned short code
= ntohs(h
->arp_op
);
690 LEPRINTF("REQUEST ");
693 LEPRINTF("REPLY MAC=%02x:%02x:%02x:%02x:%02x:%02x ",
694 h
->arp_sha
[0], h
->arp_sha
[1], h
->arp_sha
[2],
695 h
->arp_sha
[3], h
->arp_sha
[4], h
->arp_sha
[5]);
701 LEPRINTF("CODE=%u ", code
);
705 // LEPRINTF("HTYPE=%u ", ntohs(h->arp_hrd));
707 // LEPRINTF("PTYPE=%u ", ntohs(h->arp_pro));
713 static int print_pkt(struct log_entry
*le
, struct nflog_data
*ldata
, u_int8_t family
)
715 u_int32_t mark
= nflog_get_nfmark(ldata
);
716 u_int32_t indev
= nflog_get_indev(ldata
);
717 u_int32_t outdev
= nflog_get_outdev(ldata
);
718 u_int32_t physindev
= nflog_get_physindev(ldata
);
719 u_int32_t physoutdev
= nflog_get_physoutdev(ldata
);
721 char *prefix
= nflog_get_prefix(ldata
);
727 guint8 log_level
= 6; // info
729 char *chain_name
= "-";
731 if (prefix
!= NULL
) {
732 // Note: parse ":$vmid:$loglevel:$chain: $msg"
733 if (prefix
[0] == ':') {
734 char *p
= prefix
+ 1;
736 while(*p
>= '0' && *p
<= '9') { tmpid
*= 10; tmpid
+= *p
- '0'; p
++; }
739 (p
[1] >= '0' && p
[1] <= '7') &&
742 guint8 tmp_level
= p
[1] - '0'; // store for later use
743 char *chain_start
= p
+ 3; // store for later use
745 while (*p
&& *p
!= ':' && *p
!= ' ') p
++;
746 int len
= p
- chain_start
;
748 if (*p
== ':' && p
[1] == ' ' && len
&& (len
<= MAX_CHAIN_LEN
)) {
749 // parsing successful
751 *p
= 0; // terminate string
754 log_level
= tmp_level
;
755 chain_name
= chain_start
;
756 prefix
= p
+ 2; // the rest
762 LEPRINTF("%d ", vmid
);
764 LEPRINTF("%d ", log_level
);
766 LEPRINTF("%s ", chain_name
);
769 if (nflog_get_timestamp(ldata
, &ts
) == 0) {
770 LEPRINTTIME(ts
.tv_sec
);
772 LEPRINTTIME(time(NULL
));
775 if (prefix
!= NULL
) {
776 LEPRINTF("%s", prefix
);
780 if (nlif_index2name(nlifh
, indev
, devname
) != -1) {
781 LEPRINTF("IN=%s ", devname
);
783 LEPRINTF("IN=%u ", indev
);
788 if (nlif_index2name(nlifh
, outdev
, devname
) != -1) {
789 LEPRINTF("OUT=%s ", devname
);
791 LEPRINTF("OUT=%u ", outdev
);
796 if (nlif_index2name(nlifh
, physindev
, devname
) != -1) {
797 LEPRINTF("PHYSIN=%s ", devname
);
799 LEPRINTF("PHYSIN=%u ", physindev
);
803 if (physoutdev
> 0) {
804 if (nlif_index2name(nlifh
, physoutdev
, devname
) != -1) {
805 LEPRINTF("PHYSOUT=%s ", devname
);
807 LEPRINTF("PHYSOUT=%u ", physoutdev
);
811 int payload_len
= nflog_get_payload(ldata
, &payload
);
813 int hwhdrlen
= nflog_get_msg_packet_hwhdrlen(ldata
);
815 unsigned char *hwhdr
= (unsigned char *)nflog_get_msg_packet_hwhdr(ldata
);
819 for (i
= 0; i
< hwhdrlen
; i
++) {
820 LEPRINTF("%02x", hwhdr
[i
]);
821 if (i
< (hwhdrlen
-1 )) LEPRINTF(":");
827 u_int16_t hw_protocol
= 0;
828 struct nfulnl_msg_packet_hdr
*ph
= NULL
;
832 print_iphdr(le
, payload
, payload_len
);
835 print_ip6hdr(le
, payload
, payload_len
);
838 ph
= nflog_get_msg_packet_hdr(ldata
);
839 if (ph
) hw_protocol
= ntohs(ph
->hw_protocol
);
841 switch (hw_protocol
) {
843 print_iphdr(le
, payload
, payload_len
);
846 print_ip6hdr(le
, payload
, payload_len
);
849 print_arp(le
, (struct ether_arp
*)payload
, payload_len
);
855 if (mark
) LEPRINTF("mark=%u ", mark
);
863 nflog_cb(struct nflog_g_handle
*gh
, struct nfgenmsg
*nfmsg
,
864 struct nflog_data
*nfa
, void *data
)
866 struct log_entry
*le
= g_new0(struct log_entry
, 1);
868 print_pkt(le
, nfa
, nfmsg
->nfgen_family
);
870 LEPRINTF("\n"); // add newline
878 nflog_read_cb(GIOChannel
*source
,
879 GIOCondition condition
,
885 int fd
= g_io_channel_unix_get_fd(source
);
887 if ((rv
= recv(fd
, buf
, sizeof(buf
), 0)) && rv
>= 0) {
888 nflog_handle_packet(logh
, buf
, rv
);
895 nlif_read_cb(GIOChannel
*source
,
896 GIOCondition condition
,
899 static int last_res
= 0;
902 if ((res
= nlif_catch(nlifh
)) < 0) {
903 if (last_res
== 0) { // only report once
904 log_status_message(3, "nlif_catch failed (res = %d)", res
);
915 signal_read_cb(GIOChannel
*source
,
916 GIOCondition condition
,
920 struct signalfd_siginfo si
;
922 int fd
= g_io_channel_unix_get_fd(source
);
924 if ((rv
= read(fd
, &si
, sizeof(si
))) && rv
>= 0) {
925 terminate_threads
= TRUE
;
926 log_status_message(5, "received terminate request (signal)");
927 g_main_loop_quit(main_loop
);
934 nfct_cb(const struct nlmsghdr
*nlh
,
935 enum nf_conntrack_msg_type type
,
936 struct nf_conntrack
*ct
,
939 struct log_entry
*le
= g_new0(struct log_entry
, 1);
940 int len
= nfct_snprintf(&le
->buf
[le
->len
], LE_MAX
- le
->len
,
941 ct
, type
, NFCT_O_DEFAULT
,
942 NFCT_OF_SHOW_LAYER3
|NFCT_OF_TIMESTAMP
);
945 if (le
->len
== LE_MAX
) {
946 le
->buf
[le
->len
-1] = '\n';
947 } else { // le->len < LE_MAX
948 le
->buf
[le
->len
++] = '\n';
957 nfct_read_cb(GIOChannel
*source
,
958 GIOCondition condition
,
962 if ((res
= nfct_catch(nfcth
)) < 0) {
963 if (errno
== ENOBUFS
) {
964 log_status_message(3, "nfct_catch returned ENOBUFS: conntrack information may be incomplete");
966 log_status_message(3, "error catching nfct: %s", strerror(errno
));
974 main(int argc
, char *argv
[])
979 gboolean wrote_pidfile
= FALSE
;
981 openlog("pvefw-logger", LOG_CONS
|LOG_PID
, LOG_DAEMON
);
983 GOptionContext
*context
;
985 GOptionEntry entries
[] = {
986 { "debug", 'd', 0, G_OPTION_ARG_NONE
, &debug
, "Turn on debug messages", NULL
},
987 { "foreground", 'f', 0, G_OPTION_ARG_NONE
, &foreground
, "Do not daemonize server", NULL
},
988 { "conntrack", 0, 0, G_OPTION_ARG_NONE
, &conntrack
, "Add conntrack logging", NULL
},
992 context
= g_option_context_new("");
993 g_option_context_add_main_entries (context
, entries
, NULL
);
996 if (!g_option_context_parse (context
, &argc
, &argv
, &err
)) {
997 fprintf(stderr
, "error: %s\n", err
->message
);
998 fprintf(stderr
, "%s", g_option_context_get_help(context
, FALSE
, NULL
));
1003 if (optind
< argc
) {
1004 fprintf(stderr
, "error: too many arguments\n");
1005 fprintf(stderr
, "%s", g_option_context_get_help(context
, FALSE
, NULL
));
1009 g_option_context_free(context
);
1012 int log_nf_conntrackfd
= open(LOG_CONNTRACK_FILE
, O_RDONLY
);
1013 if (log_nf_conntrackfd
== -1) {
1014 if (errno
!= ENOENT
) {
1015 fprintf(stderr
, "error: failed to open "LOG_CONNTRACK_FILE
": %s\n", strerror(errno
));
1019 ssize_t bytes
= read(log_nf_conntrackfd
, &c
, sizeof(c
));
1021 fprintf(stderr
, "error: failed to read value in log_nf_conntrack: %s\n", strerror(errno
));
1023 conntrack
= (c
== '1');
1028 if (debug
) foreground
= TRUE
;
1030 if ((lockfd
= open(LOCKFILE
, O_RDWR
|O_CREAT
|O_APPEND
, 0644)) == -1) {
1031 fprintf(stderr
, "unable to create lock '%s': %s\n", LOCKFILE
, strerror (errno
) );
1035 for (int i
= 10; i
>= 0; i
--) {
1036 if (flock(lockfd
, LOCK_EX
|LOCK_NB
) != 0) {
1038 fprintf(stderr
, "unable to aquire lock '%s': %s\n", LOCKFILE
, strerror (errno
));
1042 fprintf(stderr
, "unable to aquire lock '%s' - trying again.\n", LOCKFILE
);
1048 if ((outfd
= open(LOGFILE
, O_WRONLY
|O_CREAT
|O_APPEND
, 0644)) == -1) {
1049 fprintf(stderr
, "unable to open file '%s': %s\n", LOGFILE
, strerror (errno
));
1053 if ((logh
= nflog_open()) == NULL
) {
1054 fprintf(stderr
, "unable to open nflog\n");
1058 if (nflog_bind_pf(logh
, AF_INET
) < 0) {
1059 fprintf(stderr
, "nflog_bind_pf AF_INET failed\n");
1064 if (!nflog_bind_pf(logh
, AF_INET6
) <= 0) {
1065 fprintf(stderr
, "nflog_bind_pf AF_INET6 failed\n");
1070 if (nflog_bind_pf(logh
, AF_BRIDGE
) < 0) {
1071 fprintf(stderr
, "nflog_bind_pf AF_BRIDGE failed\n");
1075 struct nflog_g_handle
*qh
= nflog_bind_group(logh
, 0);
1077 fprintf(stderr
, "no nflog handle for group 0\n");
1081 if (nflog_set_mode(qh
, NFULNL_COPY_PACKET
, 0xffff) < 0) {
1082 fprintf(stderr
, "can't set packet copy mode\n");
1086 if ((nlifh
= nlif_open()) == NULL
) {
1087 fprintf(stderr
, "unable to open netlink interface handle\n");
1092 if ((nfcth
= nfct_open(CONNTRACK
, NF_NETLINK_CONNTRACK_NEW
|NF_NETLINK_CONNTRACK_DESTROY
)) == NULL
) {
1093 fprintf(stderr
, "unable to open netfilter conntrack\n");
1100 sigaddset(&mask
, SIGINT
);
1101 sigaddset(&mask
, SIGTERM
);
1103 sigprocmask(SIG_BLOCK
, &mask
, NULL
);
1105 if ((sigfd
= signalfd(-1, &mask
, SFD_NONBLOCK
)) < 0) {
1106 fprintf(stderr
, "unable to open signalfd: %s\n", strerror (errno
));
1111 pid_t cpid
= fork();
1114 fprintf(stderr
, "failed to daemonize program - %s\n", strerror (errno
));
1117 write_pidfile(cpid
);
1122 if (chroot("/") != 0) fprintf(stderr
, "chroot '/' failed - %s\n", strerror (errno
));
1124 if ((nullfd
= open("/dev/null", O_RDWR
, 0)) != -1) {
1135 write_pidfile(getpid());
1138 wrote_pidfile
= TRUE
;
1140 nflog_callback_register(qh
, &nflog_cb
, logh
);
1142 queue
= g_async_queue_new_full(g_free
);
1144 log_status_message(5, "starting pvefw logger");
1148 GIOChannel
*nlif_ch
= g_io_channel_unix_new(nlif_fd(nlifh
));
1150 g_io_add_watch(nlif_ch
, G_IO_IN
, nlif_read_cb
, NULL
);
1152 int logfd
= nflog_fd(logh
);
1153 GIOChannel
*nflog_ch
= g_io_channel_unix_new(logfd
);
1155 g_io_add_watch(nflog_ch
, G_IO_IN
, nflog_read_cb
, NULL
);
1158 nfct_callback_register2(nfcth
, NFCT_T_NEW
|NFCT_T_DESTROY
, &nfct_cb
, NULL
);
1159 int nfctfd
= nfct_fd(nfcth
);
1160 GIOChannel
*nfct_ch
= g_io_channel_unix_new(nfctfd
);
1161 g_io_add_watch(nfct_ch
, G_IO_IN
, nfct_read_cb
, NULL
);
1164 GIOChannel
*sig_ch
= g_io_channel_unix_new(sigfd
);
1165 if (!g_io_add_watch(sig_ch
, G_IO_IN
, signal_read_cb
, NULL
)) {
1169 GThread
*wthread
= g_thread_new("log_writer_thread", log_writer_thread
, NULL
);
1171 main_loop
= g_main_loop_new(NULL
, TRUE
);
1173 g_main_loop_run(main_loop
);
1175 log_status_message(5, "stopping pvefw logger");
1177 g_thread_join(wthread
);
1182 nfct_callback_unregister2(nfcth
);