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

nf-queue.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_queue.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, NFQA_MAX) < 0)
00031                 return MNL_CB_OK;
00032 
00033         switch(type) {
00034         case NFQA_MARK:
00035         case NFQA_IFINDEX_INDEV:
00036         case NFQA_IFINDEX_OUTDEV:
00037         case NFQA_IFINDEX_PHYSINDEV:
00038         case NFQA_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 NFQA_TIMESTAMP:
00045                 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
00046                     sizeof(struct nfqnl_msg_packet_timestamp)) < 0) {
00047                         perror("mnl_attr_validate");
00048                         return MNL_CB_ERROR;
00049                 }
00050                 break;
00051         case NFQA_HWADDR:
00052                 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
00053                     sizeof(struct nfqnl_msg_packet_hw)) < 0) {
00054                         perror("mnl_attr_validate");
00055                         return MNL_CB_ERROR;
00056                 }
00057                 break;
00058         case NFQA_PAYLOAD:
00059                 break;
00060         }
00061         tb[type] = attr;
00062         return MNL_CB_OK;
00063 }
00064 
00065 static int queue_cb(const struct nlmsghdr *nlh, void *data)
00066 {
00067         struct nlattr *tb[NFQA_MAX+1] = {};
00068         struct nfqnl_msg_packet_hdr *ph = NULL;
00069         uint32_t id = 0;
00070 
00071         mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
00072         if (tb[NFQA_PACKET_HDR]) {
00073                 ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]);
00074                 id = ntohl(ph->packet_id);
00075         }
00076         printf("packet received (id=%u hw=0x%04x hook=%u)\n",
00077                 id, ntohs(ph->hw_protocol), ph->hook);
00078 
00079         return MNL_CB_OK + id;
00080 }
00081 
00082 static struct nlmsghdr *
00083 nfq_build_cfg_pf_request(char *buf, uint8_t command)
00084 {
00085         struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
00086         nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
00087         nlh->nlmsg_flags = NLM_F_REQUEST;
00088 
00089         struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00090         nfg->nfgen_family = AF_UNSPEC;
00091         nfg->version = NFNETLINK_V0;
00092 
00093         struct nfqnl_msg_config_cmd cmd = {
00094                 .command = command,
00095                 .pf = htons(AF_INET),
00096         };
00097         mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd);
00098 
00099         return nlh;
00100 }
00101 
00102 static struct nlmsghdr *
00103 nfq_build_cfg_request(char *buf, uint8_t command, int queue_num)
00104 {
00105         struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
00106         nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
00107         nlh->nlmsg_flags = NLM_F_REQUEST;
00108 
00109         struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00110         nfg->nfgen_family = AF_UNSPEC;
00111         nfg->version = NFNETLINK_V0;
00112         nfg->res_id = htons(queue_num);
00113 
00114         struct nfqnl_msg_config_cmd cmd = {
00115                 .command = command,
00116                 .pf = htons(AF_INET),
00117         };
00118         mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd);
00119 
00120         return nlh;
00121 }
00122 
00123 static struct nlmsghdr *
00124 nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num)
00125 {
00126         struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
00127         nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
00128         nlh->nlmsg_flags = NLM_F_REQUEST;
00129 
00130         struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00131         nfg->nfgen_family = AF_UNSPEC;
00132         nfg->version = NFNETLINK_V0;
00133         nfg->res_id = htons(queue_num);
00134 
00135         struct nfqnl_msg_config_params params = {
00136                 .copy_range = htonl(range),
00137                 .copy_mode = mode,
00138         };
00139         mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), &params);
00140 
00141         return nlh;
00142 }
00143 
00144 static struct nlmsghdr *
00145 nfq_build_verdict(char *buf, int id, int queue_num, int verd)
00146 {
00147         struct nlmsghdr *nlh;
00148         struct nfgenmsg *nfg;
00149 
00150         nlh = mnl_nlmsg_put_header(buf);
00151         nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT;
00152         nlh->nlmsg_flags = NLM_F_REQUEST;
00153         nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
00154         nfg->nfgen_family = AF_UNSPEC;
00155         nfg->version = NFNETLINK_V0;
00156         nfg->res_id = htons(queue_num);
00157 
00158         struct nfqnl_msg_verdict_hdr vh = {
00159                 .verdict = htonl(verd),
00160                 .id = htonl(id),
00161         };
00162         mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh);
00163 
00164         return nlh;
00165 }
00166 
00167 int main(int argc, char *argv[])
00168 {
00169         struct mnl_socket *nl;
00170         char buf[MNL_SOCKET_BUFFER_SIZE];
00171         struct nlmsghdr *nlh;
00172         int ret;
00173         unsigned int portid, queue_num;
00174 
00175         if (argc != 2) {
00176                 printf("Usage: %s [queue_num]\n", argv[0]);
00177                 exit(EXIT_FAILURE);
00178         }
00179         queue_num = atoi(argv[1]);
00180 
00181         nl = mnl_socket_open(NETLINK_NETFILTER);
00182         if (nl == NULL) {
00183                 perror("mnl_socket_open");
00184                 exit(EXIT_FAILURE);
00185         }
00186 
00187         if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
00188                 perror("mnl_socket_bind");
00189                 exit(EXIT_FAILURE);
00190         }
00191         portid = mnl_socket_get_portid(nl);
00192 
00193         nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_UNBIND);
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 = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_BIND);
00201 
00202         if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00203                 perror("mnl_socket_send");
00204                 exit(EXIT_FAILURE);
00205         }
00206 
00207         nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num);
00208 
00209         if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00210                 perror("mnl_socket_send");
00211                 exit(EXIT_FAILURE);
00212         }
00213 
00214         nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num);
00215 
00216         if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00217                 perror("mnl_socket_send");
00218                 exit(EXIT_FAILURE);
00219         }
00220 
00221         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00222         if (ret == -1) {
00223                 perror("mnl_socket_recvfrom");
00224                 exit(EXIT_FAILURE);
00225         }
00226         while (ret > 0) {
00227                 uint32_t id;
00228 
00229                 ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);
00230                 if (ret < 0){
00231                         perror("mnl_cb_run");
00232                         exit(EXIT_FAILURE);
00233                 }
00234 
00235                 id = ret - MNL_CB_OK;
00236                 nlh = nfq_build_verdict(buf, id, queue_num, NF_ACCEPT);
00237                 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
00238                         perror("mnl_socket_send");
00239                         exit(EXIT_FAILURE);
00240                 }
00241 
00242                 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00243                 if (ret == -1) {
00244                         perror("mnl_socket_recvfrom");
00245                         exit(EXIT_FAILURE);
00246                 }
00247         }
00248 
00249         mnl_socket_close(nl);
00250 
00251         return 0;
00252 }

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