int nflog_set_flags(struct nflog_g_handle *gh, u_int16_t flags) { char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(u_int16_t))]; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); nfnl_addattr16(nmh, sizeof(buf), NFULA_CFG_FLAGS, htons(flags)); return nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); }
int nflog_set_qthresh(struct nflog_g_handle *gh, u_int32_t qthresh) { char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(u_int32_t))]; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); nfnl_addattr32(nmh, sizeof(buf), NFULA_CFG_QTHRESH, htonl(qthresh)); return nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); }
static int __build_query_exp(struct nfnl_subsys_handle *ssh, const enum nf_conntrack_query qt, const void *data, void *buffer, unsigned int size) { struct nfnlhdr *req = buffer; const uint8_t *family = data; assert(ssh != NULL); assert(data != NULL); assert(req != NULL); memset(req, 0, size); switch(qt) { case NFCT_Q_CREATE: __build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data); break; case NFCT_Q_CREATE_UPDATE: __build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data); break; case NFCT_Q_GET: __build_expect(ssh, req, size, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK, data); break; case NFCT_Q_DESTROY: __build_expect(ssh, req, size, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK, data); break; case NFCT_Q_FLUSH: nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK); break; case NFCT_Q_DUMP: nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_DUMP); break; default: errno = ENOTSUP; return -1; } return 1; }
/** * nflog_set_flags - set the nflog flags for this group * \param gh Netfilter log 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. * * \return -1 in case of error and errno is explicity set. */ int nflog_set_flags(struct nflog_g_handle *gh, uint16_t flags) { union { char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(uint16_t))]; struct nlmsghdr nmh; } u; nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); nfnl_addattr16(&u.nmh, sizeof(u), NFULA_CFG_FLAGS, htons(flags)); return nfnl_query(gh->h->nfnlh, &u.nmh); }
/** * 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 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. */ int nflog_set_qthresh(struct nflog_g_handle *gh, uint32_t qthresh) { union { char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(uint32_t))]; struct nlmsghdr nmh; } u; nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); nfnl_addattr32(&u.nmh, sizeof(u), NFULA_CFG_QTHRESH, htonl(qthresh)); return nfnl_query(gh->h->nfnlh, &u.nmh); }
/* build a NFULNL_MSG_CONFIG message */ static int __build_send_cfg_msg(struct nflog_handle *h, u_int8_t command, u_int16_t queuenum, u_int8_t pf) { char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(struct nfulnl_msg_config_cmd))]; struct nfulnl_msg_config_cmd cmd; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; nfnl_fill_hdr(h->nfnlssh, nmh, 0, pf, queuenum, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); cmd.command = command; nfnl_addattr_l(nmh, sizeof(buf), NFULA_CFG_CMD, &cmd, sizeof(cmd)); return nfnl_talk(h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); }
int nflog_set_mode(struct nflog_g_handle *gh, u_int8_t mode, u_int32_t range) { char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(struct nfulnl_msg_config_mode))]; struct nfulnl_msg_config_mode params; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); params.copy_range = htonl(range); /* copy_range is short */ params.copy_mode = mode; nfnl_addattr_l(nmh, sizeof(buf), NFULA_CFG_MODE, ¶ms, sizeof(params)); return nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); }
/* build a NFULNL_MSG_CONFIG message */ static int __build_send_cfg_msg(struct nflog_handle *h, uint8_t command, uint16_t groupnum, uint8_t pf) { union { char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(struct nfulnl_msg_config_cmd))]; struct nlmsghdr nmh; } u; struct nfulnl_msg_config_cmd cmd; nfnl_fill_hdr(h->nfnlssh, &u.nmh, 0, pf, groupnum, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); cmd.command = command; nfnl_addattr_l(&u.nmh, sizeof(u), NFULA_CFG_CMD, &cmd, sizeof(cmd)); return nfnl_query(h->nfnlh, &u.nmh); }
int __build_expect(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_expect *exp) { u_int8_t l3num; if (test_bit(ATTR_ORIG_L3PROTO, exp->master.set)) l3num = exp->master.orig.l3protonum; else if (test_bit(ATTR_ORIG_L3PROTO, exp->expected.set)) l3num = exp->expected.orig.l3protonum; else return -1; memset(req, 0, size); nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags); if (test_bit(ATTR_EXP_EXPECTED, exp->set)) { __build_tuple(req, size, &exp->expected.orig, CTA_EXPECT_TUPLE); } if (test_bit(ATTR_EXP_MASTER, exp->set)) { __build_tuple(req, size, &exp->master.orig, CTA_EXPECT_MASTER); } if (test_bit(ATTR_EXP_MASK, exp->set)) { __build_tuple(req, size, &exp->mask.orig, CTA_EXPECT_MASK); } if (test_bit(ATTR_EXP_TIMEOUT, exp->set)) __build_timeout(req, size, exp); if (test_bit(ATTR_EXP_FLAGS, exp->set)) __build_flags(req, size, exp); if (test_bit(ATTR_EXP_ZONE, exp->set)) __build_zone(req, size, exp); if (test_bit(ATTR_EXP_HELPER_NAME, exp->set)) __build_helper_name(req, size, exp); return 0; }
int nflog_set_nlbufsiz(struct nflog_g_handle *gh, u_int32_t nlbufsiz) { char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(u_int32_t))]; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; int status; nfnl_fill_hdr(gh->h->nfnlssh, 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)); status = nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); /* 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; }
/** * 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 mode the part of the packet that we are interested in * \param range size of the packet that we want to get * * Sets the amount of data to be copied to userspace for each packet logged * to the given group. * * - NFULNL_COPY_NONE - do not copy any data * - NFULNL_COPY_META - copy only packet metadata * - NFULNL_COPY_PACKET - copy entire packet * * \return -1 on error; >= otherwise. */ int nflog_set_mode(struct nflog_g_handle *gh, uint8_t mode, uint32_t range) { union { char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(struct nfulnl_msg_config_mode))]; struct nlmsghdr nmh; } u; struct nfulnl_msg_config_mode params; nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id, NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); params.copy_range = htonl(range); /* copy_range is short */ params.copy_mode = mode; nfnl_addattr_l(&u.nmh, sizeof(u), NFULA_CFG_MODE, ¶ms, sizeof(params)); return nfnl_query(gh->h->nfnlh, &u.nmh); }
int __build_conntrack(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_conntrack *ct) { u_int8_t l3num = ct->tuple[__DIR_ORIG].l3protonum; if (!test_bit(ATTR_ORIG_L3PROTO, ct->set)) { errno = EINVAL; return -1; } memset(req, 0, size); nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags); if (test_bit(ATTR_ORIG_IPV4_SRC, ct->set) || test_bit(ATTR_ORIG_IPV4_DST, ct->set) || test_bit(ATTR_ORIG_IPV6_SRC, ct->set) || test_bit(ATTR_ORIG_IPV6_DST, ct->set) || test_bit(ATTR_ORIG_PORT_SRC, ct->set) || test_bit(ATTR_ORIG_PORT_DST, ct->set) || test_bit(ATTR_ORIG_L3PROTO, ct->set) || test_bit(ATTR_ORIG_L4PROTO, ct->set) || test_bit(ATTR_ICMP_TYPE, ct->set) || test_bit(ATTR_ICMP_CODE, ct->set) || test_bit(ATTR_ICMP_ID, ct->set)) { __build_tuple(req, size, &ct->tuple[__DIR_ORIG], CTA_TUPLE_ORIG); } if (test_bit(ATTR_REPL_IPV4_SRC, ct->set) || test_bit(ATTR_REPL_IPV4_DST, ct->set) || test_bit(ATTR_REPL_IPV6_SRC, ct->set) || test_bit(ATTR_REPL_IPV6_DST, ct->set) || test_bit(ATTR_REPL_PORT_SRC, ct->set) || test_bit(ATTR_REPL_PORT_DST, ct->set) || test_bit(ATTR_REPL_L3PROTO, ct->set) || test_bit(ATTR_REPL_L4PROTO, ct->set) || test_bit(ATTR_ICMP_TYPE, ct->set) || test_bit(ATTR_ICMP_CODE, ct->set) || test_bit(ATTR_ICMP_ID, ct->set)) { __build_tuple(req, size, &ct->tuple[__DIR_REPL], CTA_TUPLE_REPLY); } if (test_bit(ATTR_MASTER_IPV4_SRC, ct->set) || test_bit(ATTR_MASTER_IPV4_DST, ct->set) || test_bit(ATTR_MASTER_IPV6_SRC, ct->set) || test_bit(ATTR_MASTER_IPV6_DST, ct->set) || test_bit(ATTR_MASTER_PORT_SRC, ct->set) || test_bit(ATTR_MASTER_PORT_DST, ct->set) || test_bit(ATTR_MASTER_L3PROTO, ct->set) || test_bit(ATTR_MASTER_L4PROTO, ct->set)) { __build_tuple(req, size, &ct->tuple[__DIR_MASTER], CTA_TUPLE_MASTER); } if (test_bit(ATTR_STATUS, ct->set)) { __build_status(req, size, ct); } else { /* build IPS_CONFIRMED if we're creating a new conntrack */ if (type == IPCTNL_MSG_CT_NEW && flags & NLM_F_CREATE) __build_status(req, size, ct); } if (test_bit(ATTR_TIMEOUT, ct->set)) { __build_timeout(req, size, ct); } if (test_bit(ATTR_MARK, ct->set)) { __build_mark(req, size, ct); } if (test_bit(ATTR_SECMARK, ct->set)) { __build_secmark(req, size, ct); } __build_protoinfo(req, size, ct); if (test_bit(ATTR_SNAT_IPV4, ct->set) && test_bit(ATTR_SNAT_PORT, ct->set)) { __build_snat(req, size, ct); } else if (test_bit(ATTR_SNAT_IPV4, ct->set)) { __build_snat_ipv4(req, size, ct); } else if (test_bit(ATTR_SNAT_PORT, ct->set)) { __build_snat_port(req, size, ct); } if (test_bit(ATTR_DNAT_IPV4, ct->set) && test_bit(ATTR_DNAT_PORT, ct->set)) { __build_dnat(req, size, ct); } else if (test_bit(ATTR_DNAT_IPV4, ct->set)) { __build_dnat_ipv4(req, size, ct); } else if (test_bit(ATTR_DNAT_PORT, ct->set)) { __build_dnat_port(req, size, ct); } if (test_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->set) && test_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->set) && test_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->set)) { __build_nat_seq_adj(req, size, ct, __DIR_ORIG); } if (test_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->set) && test_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->set) && test_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->set)) { __build_nat_seq_adj(req, size, ct, __DIR_REPL); } if (test_bit(ATTR_HELPER_NAME, ct->set)) { __build_helper_name(req, size, ct); } return 0; }
static int osf_load_line(char *buffer, int len, int del) { int i, cnt = 0; char obuf[MAXOPTSTRLEN]; struct xt_osf_user_finger f; char *pbeg, *pend; char buf[NFNL_HEADER_LEN + NFA_LENGTH(sizeof(struct xt_osf_user_finger))]; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; memset(&f, 0, sizeof(struct xt_osf_user_finger)); ulog("Loading '%s'.\n", buffer); for (i = 0; i < len && buffer[i] != '\0'; ++i) { if (buffer[i] == ':') cnt++; } if (cnt != 8) { ulog("Wrong input line '%s': cnt: %d, must be 8, i: %d, must be %d.\n", buffer, cnt, i, len); return -EINVAL; } memset(obuf, 0, sizeof(obuf)); pbeg = buffer; pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; if (pbeg[0] == 'S') { f.wss.wc = OSF_WSS_MSS; if (pbeg[1] == '%') f.wss.val = strtoul(&pbeg[2], NULL, 10); else if (pbeg[1] == '*') f.wss.val = 0; else f.wss.val = strtoul(&pbeg[1], NULL, 10); } else if (pbeg[0] == 'T') { f.wss.wc = OSF_WSS_MTU; if (pbeg[1] == '%') f.wss.val = strtoul(&pbeg[2], NULL, 10); else if (pbeg[1] == '*') f.wss.val = 0; else f.wss.val = strtoul(&pbeg[1], NULL, 10); } else if (pbeg[0] == '%') { f.wss.wc = OSF_WSS_MODULO; f.wss.val = strtoul(&pbeg[1], NULL, 10); } else if (isdigit(pbeg[0])) { f.wss.wc = OSF_WSS_PLAIN; f.wss.val = strtoul(&pbeg[0], NULL, 10); } pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; f.ttl = strtoul(pbeg, NULL, 10); pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; f.df = strtoul(pbeg, NULL, 10); pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; f.ss = strtoul(pbeg, NULL, 10); pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; cnt = snprintf(obuf, sizeof(obuf), "%s,", pbeg); pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; if (pbeg[0] == '@' || pbeg[0] == '*') cnt = snprintf(f.genre, sizeof(f.genre), "%s", pbeg + 1); else cnt = snprintf(f.genre, sizeof(f.genre), "%s", pbeg); pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; cnt = snprintf(f.version, sizeof(f.version), "%s", pbeg); pbeg = pend + 1; } pend = xt_osf_strchr(pbeg, OSFPDEL); if (pend) { *pend = '\0'; cnt = snprintf(f.subtype, sizeof(f.subtype), "%s", pbeg); pbeg = pend + 1; } xt_osf_parse_opt(f.opt, &f.opt_num, obuf, sizeof(obuf)); memset(buf, 0, sizeof(buf)); if (del) nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_REMOVE, NLM_F_REQUEST); else nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_ADD, NLM_F_REQUEST | NLM_F_CREATE); nfnl_addattr_l(nmh, sizeof(buf), OSF_ATTR_FINGER, &f, sizeof(struct xt_osf_user_finger)); return nfnl_talk(nfnlh, nmh, 0, 0, NULL, NULL, NULL); }