diff options
Diffstat (limited to 'src/libnetfilter_log.c')
-rw-r--r-- | src/libnetfilter_log.c | 302 |
1 files changed, 229 insertions, 73 deletions
diff --git a/src/libnetfilter_log.c b/src/libnetfilter_log.c index 567049c..339c961 100644 --- a/src/libnetfilter_log.c +++ b/src/libnetfilter_log.c @@ -4,7 +4,7 @@ * (C) 2005, 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org> * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 + * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation (or any later at your option) * * This program is distributed in the hope that it will be useful, @@ -33,6 +33,9 @@ #include <libnfnetlink/libnfnetlink.h> #include <libnetfilter_log/libnetfilter_log.h> +#include <libmnl/libmnl.h> +#include <linux/netfilter/nfnetlink_conntrack.h> + /** * \mainpage * @@ -82,7 +85,7 @@ struct nflog_g_handle int nflog_errno; /*********************************************************************** - * low level stuff + * low level stuff ***********************************************************************/ static void del_gh(struct nflog_g_handle *gh) @@ -158,11 +161,6 @@ static int __nflog_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[], return gh->cb(gh, nfmsg, &nfldata, gh->data); } -static struct nfnl_callback pkt_cb = { - .call = &__nflog_rcv_pkt, - .attr_count = NFULA_MAX, -}; - /* public interface */ struct nfnl_handle *nflog_nfnlh(struct nflog_handle *h) @@ -182,15 +180,15 @@ struct nfnl_handle *nflog_nfnlh(struct nflog_handle *h) * * Here's a little code snippet that binds to the group 100: * \verbatim - printf("binding this socket to group 0\n"); - qh = nflog_bind_group(h, 0); - if (!qh) { - fprintf(stderr, "no handle for grup 0\n"); + printf("binding this socket to group 100\n"); + gh = nflog_bind_group(h, 100); + if (!gh) { + fprintf(stderr, "no handle for group 100\n"); exit(1); } printf("setting copy_packet mode\n"); - if (nflog_set_mode(qh, NFULNL_COPY_PACKET, 0xffff) < 0) { + if (nflog_set_mode(gh, NFULNL_COPY_PACKET, 0xffff) < 0) { fprintf(stderr, "can't set packet copy mode\n"); exit(1); } @@ -207,22 +205,37 @@ struct nfnl_handle *nflog_nfnlh(struct nflog_handle *h) } \endverbatim * - * Data and information about the packet can be fetch by using message parsing - * functions (See \link Parsing \endlink). + * Data and information about the packet can be fetched by using message parsing + * \htmlonly + functions (See <a class="el" href="group__Parsing.html">Parsing</a>). +\endhtmlonly + * \manonly +functions. +.PP +\fBSee also:\fP +.RS 4 +\fBLibrarySetup\fP man page (\fBman nflog_open\fP) +.br +\fBParsing\fP man page (\fBman nflog_get_gid\fP) +.RE +.PP +.SH SYNOPSIS +.nf +\fB +#include <stddef.h> +#include <libnetfilter_log/libnetfilter_log.h> +\endmanonly * @{ */ /** * nflog_fd - get the file descriptor associated with the nflog handler - * \param log handler obtained via call to nflog_open() + * \param h handler obtained via call to nflog_open() * * \return a file descriptor for the netlink connection associated with the * given log connection handle. The file descriptor can then be used for * receiving the logged packets for processing. * - * This function returns a file descriptor that can be used for communication - * over the netlink connection associated with the given log connection - * handle. */ int nflog_fd(struct nflog_handle *h) { @@ -237,15 +250,18 @@ struct nflog_handle *nflog_open_nfnl(struct nfnl_handle *nfnlh) { struct nflog_handle *h; int err; + struct nfnl_callback pkt_cb = { + .call = &__nflog_rcv_pkt, + .attr_count = NFULA_MAX, + }; - h = malloc(sizeof(*h)); + h = calloc(1, sizeof(*h)); if (!h) return NULL; - memset(h, 0, sizeof(*h)); h->nfnlh = nfnlh; - h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_ULOG, + h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_ULOG, NFULNL_MSG_MAX, 0); if (!h->nfnlssh) { /* FIXME: nflog_errno */ @@ -280,7 +296,9 @@ out_free: * it by calling nflog_close(). A new netlink connection is obtained internally * and associated with the log connection handle returned. * - * \return a pointer to a new log handle or NULL on failure. + * \return a pointer to a new log handle or NULL on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ struct nflog_handle *nflog_open(void) { @@ -307,6 +325,20 @@ struct nflog_handle *nflog_open(void) * @} */ +/** + * \addtogroup Log + * @{ + */ + +/** + * nflog_callback_register - register function to process packets + * + * \param gh Netfilter log group handle obtained by call to nflog_bind_group() + * \param cb callback function to call for each logged packet + * \param data custom data to pass to the callback function + \return 0 + */ + int nflog_callback_register(struct nflog_g_handle *gh, nflog_callback *cb, void *data) { @@ -316,17 +348,42 @@ int nflog_callback_register(struct nflog_g_handle *gh, nflog_callback *cb, return 0; } +/** + * nflog_handle_packet - handle a packet received from the nflog subsystem + * \param h Netfilter log handle obtained via call to nflog_open() + * \param buf nflog data received from the kernel + * \param len length of packet data in buffer + * + * Triggers an associated callback for each packet contained in \b buf. + * Data can be read from the queue using nflog_fd() and \b recv(). + * See example code in the Detailed Description. + * \return 0 on success, -1 if either the callback returned -ve or \b buf + * contains corrupt data. \b errno is not reliably set: + * caller should zeroise first if interested. + */ + int nflog_handle_packet(struct nflog_handle *h, char *buf, int len) { return nfnl_handle_packet(h->nfnlh, buf, len); } /** + * @} + */ + +/** * \addtogroup LibrarySetup * * When the program has finished with libnetfilter_log, it has to call * the nflog_close() function to release all associated resources. * + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <netinet/in.h> +#include <libnetfilter_log/libnetfilter_log.h> +\endmanonly * @{ */ @@ -336,7 +393,9 @@ int nflog_handle_packet(struct nflog_handle *h, char *buf, int len) * * This function closes the nflog handler and free associated resources. * - * \return 0 on success, non-zero on failure. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * as for __close__(2) */ int nflog_close(struct nflog_handle *h) { @@ -353,7 +412,9 @@ int nflog_close(struct nflog_handle *h) * Binds the given log connection handle to process packets belonging to * the given protocol family (ie. PF_INET, PF_INET6, etc). * - * \return integer inferior to 0 in case of failure + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * \b EOPNOTSUPP Not running as root */ int nflog_bind_pf(struct nflog_handle *h, uint16_t pf) { @@ -368,6 +429,9 @@ int nflog_bind_pf(struct nflog_handle *h, uint16_t pf) * * Unbinds the given nflog handle from processing packets belonging * to the given protocol family. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * \b EOPNOTSUPP Not running as root */ int nflog_unbind_pf(struct nflog_handle *h, uint16_t pf) { @@ -388,21 +452,27 @@ int nflog_unbind_pf(struct nflog_handle *h, uint16_t pf) * \param h Netfilter log handle obtained via call to nflog_open() * \param num the number of the group to bind to * - * \return a nflog_g_handle pointing to the newly created group + * \return an nflog_g_handle for the newly created group or NULL on failure. + * \par Errors + * \b EBUSY This process has already binded to the group + * \n + * \b EOPNOTSUPP Request rejected by kernel. Another process has already + * binded to the group, or this process is not running as root */ struct nflog_g_handle * nflog_bind_group(struct nflog_handle *h, uint16_t num) { struct nflog_g_handle *gh; - - if (find_gh(h, num)) + + if (find_gh(h, num)) { + errno = EBUSY; return NULL; - - gh = malloc(sizeof(*gh)); + } + + gh = calloc(1, sizeof(*gh)); if (!gh) return NULL; - memset(gh, 0, sizeof(*gh)); gh->h = h; gh->id = num; @@ -428,7 +498,9 @@ nflog_bind_group(struct nflog_handle *h, uint16_t num) * nflog_unbind_group - unbind a group handle. * \param gh Netfilter log group handle obtained via nflog_bind_group() * - * \return -1 in case of error and errno is explicity in case of error. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_unbind_group(struct nflog_g_handle *gh) { @@ -443,7 +515,7 @@ int nflog_unbind_group(struct nflog_g_handle *gh) /** * nflog_set_mode - set the amount of packet data that nflog copies to userspace - * \param qh Netfilter log handle obtained by call to nflog_bind_group(). + * \param gh Netfilter log group handle obtained by call to nflog_bind_group(). * \param mode the part of the packet that we are interested in * \param range size of the packet that we want to get * @@ -454,7 +526,9 @@ int nflog_unbind_group(struct nflog_g_handle *gh) * - NFULNL_COPY_META - copy only packet metadata * - NFULNL_COPY_PACKET - copy entire packet * - * \return -1 on error; >= otherwise. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_set_mode(struct nflog_g_handle *gh, uint8_t mode, uint32_t range) @@ -479,15 +553,17 @@ int nflog_set_mode(struct nflog_g_handle *gh, /** * nflog_set_timeout - set the maximum time to push log buffer for this group - * \param gh Netfilter log handle obtained by call to nflog_bind_group(). + * \param gh Netfilter log group handle obtained by call to nflog_bind_group(). * \param timeout Time to wait until the log buffer is pushed to userspace * - * This function allows to set the maximum time that nflog waits until it + * This function allows one to set the maximum time that nflog waits until it * pushes the log buffer to userspace if no new logged packets have occured. * Basically, nflog implements a buffer to reduce the computational cost * of delivering the log message to userspace. * - * \return -1 in case of error and errno is explicity set. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_set_timeout(struct nflog_g_handle *gh, uint32_t timeout) { @@ -506,13 +582,15 @@ int nflog_set_timeout(struct nflog_g_handle *gh, uint32_t timeout) /** * nflog_set_qthresh - set the maximum amount of logs in buffer for this group - * \param gh Netfilter log handle obtained by call to nflog_bind_group(). + * \param gh Netfilter log group handle obtained by call to nflog_bind_group(). * \param qthresh Maximum number of log entries * * This function determines the maximum number of log entries in the buffer * until it is pushed to userspace. * - * \return -1 in case of error and errno is explicity set. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_set_qthresh(struct nflog_g_handle *gh, uint32_t qthresh) { @@ -531,17 +609,19 @@ int nflog_set_qthresh(struct nflog_g_handle *gh, uint32_t qthresh) /** * nflog_set_nlbufsiz - set the size of the nflog buffer for this group - * \param gh Netfilter log handle obtained by call to nflog_bind_group(). + * \param gh Netfilter log group handle obtained by call to nflog_bind_group(). * \param nlbufsiz Size of the nflog buffer * * This function sets the size (in bytes) of the buffer that is used to * stack log messages in nflog. * - * NOTE: The use of this function is strongly discouraged. The default + * \warning The use of this function is strongly discouraged. The default * buffer size (which is one memory page) provides the optimum results * in terms of performance. Do not use this function in your applications. * - * \return -1 in case of error and errno is explicity set. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_set_nlbufsiz(struct nflog_g_handle *gh, uint32_t nlbufsiz) { @@ -567,15 +647,18 @@ int nflog_set_nlbufsiz(struct nflog_g_handle *gh, uint32_t nlbufsiz) /** * nflog_set_flags - set the nflog flags for this group - * \param gh Netfilter log handle obtained by call to nflog_bind_group(). + * \param gh Netfilter log group handle obtained by call to nflog_bind_group(). * \param flags Flags that you want to set * * There are two existing flags: * * - NFULNL_CFG_F_SEQ: This enables local nflog sequence numbering. * - NFULNL_CFG_F_SEQ_GLOBAL: This enables global nflog sequence numbering. + * - NFULNL_CFG_F_CONNTRACK: This enables to acquire related conntrack. * - * \return -1 in case of error and errno is explicity set. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_set_flags(struct nflog_g_handle *gh, uint16_t flags) { @@ -598,6 +681,13 @@ int nflog_set_flags(struct nflog_g_handle *gh, uint16_t flags) /** * \defgroup Parsing Message parsing functions + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <stddef.h> +#include <libnetfilter_log/libnetfilter_log.h> +\endmanonly * @{ */ @@ -612,8 +702,8 @@ int nflog_set_flags(struct nflog_g_handle *gh, uint16_t flags) * The nfulnl_msg_packet_hdr structure is defined in libnetfilter_log.h as: *\verbatim struct nfulnl_msg_packet_hdr { - uint16_t hw_protocol; // hw protocol (network order) - uint8_t hook; // netfilter hook + uint16_t hw_protocol; // hw protocol (network order) + uint8_t hook; // netfilter hook uint8_t _pad; } __attribute__ ((packed)); \endverbatim @@ -673,9 +763,11 @@ uint32_t nflog_get_nfmark(struct nflog_data *nfad) * \param nfad Netlink packet data handle passed to callback function * \param tv structure to fill with timestamp info * - * Retrieves the received timestamp when the given logged packet. + * Retrieves the received timestamp from the given logged packet. * - * \return 0 on success, a negative value on failure. + * \return 0 on success, -1 on failure with \b errno set. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_get_timestamp(struct nflog_data *nfad, struct timeval *tv) { @@ -700,8 +792,8 @@ int nflog_get_timestamp(struct nflog_data *nfad, struct timeval *tv) * returned index is 0, the packet was locally generated or the input * interface is not known (ie. POSTROUTING?). * - * \warning all nflog_get_dev() functions return 0 if not set, since linux - * only allows ifindex >= 1, see net/core/dev.c:2600 (in 2.6.13.1) + * \warning all nflog_get_dev() functions return 0 if not set, since Linux + * only allows ifindex >= 1, see net/core/dev.c:9819 (in 5.14.3) */ uint32_t nflog_get_indev(struct nflog_data *nfad) { @@ -710,6 +802,7 @@ uint32_t nflog_get_indev(struct nflog_data *nfad) /** * nflog_get_physindev - get the physical interface that the packet was received + * through * \param nfad Netlink packet data handle passed to callback function * * \return The index of the physical device the packet was received via. @@ -722,10 +815,10 @@ uint32_t nflog_get_physindev(struct nflog_data *nfad) } /** - * nflog_get_outdev - gets the interface that the packet will be routed out + * nflog_get_outdev - gets the interface that the packet will be routed to * \param nfad Netlink packet data handle passed to callback function * - * \return The index of the device the packet will be sent out. If the + * \return The index of the device the packet will be sent to. If the * returned index is 0, the packet is destined for localhost or the output * interface is not yet known (ie. PREROUTING?). */ @@ -735,15 +828,12 @@ uint32_t nflog_get_outdev(struct nflog_data *nfad) } /** - * nflog_get_physoutdev - get the physical interface that the packet output + * nflog_get_physoutdev - get the physical interface for packet output * \param nfad Netlink packet data handle passed to callback function * - * The index of the physical device the packet will be sent out. If the + * \return Index of physical device the packet will be routed to. If the * returned index is 0, the packet is destined for localhost or the * physical output interface is not yet known (ie. PREROUTING?). - * - * \return The index of physical interface that the packet output will be - * routed out. */ uint32_t nflog_get_physoutdev(struct nflog_data *nfad) { @@ -762,12 +852,16 @@ uint32_t nflog_get_physoutdev(struct nflog_data *nfad) * * The nfulnl_msg_packet_hw structure is defined in libnetfilter_log.h as: * \verbatim - struct nfulnl_msg_packet_hw { - uint16_t hw_addrlen; - uint16_t _pad; - uint8_t hw_addr[8]; - } __attribute__ ((packed)); + struct nfulnl_msg_packet_hw { + uint16_t hw_addrlen; // Network Byte Order + uint16_t _pad; + uint8_t hw_addr[8]; + } __attribute__ ((packed)); \endverbatim + * + * \return Pointer to struct nfulnl_msg_packet_hw from originating host + * or NULL if none available (e.g. locally-originated packet not for \b lo + * interface). */ struct nfulnl_msg_packet_hw *nflog_get_packet_hw(struct nflog_data *nfad) { @@ -784,7 +878,7 @@ struct nfulnl_msg_packet_hw *nflog_get_packet_hw(struct nflog_data *nfad) * data retrieved by this function will depend on the mode set with the * nflog_set_mode() function. * - * \return -1 on error, otherwise > 0. + * \return payload length, or -1 if this is not available */ int nflog_get_payload(struct nflog_data *nfad, char **data) { @@ -800,7 +894,7 @@ int nflog_get_payload(struct nflog_data *nfad, char **data) * \param nfad Netlink packet data handle passed to callback function * * \return the string prefix that is specified as argument to the iptables' - * NFLOG target. + * NFLOG target or NULL if this is not available. */ char *nflog_get_prefix(struct nflog_data *nfad) { @@ -808,10 +902,13 @@ char *nflog_get_prefix(struct nflog_data *nfad) } /** - * nflog_get_uid - get the UID of the user that has generated the packet + * nflog_get_uid - get the UID of the user that generated the packet * \param nfad Netlink packet data handle passed to callback function + * \param uid UID of the user that generated the packet, + * if the function returns zero * - * \return the UID of the user that has genered the packet, if any. + * \return 0 on success or -1 if UID was unavailable (\b uid + * is then invalid) */ int nflog_get_uid(struct nflog_data *nfad, uint32_t *uid) { @@ -825,8 +922,11 @@ int nflog_get_uid(struct nflog_data *nfad, uint32_t *uid) /** * nflog_get_gid - get the GID of the user that has generated the packet * \param nfad Netlink packet data handle passed to callback function + * \param gid GID of the user that generated the packet, + * if the function returns zero * - * \return the GID of the user that has genered the packet, if any. + * \return 0 on success or -1 if GID was unavailable (\b gid + * is then invalid) */ int nflog_get_gid(struct nflog_data *nfad, uint32_t *gid) { @@ -840,10 +940,13 @@ int nflog_get_gid(struct nflog_data *nfad, uint32_t *gid) /** * nflog_get_seq - get the local nflog sequence number * \param nfad Netlink packet data handle passed to callback function + * \param seq local nflog sequence number, + * if the function returns zero * * You must enable this via nflog_set_flags(). * - * \return the local nflog sequence number. + * \return 0 on success or -1 if sequence number was unavailable (\b seq + * is then invalid) */ int nflog_get_seq(struct nflog_data *nfad, uint32_t *seq) { @@ -857,10 +960,13 @@ int nflog_get_seq(struct nflog_data *nfad, uint32_t *seq) /** * nflog_get_seq_global - get the global nflog sequence number * \param nfad Netlink packet data handle passed to callback function + * \param seq global nflog sequence number, + * if the function returns zero * * You must enable this via nflog_set_flags(). * - * \return the global nflog sequence number. + * \return 0 on success or -1 if sequence number was unavailable (\b seq + * is then invalid) */ int nflog_get_seq_global(struct nflog_data *nfad, uint32_t *seq) { @@ -872,6 +978,38 @@ int nflog_get_seq_global(struct nflog_data *nfad, uint32_t *seq) } /** + * nflog_get_ct_id - get the conntrack id + * \param nfad Netlink packet data handle passed to callback function + * \param id conntrack id, if the function returns zero + * + * You must enable this via nflog_set_flags(). + * + * \return 0 on success or -1 if conntrack itself or its id was unavailable + */ +int nflog_get_ctid(struct nflog_data *nfad, uint32_t *id) +{ + struct nlattr *cta = (struct nlattr *)nfad->nfa[NFULA_CT - 1]; + struct nlattr *attr, *ida = NULL; + + if (!cta) + return -1; + + mnl_attr_for_each_nested(attr, cta) { + if (mnl_attr_get_type(attr) == CTA_ID) { + ida = attr; + break; + } + } + + if (!ida || mnl_attr_validate(ida, MNL_TYPE_U32) < 0) + return -1; + + *id = ntohl(mnl_attr_get_u32(ida)); + + return 0; +} + +/** * @} */ @@ -887,7 +1025,13 @@ do { \ } while (0) /** - * \defgroup Printing + * \defgroup Printing Printing + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <libnetfilter_log/libnetfilter_log.h> +\endmanonly * @{ */ @@ -907,20 +1051,23 @@ do { \ * - NFLOG_XML_PHYSDEV: include the physical device information * - NFLOG_XML_PAYLOAD: include the payload (in hexadecimal) * - NFLOG_XML_TIME: include the timestamp + * - NFLOG_XML_CTID: include conntrack id * - NFLOG_XML_ALL: include all the logging information (all flags set) * - * You can combine this flags with an binary OR. + * You can combine these flags with a bitwise OR. * * \return -1 in case of failure, otherwise the length of the string that * would have been printed into the buffer (in case that there is enough * room in it). See snprintf() return value for more information. + * \par Errors + * from underlying calls, in exceptional circumstances */ int nflog_snprintf_xml(char *buf, size_t rem, struct nflog_data *tb, int flags) { - struct nfulnl_msg_packet_hdr *ph; - struct nfulnl_msg_packet_hw *hwph; - uint32_t mark, ifi; int size, offset = 0, len = 0, ret; + struct nfulnl_msg_packet_hw *hwph; + struct nfulnl_msg_packet_hdr *ph; + uint32_t mark, ifi, ctid; char *data; size = snprintf(buf + offset, rem, "<log>"); @@ -1039,6 +1186,15 @@ int nflog_snprintf_xml(char *buf, size_t rem, struct nflog_data *tb, int flags) SNPRINTF_FAILURE(size, rem, offset, len); } + if (flags & NFLOG_XML_CTID) { + ret = nflog_get_ctid(tb, &ctid); + if (ret >= 0) { + size = snprintf(buf + offset, rem, + "<ctid>%u</ctid>", ctid); + SNPRINTF_FAILURE(size, rem, offset, len); + } + } + ret = nflog_get_payload(tb, &data); if (ret >= 0 && (flags & NFLOG_XML_PAYLOAD)) { int i; |