00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <unistd.h>
00010 #include <string.h>
00011 #include <time.h>
00012 #include <arpa/inet.h>
00013
00014 #include <libmnl/libmnl.h>
00015 #include <linux/netfilter.h>
00016 #include <linux/netfilter/nfnetlink.h>
00017
00018 #ifndef aligned_be64
00019 #define aligned_be64 u_int64_t __attribute__((aligned(8)))
00020 #endif
00021
00022 #include <linux/netfilter/nfnetlink_log.h>
00023
00024 static int parse_attr_cb(const struct nlattr *attr, void *data)
00025 {
00026 const struct nlattr **tb = data;
00027 int type = mnl_attr_get_type(attr);
00028
00029
00030 if (mnl_attr_type_valid(attr, NFULA_MAX) < 0)
00031 return MNL_CB_OK;
00032
00033 switch(type) {
00034 case NFULA_MARK:
00035 case NFULA_IFINDEX_INDEV:
00036 case NFULA_IFINDEX_OUTDEV:
00037 case NFULA_IFINDEX_PHYSINDEV:
00038 case NFULA_IFINDEX_PHYSOUTDEV:
00039 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00040 perror("mnl_attr_validate");
00041 return MNL_CB_ERROR;
00042 }
00043 break;
00044 case NFULA_TIMESTAMP:
00045 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
00046 sizeof(struct nfulnl_msg_packet_timestamp)) < 0) {
00047 perror("mnl_attr_validate");
00048 return MNL_CB_ERROR;
00049 }
00050 break;
00051 case NFULA_HWADDR:
00052 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
00053 sizeof(struct nfulnl_msg_packet_hw)) < 0) {
00054 perror("mnl_attr_validate");
00055 return MNL_CB_ERROR;
00056 }
00057 break;
00058 case NFULA_PREFIX:
00059 if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) {
00060 perror("mnl_attr_validate");
00061 return MNL_CB_ERROR;
00062 }
00063 break;
00064 case NFULA_PAYLOAD:
00065 break;
00066 }
00067 tb[type] = attr;
00068 return MNL_CB_OK;
00069 }
00070
00071 static int log_cb(const struct nlmsghdr *nlh, void *data)
00072 {
00073 struct nlattr *tb[NFULA_MAX+1] = {};
00074 struct nfulnl_msg_packet_hdr *ph = NULL;
00075 const char *prefix = NULL;
00076 uint32_t mark = 0;
00077
00078 mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
00079 if (tb[NFULA_PACKET_HDR])
00080 ph = mnl_attr_get_payload(tb[NFULA_PACKET_HDR]);
00081 if (tb[NFULA_PREFIX])
00082 prefix = mnl_attr_get_str(tb[NFULA_PREFIX]);
00083 if (tb[NFULA_MARK])
00084 mark = ntohl(mnl_attr_get_u32(tb[NFULA_MARK]));
00085
00086 printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n",
00087 prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook,
00088 mark);
00089
00090 return MNL_CB_OK;
00091 }
00092
00093 static struct nlmsghdr *
00094 nflog_build_cfg_pf_request(char *buf, uint8_t command)
00095 {
00096 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
00097 nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
00098 nlh->nlmsg_flags = NLM_F_REQUEST;
00099
00100 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00101 nfg->nfgen_family = AF_INET;
00102 nfg->version = NFNETLINK_V0;
00103
00104 struct nfulnl_msg_config_cmd cmd = {
00105 .command = command,
00106 };
00107 mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
00108
00109 return nlh;
00110 }
00111
00112 static struct nlmsghdr *
00113 nflog_build_cfg_request(char *buf, uint8_t command, int qnum)
00114 {
00115 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
00116 nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
00117 nlh->nlmsg_flags = NLM_F_REQUEST;
00118
00119 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00120 nfg->nfgen_family = AF_INET;
00121 nfg->version = NFNETLINK_V0;
00122 nfg->res_id = htons(qnum);
00123
00124 struct nfulnl_msg_config_cmd cmd = {
00125 .command = command,
00126 };
00127 mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
00128
00129 return nlh;
00130 }
00131
00132 static struct nlmsghdr *
00133 nflog_build_cfg_params(char *buf, uint8_t mode, int range, int qnum)
00134 {
00135 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
00136 nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
00137 nlh->nlmsg_flags = NLM_F_REQUEST;
00138
00139 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00140 nfg->nfgen_family = AF_UNSPEC;
00141 nfg->version = NFNETLINK_V0;
00142 nfg->res_id = htons(qnum);
00143
00144 struct nfulnl_msg_config_mode params = {
00145 .copy_range = htonl(range),
00146 .copy_mode = mode,
00147 };
00148 mnl_attr_put(nlh, NFULA_CFG_MODE, sizeof(params), ¶ms);
00149
00150 return nlh;
00151 }
00152
00153 int main(int argc, char *argv[])
00154 {
00155 struct mnl_socket *nl;
00156 char buf[MNL_SOCKET_BUFFER_SIZE];
00157 struct nlmsghdr *nlh;
00158 int ret;
00159 unsigned int portid, qnum;
00160
00161 if (argc != 2) {
00162 printf("Usage: %s [queue_num]\n", argv[0]);
00163 exit(EXIT_FAILURE);
00164 }
00165 qnum = atoi(argv[1]);
00166
00167 nl = mnl_socket_open(NETLINK_NETFILTER);
00168 if (nl == NULL) {
00169 perror("mnl_socket_open");
00170 exit(EXIT_FAILURE);
00171 }
00172
00173 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
00174 perror("mnl_socket_bind");
00175 exit(EXIT_FAILURE);
00176 }
00177 portid = mnl_socket_get_portid(nl);
00178
00179 nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_UNBIND);
00180
00181 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00182 perror("mnl_socket_send");
00183 exit(EXIT_FAILURE);
00184 }
00185
00186 nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_BIND);
00187
00188 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00189 perror("mnl_socket_send");
00190 exit(EXIT_FAILURE);
00191 }
00192
00193 nlh = nflog_build_cfg_request(buf, NFULNL_CFG_CMD_BIND, qnum);
00194
00195 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00196 perror("mnl_socket_send");
00197 exit(EXIT_FAILURE);
00198 }
00199
00200 nlh = nflog_build_cfg_params(buf, NFULNL_COPY_PACKET, 0xFFFF, qnum);
00201
00202 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00203 perror("mnl_socket_send");
00204 exit(EXIT_FAILURE);
00205 }
00206
00207 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00208 if (ret == -1) {
00209 perror("mnl_socket_recvfrom");
00210 exit(EXIT_FAILURE);
00211 }
00212 while (ret > 0) {
00213 ret = mnl_cb_run(buf, ret, 0, portid, log_cb, NULL);
00214 if (ret < 0){
00215 perror("mnl_cb_run");
00216 exit(EXIT_FAILURE);
00217 }
00218
00219 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00220 if (ret == -1) {
00221 perror("mnl_socket_recvfrom");
00222 exit(EXIT_FAILURE);
00223 }
00224 }
00225
00226 mnl_socket_close(nl);
00227
00228 return 0;
00229 }