00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <unistd.h>
00010 #include <arpa/inet.h>
00011 #include <time.h>
00012 #include <sys/select.h>
00013 #include <string.h>
00014
00015 #include <libmnl/libmnl.h>
00016 #include <linux/netfilter/nfnetlink.h>
00017 #include <linux/netfilter/nfnetlink_conntrack.h>
00018 #include <linux/netfilter/nf_conntrack_common.h>
00019 #include <linux/netfilter/nf_conntrack_tcp.h>
00020
00021 static void put_msg(char *buf, uint16_t i, int seq)
00022 {
00023 struct nlmsghdr *nlh;
00024 struct nfgenmsg *nfh;
00025 struct nlattr *nest1, *nest2;
00026
00027 nlh = mnl_nlmsg_put_header(buf);
00028 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
00029 nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
00030 nlh->nlmsg_seq = seq;
00031
00032 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
00033 nfh->nfgen_family = AF_INET;
00034 nfh->version = NFNETLINK_V0;
00035 nfh->res_id = 0;
00036
00037 nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG);
00038 nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
00039 mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("1.1.1.1"));
00040 mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("2.2.2.2"));
00041 mnl_attr_nest_end(nlh, nest2);
00042
00043 nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
00044 mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP);
00045 mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(i));
00046 mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(1025));
00047 mnl_attr_nest_end(nlh, nest2);
00048 mnl_attr_nest_end(nlh, nest1);
00049
00050 nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY);
00051 nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
00052 mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("2.2.2.2"));
00053 mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("1.1.1.1"));
00054 mnl_attr_nest_end(nlh, nest2);
00055
00056 nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
00057 mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP);
00058 mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(1025));
00059 mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(i));
00060 mnl_attr_nest_end(nlh, nest2);
00061 mnl_attr_nest_end(nlh, nest1);
00062
00063 nest1 = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
00064 nest2 = mnl_attr_nest_start(nlh, CTA_PROTOINFO_TCP);
00065 mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_STATE, TCP_CONNTRACK_SYN_SENT);
00066 mnl_attr_nest_end(nlh, nest2);
00067 mnl_attr_nest_end(nlh, nest1);
00068
00069 mnl_attr_put_u32(nlh, CTA_STATUS, htonl(IPS_CONFIRMED));
00070 mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(1000));
00071 }
00072
00073 static int cb_err(const struct nlmsghdr *nlh, void *data)
00074 {
00075 struct nlmsgerr *err = (void *)(nlh + 1);
00076 if (err->error != 0)
00077 printf("message with seq %u has failed: %s\n",
00078 nlh->nlmsg_seq, strerror(-err->error));
00079 return MNL_CB_OK;
00080 }
00081
00082 static mnl_cb_t cb_ctl_array[NLMSG_MIN_TYPE] = {
00083 [NLMSG_ERROR] = cb_err,
00084 };
00085
00086 static void
00087 send_batch(struct mnl_socket *nl, struct mnl_nlmsg_batch *b, int portid)
00088 {
00089 int ret, fd = mnl_socket_get_fd(nl);
00090 size_t len = mnl_nlmsg_batch_size(b);
00091 char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
00092
00093 ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b), len);
00094 if (ret == -1) {
00095 perror("mnl_socket_recvfrom");
00096 exit(EXIT_FAILURE);
00097 }
00098
00099
00100 struct timeval tv = {
00101 .tv_sec = 0,
00102 .tv_usec = 0
00103 };
00104 fd_set readfds;
00105 FD_ZERO(&readfds);
00106 FD_SET(fd, &readfds);
00107
00108 ret = select(fd+1, &readfds, NULL, NULL, &tv);
00109 if (ret == -1) {
00110 perror("select");
00111 exit(EXIT_FAILURE);
00112 }
00113 while (ret > 0 && FD_ISSET(fd, &readfds)) {
00114 ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf));
00115 if (ret == -1) {
00116 perror("mnl_socket_recvfrom");
00117 exit(EXIT_FAILURE);
00118 }
00119
00120 ret = mnl_cb_run2(rcv_buf, ret, 0, portid,
00121 NULL, NULL, cb_ctl_array,
00122 MNL_ARRAY_SIZE(cb_ctl_array));
00123 if (ret == -1) {
00124 perror("mnl_cb_run");
00125 exit(EXIT_FAILURE);
00126 }
00127
00128 ret = select(fd+1, &readfds, NULL, NULL, &tv);
00129 if (ret == -1) {
00130 perror("select");
00131 exit(EXIT_FAILURE);
00132 }
00133 FD_ZERO(&readfds);
00134 FD_SET(fd, &readfds);
00135 }
00136 }
00137
00138 int main(void)
00139 {
00140 struct mnl_socket *nl;
00141 char snd_buf[MNL_SOCKET_BUFFER_SIZE*2];
00142 struct mnl_nlmsg_batch *b;
00143 int j;
00144 unsigned int seq, portid;
00145 uint16_t i;
00146
00147 nl = mnl_socket_open(NETLINK_NETFILTER);
00148 if (nl == NULL) {
00149 perror("mnl_socket_open");
00150 exit(EXIT_FAILURE);
00151 }
00152 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
00153 perror("mnl_socket_bind");
00154 exit(EXIT_FAILURE);
00155 }
00156 portid = mnl_socket_get_portid(nl);
00157
00158
00159
00160
00161
00162 b = mnl_nlmsg_batch_start(snd_buf, MNL_SOCKET_BUFFER_SIZE);
00163 if (b == NULL) {
00164 perror("mnl_nlmsg_batch_start");
00165 exit(EXIT_FAILURE);
00166 }
00167
00168 seq = time(NULL);
00169 for (i=1024, j=0; i<65535; i++, j++) {
00170 put_msg(mnl_nlmsg_batch_current(b), i, seq+j);
00171
00172
00173
00174 if (mnl_nlmsg_batch_next(b))
00175 continue;
00176
00177 send_batch(nl, b, portid);
00178
00179
00180
00181 mnl_nlmsg_batch_reset(b);
00182 }
00183
00184
00185 if (!mnl_nlmsg_batch_is_empty(b))
00186 send_batch(nl, b, portid);
00187
00188 mnl_nlmsg_batch_stop(b);
00189 mnl_socket_close(nl);
00190
00191 return 0;
00192 }