From 2ae5bdfb8261e491d2778f3455e2f827306acd14 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Sat, 30 Jul 2005 16:49:57 +0000 Subject: initial (incomplete) backwards compatibility libipulug api --- _log/src/libipulog_compat.c | 213 ++++++++++++++++++++++++++++++++++++++++++++ _log/src/libnfnetlink_log.c | 9 +- 2 files changed, 220 insertions(+), 2 deletions(-) diff --git a/_log/src/libipulog_compat.c b/_log/src/libipulog_compat.c index e69de29..b59d55a 100644 --- a/_log/src/libipulog_compat.c +++ b/_log/src/libipulog_compat.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* private */ +#define PAYLOAD_SIZE 0xffff + + +struct ipulog_handle +{ + struct nfulnl_handle nfulh; + struct nfulnl_g_handle nful_gh; + struct nlmsghdr *last_nlh; +#if 0 + int fd; + u_int8_t blocking; + struct sockaddr_nl local; + struct sockaddr_nl peer; +#endif + struct ulog_packet_msg upmsg; /* has to be last in structure */ +}; + +struct ipulog_errmap_t +{ + int errcode; + char *message; +} ipulog_errmap[] = +{ + { IPULOG_ERR_NONE, "No error" }, + { IPULOG_ERR_IMPL, "Not implemented yet" }, + { IPULOG_ERR_HANDLE, "Unable to create netlink handle" }, + { IPULOG_ERR_SOCKET, "Unable to create netlink socket" }, + { IPULOG_ERR_BIND, "Unable to bind netlink socket" }, + { IPULOG_ERR_RECVBUF, "Receive buffer size invalid" }, + { IPULOG_ERR_RECV, "Error during netlink receive" }, + { IPULOG_ERR_NLEOF, "Received EOF on netlink socket" }, + { IPULOG_ERR_TRUNC, "Receive message truncated" }, + { IPULOG_ERR_INVGR, "Invalid group specified" }, + { IPULOG_ERR_INVNL, "Invalid netlink message" }, +}; + +/* obviously this only finds the highest group in the mask */ +static unsigned int gmask2group(unsigned int gmask) +{ + int bit; + + for (bit = sizeof(gmask)*4 -1; bit >= 0; bit--) { + if (gmask & (1 << bit)) + return bit+1; + } + return 0; +} + + + +/* public */ + +int ipulog_errno = IPULOG_ERR_NONE; + +char *ipulog_strerror(int errcode) +{ + if (errcode < 0 || errcode > IPULOG_MAXERR) + errcode = IPULOG_ERR_IMPL; + return ipulog_errmap[errcode].message; +} + +/* convert a netlink group (1-32) to a group_mask suitable for create_handle */ +u_int32_t ipulog_group2gmask(u_int32_t group) +{ + if (group < 1 || group > 32) + { + ipulog_errno = IPULOG_ERR_INVGR; + return 0; + } + return (1 << (group - 1)); +} + +/* create a ipulog handle for the reception of packets sent to gmask */ +struct ipulog_handle *ipulog_create_handle(u_int32_t gmask, + u_int32_t rcvbufsize) +{ + struct ipulog_handle *h; + unsigned int group = gmask2group(gmask); + + h = (struct ipulog_handle *) malloc(sizeof(*h)+PAYLOAD_SIZE); + if (! h) { + ipulog_errno = IPULOG_ERR_HANDLE; + return NULL; + } + memset(h, 0, sizeof(*h)); + if (nfulnl_open(&h->nfulh) < 0) + goto out_free; + + if (nfulnl_bind_pf(&h->nfulh, AF_INET) < 0) + goto out_free; + + if (nfulnl_bind_group(&h->nfulh, &h->nful_gh, group) < 0) + goto out_free; + + return h; + +out_free: + ipulog_errno = IPULOG_ERR_HANDLE; + free(h); + return NULL; +} + +void ipulog_destroy_handle(struct ipulog_handle *h) +{ + nfulnl_unbind_group(&h->nful_gh); + nfulnl_close(&h->nfulh); + free(h); +} + +ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h, + const unsigned char *buf, + size_t len) +{ + struct nlmsghdr *nlh; + struct nfattr *tb[NFULA_MAX]; + struct nfulnl_msg_packet_hdr *hdr; + + if (!h->last_nlh) + nlh = nfnl_get_msg_first(&h->nfulh.nfnlh, buf, len); + else + nlh = nfnl_get_msg_next(&h->nfulh.nfnlh, buf, len); + h->last_nlh = nlh; + + if (!nlh) + return NULL; + + nfnl_parse_attr(tb, NFULA_MAX, NFM_NFA(nlh), NFM_PAYLOAD(nlh)); + + if (!tb[NFULA_PACKET_HDR-1]) { + /* ERROR */ + } + hdr = NFA_DATA(tb[NFULA_PACKET_HDR-1]); + + h->upmsg.hook = hdr->hook; + if (tb[NFULA_MARK-1]) + h->upmsg.mark = ntohl(*(u_int32_t *)NFA_DATA(tb[NFULA_MARK-1])); + else + h->upmsg.mark = 0; + + if (tb[NFULA_TIMESTAMP]) { + /* FIXME: 64bit network-to-host */ + h->upmsg.timestamp_sec = h->upmsg.timestamp_usec = 0; + } else + h->upmsg.timestamp_sec = h->upmsg.timestamp_usec = 0; + + if (tb[NFULA_IFINDEX_INDEV-1]) { + /* FIXME: ifindex lookup */ + h->upmsg.indev_name[0] = '\0'; + } else + h->upmsg.indev_name[0] = '\0'; + + if (tb[NFULA_IFINDEX_OUTDEV-1]) { + /* FIXME: ifindex lookup */ + h->upmsg.outdev_name[0] = '\0'; + } else + h->upmsg.outdev_name[0] = '\0'; + + if (tb[NFULA_HWADDR-1]) { + struct nfulnl_msg_packet_hw *phw = NFA_DATA(tb[NFULA_HWADDR-1]); + h->upmsg.mac_len = ntohs(phw->hw_addrlen); + memcpy(h->upmsg.mac, phw->hw_addr, 8); + } else + h->upmsg.mac_len = 0; + + if (tb[NFULA_PREFIX-1]) { + int plen = NFA_PAYLOAD(tb[NFULA_PREFIX-1]); + if (ULOG_PREFIX_LEN < plen) + plen = ULOG_PREFIX_LEN; + memcpy(h->upmsg.prefix, NFA_DATA(tb[NFULA_PREFIX-1]), plen); + h->upmsg.prefix[ULOG_PREFIX_LEN-1] = '\0'; + } + + if (tb[NFULA_PAYLOAD-1]) { + memcpy(h->upmsg.payload, NFA_DATA(tb[NFULA_PAYLOAD-1]), + NFA_PAYLOAD(tb[NFULA_PAYLOAD-1])); + h->upmsg.data_len = NFA_PAYLOAD(tb[NFULA_PAYLOAD-1]); + } else + h->upmsg.data_len = 0; + + return &h->upmsg; +} + +ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf, + size_t len, int timeout) +{ + //return nfnl_listen(); +} + +/* print a human readable description of the last error to stderr */ +void ipulog_perror(const char *s) +{ + if (s) + fputs(s, stderr); + else + fputs("ERROR", stderr); + if (ipulog_errno) + fprintf(stderr, ": %s", ipulog_strerror(ipulog_errno)); + if (errno) + fprintf(stderr, ": %s", strerror(errno)); + fputc('\n', stderr); +} + diff --git a/_log/src/libnfnetlink_log.c b/_log/src/libnfnetlink_log.c index 5bf2264..d0bd124 100644 --- a/_log/src/libnfnetlink_log.c +++ b/_log/src/libnfnetlink_log.c @@ -28,7 +28,7 @@ #include #include #include -#include "libnfnetlink_log.h" +#include #define HEADER_LEN (NLMSG_LENGTH(sizeof(struct nlmsghdr)) \ +NLMSG_LENGTH(sizeof(struct nfgenmsg))) @@ -154,12 +154,17 @@ int nfulnl_set_nlbufsiz(struct nfulnl_g_handle *gh, u_int32_t nlbufsiz) { char buf[HEADER_LEN+NFA_LENGTH(sizeof(u_int32_t))]; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; + int status; nfnl_fill_hdr(&gh->h->nfnlh, nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); nfnl_addattr32(nmh, sizeof(buf), NFULA_CFG_NLBUFSIZ, htonl(nlbufsiz)); - return nfnl_send(&gh->h->nfnlh, nmh); + status = nfnl_send(&gh->h->nfnlh, nmh); + + /* we try to have space for at least 10 messages in the socket buffer */ + if (status >= 0) + nfnl_rcvbufsiz(&gh->h->nfnlh, 10*nlbufsiz); } -- cgit v1.2.3