libmnl  1.0.3
nfct-event.c
00001 /* This example is placed in the public domain. */
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <arpa/inet.h>
00006 
00007 #include <libmnl/libmnl.h>
00008 #include <linux/netfilter/nfnetlink.h>
00009 #include <linux/netfilter/nfnetlink_conntrack.h>
00010 
00011 static int parse_ip_cb(const struct nlattr *attr, void *data)
00012 {
00013         const struct nlattr **tb = data;
00014         int type = mnl_attr_get_type(attr);
00015 
00016         if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
00017                 return MNL_CB_OK;
00018 
00019         switch(type) {
00020         case CTA_IP_V4_SRC:
00021         case CTA_IP_V4_DST:
00022                 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00023                         perror("mnl_attr_validate");
00024                         return MNL_CB_ERROR;
00025                 }
00026                 break;
00027         }
00028         tb[type] = attr;
00029         return MNL_CB_OK;
00030 }
00031 
00032 static void print_ip(const struct nlattr *nest)
00033 {
00034         struct nlattr *tb[CTA_IP_MAX+1] = {};
00035 
00036         mnl_attr_parse_nested(nest, parse_ip_cb, tb);
00037         if (tb[CTA_IP_V4_SRC]) {
00038                 struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
00039                 printf("src=%s ", inet_ntoa(*in));
00040         }
00041         if (tb[CTA_IP_V4_DST]) {
00042                 struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]);
00043                 printf("dst=%s ", inet_ntoa(*in));
00044         }
00045 }
00046 
00047 static int parse_proto_cb(const struct nlattr *attr, void *data)
00048 {
00049         const struct nlattr **tb = data;
00050         int type = mnl_attr_get_type(attr);
00051 
00052         if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0)
00053                 return MNL_CB_OK;
00054 
00055         switch(type) {
00056         case CTA_PROTO_NUM:
00057         case CTA_PROTO_ICMP_TYPE:
00058         case CTA_PROTO_ICMP_CODE:
00059                 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
00060                         perror("mnl_attr_validate");
00061                         return MNL_CB_ERROR;
00062                 }
00063                 break;
00064         case CTA_PROTO_SRC_PORT:
00065         case CTA_PROTO_DST_PORT:
00066         case CTA_PROTO_ICMP_ID:
00067                 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
00068                         perror("mnl_attr_validate");
00069                         return MNL_CB_ERROR;
00070                 }
00071                 break;
00072         }
00073         tb[type] = attr;
00074         return MNL_CB_OK;
00075 }
00076 
00077 static void print_proto(const struct nlattr *nest)
00078 {
00079         struct nlattr *tb[CTA_PROTO_MAX+1] = {};
00080 
00081         mnl_attr_parse_nested(nest, parse_proto_cb, tb);
00082         if (tb[CTA_PROTO_NUM]) {
00083                 printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM]));
00084         }
00085         if (tb[CTA_PROTO_SRC_PORT]) {
00086                 printf("sport=%u ",
00087                         ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT])));
00088         }
00089         if (tb[CTA_PROTO_DST_PORT]) {
00090                 printf("dport=%u ",
00091                         ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT])));
00092         }
00093         if (tb[CTA_PROTO_ICMP_ID]) {
00094                 printf("id=%u ",
00095                         ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID])));
00096         }
00097         if (tb[CTA_PROTO_ICMP_TYPE]) {
00098                 printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
00099         }
00100         if (tb[CTA_PROTO_ICMP_CODE]) {
00101                 printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]));
00102         }
00103 }
00104 
00105 static int parse_tuple_cb(const struct nlattr *attr, void *data)
00106 {
00107         const struct nlattr **tb = data;
00108         int type = mnl_attr_get_type(attr);
00109 
00110         if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0)
00111                 return MNL_CB_OK;
00112 
00113         switch(type) {
00114         case CTA_TUPLE_IP:
00115                 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
00116                         perror("mnl_attr_validate");
00117                         return MNL_CB_ERROR;
00118                 }
00119                 break;
00120         case CTA_TUPLE_PROTO:
00121                 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
00122                         perror("mnl_attr_validate");
00123                         return MNL_CB_ERROR;
00124                 }
00125                 break;
00126         }
00127         tb[type] = attr;
00128         return MNL_CB_OK;
00129 }
00130 
00131 static void print_tuple(const struct nlattr *nest)
00132 {
00133         struct nlattr *tb[CTA_TUPLE_MAX+1] = {};
00134 
00135         mnl_attr_parse_nested(nest, parse_tuple_cb, tb);
00136         if (tb[CTA_TUPLE_IP]) {
00137                 print_ip(tb[CTA_TUPLE_IP]);
00138         }
00139         if (tb[CTA_TUPLE_PROTO]) {
00140                 print_proto(tb[CTA_TUPLE_PROTO]);
00141         }
00142 }
00143 
00144 static int data_attr_cb(const struct nlattr *attr, void *data)
00145 {
00146         const struct nlattr **tb = data;
00147         int type = mnl_attr_get_type(attr);
00148 
00149         if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
00150                 return MNL_CB_OK;
00151 
00152         switch(type) {
00153         case CTA_TUPLE_ORIG:
00154                 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
00155                         perror("mnl_attr_validate");
00156                         return MNL_CB_ERROR;
00157                 }
00158                 break;
00159         case CTA_TIMEOUT:
00160         case CTA_MARK:
00161         case CTA_SECMARK:
00162                 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
00163                         perror("mnl_attr_validate");
00164                         return MNL_CB_ERROR;
00165                 }
00166                 break;
00167         }
00168         tb[type] = attr;
00169         return MNL_CB_OK;
00170 }
00171 
00172 static int data_cb(const struct nlmsghdr *nlh, void *data)
00173 {
00174         struct nlattr *tb[CTA_MAX+1] = {};
00175         struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
00176 
00177         switch(nlh->nlmsg_type & 0xFF) {
00178         case IPCTNL_MSG_CT_NEW:
00179                 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
00180                         printf("%9s ", "[NEW] ");
00181                 else
00182                         printf("%9s ", "[UPDATE] ");
00183                 break;
00184         case IPCTNL_MSG_CT_DELETE:
00185                 printf("%9s ", "[DESTROY] ");
00186                 break;
00187         }
00188 
00189         mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb);
00190         if (tb[CTA_TUPLE_ORIG]) {
00191                 print_tuple(tb[CTA_TUPLE_ORIG]);
00192         }
00193         if (tb[CTA_MARK]) {
00194                 printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK])));
00195         }
00196         if (tb[CTA_SECMARK]) {
00197                 printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])));
00198         }
00199         printf("\n");
00200         return MNL_CB_OK;
00201 }
00202 
00203 int main(void)
00204 {
00205         struct mnl_socket *nl;
00206         char buf[MNL_SOCKET_BUFFER_SIZE];
00207         int ret;
00208 
00209         nl = mnl_socket_open(NETLINK_NETFILTER);
00210         if (nl == NULL) {
00211                 perror("mnl_socket_open");
00212                 exit(EXIT_FAILURE);
00213         }
00214 
00215         if (mnl_socket_bind(nl, NF_NETLINK_CONNTRACK_NEW |
00216                                 NF_NETLINK_CONNTRACK_UPDATE |
00217                                 NF_NETLINK_CONNTRACK_DESTROY,
00218                                 MNL_SOCKET_AUTOPID) < 0) {
00219                 perror("mnl_socket_bind");
00220                 exit(EXIT_FAILURE);
00221         }
00222 
00223         while (1) {
00224                 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
00225                 if (ret == -1) {
00226                         perror("mnl_socket_recvfrom");
00227                         exit(EXIT_FAILURE);
00228                 }
00229 
00230                 ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
00231                 if (ret == -1) {
00232                         perror("mnl_cb_run");
00233                         exit(EXIT_FAILURE);
00234                 }
00235         }
00236 
00237         mnl_socket_close(nl);
00238 
00239         return 0;
00240 }