• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

nf-log.c

00001 /*
00002  * (C) 2010 by Pablo Neira Ayuso <pablo@netfilter.org>
00003  *
00004  * This software may be used and distributed according to the terms
00005  * of the GNU General Public License, incorporated herein by reference.
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         /* skip unsupported attribute in user-space */
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), &params);
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 }

Generated on Sun Dec 26 2010 22:23:55 for libmnl by  doxygen 1.7.1