libmnl
1.0.3
|
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 }