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