From cde6011a7a58af2c6431f34c24b07c7d9338d6ea 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, 6 Aug 2005 22:19:45 +0000 Subject: - don't export internals of handle data structure to users - dynamically allocate handler at callee. - add more convenient callback_register() / handle_packet() api - add internal linked list of group handles and lookup/management functions - merge changes into compatibility library --- include/libnfnetlink_log/libnfnetlink_log.h | 33 +++--- src/libipulog_compat.c | 20 ++-- src/libnfnetlink_log.c | 175 +++++++++++++++++++++++++--- 3 files changed, 186 insertions(+), 42 deletions(-) diff --git a/include/libnfnetlink_log/libnfnetlink_log.h b/include/libnfnetlink_log/libnfnetlink_log.h index 10345fd..4815bf3 100644 --- a/include/libnfnetlink_log/libnfnetlink_log.h +++ b/include/libnfnetlink_log/libnfnetlink_log.h @@ -13,36 +13,33 @@ #include #include +struct nfulnl_handle; +struct nfulnl_g_handle; -struct nfulnl_handle -{ - struct nfnl_handle nfnlh; -}; +extern struct nfnl_handle *nfulnl_nfnlh(struct nfulnl_handle *h); -struct nfulnl_g_handle -{ - struct nfulnl_handle *h; - u_int16_t id; -}; +typedef nfulnl_callback(struct nfulnl_g_handle *gh, struct nfgenmsg *nfmsg, + struct nfattr *nfa[], void *data); -struct ctnl_msg_handler { - int type; - int (*handler)(struct sockaddr_nl *, struct nlmsghdr *, void *arg); -}; -extern int nfulnl_open(struct nfulnl_handle *h); +extern struct nfulnl_handle *nfulnl_open(void); extern int nfulnl_close(struct nfulnl_handle *h); extern int nfulnl_bind_pf(struct nfulnl_handle *h, u_int16_t pf); extern int nfulnl_unbind_pf(struct nfulnl_handle *h, u_int16_t pf); -extern int nfulnl_bind_group(struct nfulnl_handle *h, - struct nfulnl_g_handle *qh, u_int16_t num); -extern int nfulnl_unbind_group(struct nfulnl_g_handle *qh); +extern struct nfulnl_g_handle *nfulnl_bind_group(struct nfulnl_handle *h, + u_int16_t num); +extern int nfulnl_unbind_group(struct nfulnl_g_handle *gh); -extern int nfulnl_set_mode(struct nfulnl_g_handle *qh, +extern int nfulnl_set_mode(struct nfulnl_g_handle *gh, u_int8_t mode, unsigned int len); extern int nfulnl_set_timeout(struct nfulnl_g_handle *gh, u_int32_t timeout); extern int nfulnl_set_qthresh(struct nfulnl_g_handle *gh, u_int32_t qthresh); extern int nfulnl_set_nlbufsiz(struct nfulnl_g_handle *gh, u_int32_t nlbufsiz); + +extern int nfulnl_callback_register(struct nfulnl_g_handle *gh, + nfulnl_callback *cb, void *data); +extern int nfulnl_handle_packet(struct nfulnl_handle *h, char *buf, int len); + #endif /* __LIBNFNETLINK_LOG_H */ diff --git a/src/libipulog_compat.c b/src/libipulog_compat.c index b6fc82e..d981e94 100644 --- a/src/libipulog_compat.c +++ b/src/libipulog_compat.c @@ -14,8 +14,8 @@ struct ipulog_handle { - struct nfulnl_handle nfulh; - struct nfulnl_g_handle nful_gh; + struct nfulnl_handle *nfulh; + struct nfulnl_g_handle *nful_gh; struct nlmsghdr *last_nlh; #if 0 int fd; @@ -94,13 +94,15 @@ struct ipulog_handle *ipulog_create_handle(u_int32_t gmask, return NULL; } memset(h, 0, sizeof(*h)); - if (nfulnl_open(&h->nfulh) < 0) + h->nfulh = nfulnl_open(); + if (!h->nfulh) goto out_free; - if (nfulnl_bind_pf(&h->nfulh, AF_INET) < 0) + if (nfulnl_bind_pf(h->nfulh, AF_INET) < 0) goto out_free; - if (nfulnl_bind_group(&h->nfulh, &h->nful_gh, group) < 0) + h->nful_gh = nfulnl_bind_group(h->nfulh, group); + if (!h->nful_gh) goto out_free; return h; @@ -113,8 +115,8 @@ out_free: void ipulog_destroy_handle(struct ipulog_handle *h) { - nfulnl_unbind_group(&h->nful_gh); - nfulnl_close(&h->nfulh); + nfulnl_unbind_group(h->nful_gh); + nfulnl_close(h->nfulh); free(h); } @@ -127,10 +129,10 @@ ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h, struct nfulnl_msg_packet_hdr *hdr; if (!h->last_nlh) - nlh = nfnl_get_msg_first(&h->nfulh.nfnlh, buf, len); + nlh = nfnl_get_msg_first(nfulnl_nfnlh(h->nfulh), buf, len); else { next_msg: - nlh = nfnl_get_msg_next(&h->nfulh.nfnlh, buf, len); + nlh = nfnl_get_msg_next(nfulnl_nfnlh(h->nfulh), buf, len); } h->last_nlh = nlh; diff --git a/src/libnfnetlink_log.c b/src/libnfnetlink_log.c index d0bd124..e497850 100644 --- a/src/libnfnetlink_log.c +++ b/src/libnfnetlink_log.c @@ -28,31 +28,74 @@ #include #include #include +#include #include #define HEADER_LEN (NLMSG_LENGTH(sizeof(struct nlmsghdr)) \ +NLMSG_LENGTH(sizeof(struct nfgenmsg))) +struct nfulnl_handle +{ + struct nfnl_handle nfnlh; + struct nfulnl_g_handle *gh_list; +}; + +struct nfulnl_g_handle +{ + struct nfulnl_g_handle *next; + struct nfulnl_handle *h; + u_int16_t id; + + nfulnl_callback *cb; + void *data; +}; + +static int nfulnl_errno; + /*********************************************************************** * low level stuff ***********************************************************************/ -int nfulnl_open(struct nfulnl_handle *h) +static void del_gh(struct nfulnl_g_handle *gh) { - int err; + struct nfulnl_g_handle *cur_gh, *prev_gh = NULL; + + for (cur_gh = gh->h->gh_list; cur_gh; cur_gh = cur_gh->next) { + if (cur_gh == gh) { + if (prev_gh) + prev_gh->next = gh->next; + else + gh->h->gh_list = gh->next; + return; + } + prev_gh = cur_gh; + } +} - memset(h, 0, sizeof(*h)); +static void add_gh(struct nfulnl_g_handle *gh) +{ + gh->next = gh->h->gh_list; + gh->h->gh_list = gh; +} - err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_ULOG, 0); - if (err < 0) - return err; +static struct nfulnl_g_handle *find_gh(struct nfulnl_handle *h, u_int16_t group) +{ + struct nfulnl_g_handle *gh; - return 0; + for (gh = h->gh_list; gh; gh = gh->next) { + if (gh->id == group) + return gh; + } + return NULL; } -int nfulnl_close(struct nfulnl_handle *h) +static int __nfulnl_rcv_cmd(struct nlmsghdr *nlh, struct nfattr *nfa[], + void *data) { - return nfnl_close(&h->nfnlh); + struct nfulnl_handle *h = data; + + /* FIXME: implement this */ + return 0; } /* build a NFULNL_MSG_CONFIG message */ @@ -73,6 +116,89 @@ __build_send_cfg_msg(struct nfulnl_handle *h, u_int8_t command, return nfnl_send(&h->nfnlh, nmh); } +static int __nfulnl_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[], + void *data) +{ + struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfulnl_handle *h = data; + u_int16_t group = ntohl(nfmsg->res_id); + struct nfulnl_g_handle *gh = find_gh(h, group); + + if (!gh) + return -EEXIST; + + return gh->cb(gh, nfmsg, nfa, gh->data); +} + +struct nfnl_callback cmd_cb = { + .call = &__nfulnl_rcv_cmd, + .attr_count = NFULA_CFG_MAX, +}; + +struct nfnl_callback pkt_cb = { + .call = &__nfulnl_rcv_pkt, + .attr_count = NFULA_MAX, +}; + +struct nfnl_handle *nfulnl_nfnlh(struct nfulnl_handle *h) +{ + return &h->nfnlh; +} + +struct nfulnl_handle *nfulnl_open(void) +{ + struct nfulnl_handle *h; + int err; + + h = malloc(sizeof(*h)); + if (!h) + return NULL; + + memset(h, 0, sizeof(*h)); + + err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_ULOG, NFULNL_MSG_MAX, 0); + if (err < 0) { + nfulnl_errno = err; + return NULL; + } + + cmd_cb.data = h; + err = nfnl_callback_register(&h->nfnlh, NFULNL_MSG_CONFIG, &cmd_cb); + if (err < 0) { + nfnl_close(&h->nfnlh); + nfulnl_errno = err; + return NULL; + } + pkt_cb.data = h; + err = nfnl_callback_register(&h->nfnlh, NFULNL_MSG_PACKET, &pkt_cb); + if (err < 0) { + nfnl_close(&h->nfnlh); + nfulnl_errno = err; + return NULL; + } + + return h; +} + +int nfulnl_callback_register(struct nfulnl_g_handle *gh, nfulnl_callback *cb, + void *data) +{ + gh->data = data; + gh->cb = cb; + + return 0; +} + +int nfulnl_handle_packet(struct nfulnl_handle *h, char *buf, int len) +{ + return nfnl_handle_packet(&h->nfnlh, buf, len); +} + +int nfulnl_close(struct nfulnl_handle *h) +{ + return nfnl_close(&h->nfnlh); +} + /* bind nf_queue from a specific protocol family */ int nfulnl_bind_pf(struct nfulnl_handle *h, u_int16_t pf) { @@ -86,21 +212,39 @@ int nfulnl_unbind_pf(struct nfulnl_handle *h, u_int16_t pf) } /* bind this socket to a specific queue number */ -int nfulnl_bind_group(struct nfulnl_handle *h, - struct nfulnl_g_handle *gh, u_int16_t num) +struct nfulnl_g_handle * +nfulnl_bind_group(struct nfulnl_handle *h, u_int16_t num) { + struct nfulnl_g_handle *gh; + + if (find_gh(h, num)) + return NULL; + + gh = malloc(sizeof(*gh)); + if (!gh) + return NULL; + + memset(gh, 0, sizeof(*gh)); gh->h = h; gh->id = num; - return __build_send_cfg_msg(h, NFULNL_CFG_CMD_BIND, num, 0); + if (__build_send_cfg_msg(h, NFULNL_CFG_CMD_BIND, num, 0) < 0) { + free(gh); + return NULL; + } + + add_gh(gh); + return gh; } /* unbind this socket from a specific queue number */ int nfulnl_unbind_group(struct nfulnl_g_handle *gh) { int ret = __build_send_cfg_msg(gh->h, NFULNL_CFG_CMD_UNBIND, gh->id, 0); - if (ret == 0) - gh->h = NULL; + if (ret == 0) { + del_gh(gh); + free(gh); + } return ret; } @@ -166,5 +310,6 @@ int nfulnl_set_nlbufsiz(struct nfulnl_g_handle *gh, u_int32_t nlbufsiz) /* we try to have space for at least 10 messages in the socket buffer */ if (status >= 0) nfnl_rcvbufsiz(&gh->h->nfnlh, 10*nlbufsiz); -} + return status; +} -- cgit v1.2.3