/* * (C) 2005-2011 by Pablo Neira Ayuso * Harald Welte * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include "internal/internal.h" struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh, uint8_t subsys_id, unsigned int subscriptions) { return nfct_open_nfnl2(nfnlh, subsys_id, subscriptions, true); } struct nfct_handle *nfct_open_nfnl2(struct nfnl_handle *nfnlh, uint8_t subsys_id, unsigned int subscriptions, bool bind) { struct nfct_handle *cth; cth = malloc(sizeof(struct nfct_handle)); if (!cth) return NULL; memset(cth, 0, sizeof(*cth)); cth->nfnlh = nfnlh; if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK) { cth->nfnlssh_ct = nfnl_subsys_open2(cth->nfnlh, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_MAX, subscriptions, bind); if (!cth->nfnlssh_ct) goto out_free; } if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK_EXP) { cth->nfnlssh_exp = nfnl_subsys_open2(cth->nfnlh, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_MAX, subscriptions, bind); if (!cth->nfnlssh_exp) goto out_free; } return cth; out_free: if (cth->nfnlssh_exp) { nfnl_subsys_close(cth->nfnlssh_exp); cth->nfnlssh_exp = NULL; } if (cth->nfnlssh_ct) { nfnl_subsys_close(cth->nfnlssh_ct); cth->nfnlssh_ct = NULL; } free(cth); return NULL; } /** * \defgroup LibrarySetup Library setup * @{ */ /** * nfct_open - open a ctnetlink handler * \param subsys_id can be NFNL_SUBSYS_CTNETLINK or NFNL_SUBSYS_CTNETLINK_EXP * \param subscriptions ctnetlink groups to subscribe to events * * This function returns a handler to send commands to and receive replies from * kernel-space. You can pass the following subsystem IDs: * * - NFNL_SUBSYS_CTNETLINK: if you are only interested in conntrack operations * (excluding expectations). * - NFNL_SUBSYS_CTNETLINK_EXP: if you are only interested in expectation * operations (exclude conntracks). * - NFNL_SUBSYS_NONE: if you are interested in both conntrack and expectation * operations. * * On error, NULL is returned and errno is explicitly set. */ struct nfct_handle *nfct_open(uint8_t subsys_id, unsigned subscriptions) { struct nfnl_handle *nfnlh = nfnl_open(); struct nfct_handle *nfcth; if (!nfnlh) return NULL; nfcth = nfct_open_nfnl(nfnlh, subsys_id, subscriptions); if (!nfcth) nfnl_close(nfnlh); return nfcth; } /** * nfct_open2 - open a ctnetlink handler by given fd * \param subsys_id can be NFNL_SUBSYS_CTNETLINK or NFNL_SUBSYS_CTNETLINK_EXP * \param subscriptions ctnetlink groups to subscribe to events * \param fd use bound file descriptor to get nfnl_handle * * This function returns a handler to send commands to and receive replies from * kernel-space. You can pass the following subsystem IDs: * * - NFNL_SUBSYS_CTNETLINK: if you are only interested in conntrack operations * (excluding expectations). * - NFNL_SUBSYS_CTNETLINK_EXP: if you are only interested in expectation * operations (exclude conntracks). * - NFNL_SUBSYS_NONE: if you are interested in both conntrack and expectation * operations. * * On error, NULL is returned and errno is explicitly set. */ struct nfct_handle *nfct_open2(uint8_t subsys_id, unsigned subscriptions, int fd) { struct nfnl_handle *nfnlh = nfnl_open2(fd, false); struct nfct_handle *nfcth; if (!nfnlh) return NULL; nfcth = nfct_open_nfnl2(nfnlh, subsys_id, subscriptions, false); if (!nfcth) { nfnl_close2(nfnlh); } return nfcth; } /** * nfct_close - close a ctnetlink handler * \param cth handler obtained via nfct_open() * * This function returns -1 on error and errno is explicitly set. */ int nfct_close(struct nfct_handle *cth) { return nfct_close2(cth, false); } /** * nfct_close2 - close a ctnetlink handler * \param cth handler obtained via nfct_open() * \param keep_fd to indicate not close the file descriptor * * This function returns -1 on error and errno is explicitly set. */ int nfct_close2(struct nfct_handle *cth, bool keep_fd) { int err; if (cth->nfnlssh_exp) { nfnl_subsys_close(cth->nfnlssh_exp); cth->nfnlssh_exp = NULL; } if (cth->nfnlssh_ct) { nfnl_subsys_close(cth->nfnlssh_ct); cth->nfnlssh_ct = NULL; } /* required by the new API */ cth->cb = NULL; cth->cb2 = NULL; cth->expect_cb = NULL; cth->expect_cb2 = NULL; free(cth->nfnl_cb_ct.data); free(cth->nfnl_cb_exp.data); cth->nfnl_cb_ct.call = NULL; cth->nfnl_cb_ct.data = NULL; cth->nfnl_cb_ct.attr_count = 0; cth->nfnl_cb_exp.call = NULL; cth->nfnl_cb_exp.data = NULL; cth->nfnl_cb_exp.attr_count = 0; if (keep_fd) err = nfnl_close2(cth->nfnlh); else err = nfnl_close(cth->nfnlh); free(cth); return err; } /** * nfct_fd - get the Netlink file descriptor of one existing ctnetlink handler * \param cth handler obtained via nfct_open() */ int nfct_fd(struct nfct_handle *cth) { return nfnl_fd(cth->nfnlh); } const struct nfnl_handle *nfct_nfnlh(struct nfct_handle *cth) { return cth->nfnlh; } /** * @} */