00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <unistd.h>
00005 #include <sys/types.h>
00006 #include <sys/socket.h>
00007 #include <netinet/in.h>
00008 #include <libnfnetlink/libnfnetlink.h>
00009 #include <libnetfilter_log/libnetfilter_log.h>
00010 #include <libnetfilter_log/libipulog.h>
00011
00012
00013 #define PAYLOAD_SIZE 0xffff
00014
00015
00016 struct ipulog_handle
00017 {
00018 struct nflog_handle *nfulh;
00019 struct nflog_g_handle *nful_gh;
00020 struct nlmsghdr *last_nlh;
00021 #if 0
00022 int fd;
00023 u_int8_t blocking;
00024 struct sockaddr_nl local;
00025 struct sockaddr_nl peer;
00026 #endif
00027 struct ulog_packet_msg upmsg;
00028 };
00029
00030 struct ipulog_errmap_t
00031 {
00032 int errcode;
00033 char *message;
00034 } ipulog_errmap[] =
00035 {
00036 { IPULOG_ERR_NONE, "No error" },
00037 { IPULOG_ERR_IMPL, "Not implemented yet" },
00038 { IPULOG_ERR_HANDLE, "Unable to create netlink handle" },
00039 { IPULOG_ERR_SOCKET, "Unable to create netlink socket" },
00040 { IPULOG_ERR_BIND, "Unable to bind netlink socket" },
00041 { IPULOG_ERR_RECVBUF, "Receive buffer size invalid" },
00042 { IPULOG_ERR_RECV, "Error during netlink receive" },
00043 { IPULOG_ERR_NLEOF, "Received EOF on netlink socket" },
00044 { IPULOG_ERR_TRUNC, "Receive message truncated" },
00045 { IPULOG_ERR_INVGR, "Invalid group specified" },
00046 { IPULOG_ERR_INVNL, "Invalid netlink message" },
00047 };
00048
00049
00050 static unsigned int gmask2group(unsigned int gmask)
00051 {
00052 int bit;
00053
00054 for (bit = sizeof(gmask)*4 -1; bit >= 0; bit--) {
00055 if (gmask & (1 << bit))
00056 return bit+1;
00057 }
00058 return 0;
00059 }
00060
00061
00062
00063
00064
00065 int ipulog_errno = IPULOG_ERR_NONE;
00066
00067 char *ipulog_strerror(int errcode)
00068 {
00069 if (errcode < 0 || errcode > IPULOG_MAXERR)
00070 errcode = IPULOG_ERR_IMPL;
00071 return ipulog_errmap[errcode].message;
00072 }
00073
00074
00075 u_int32_t ipulog_group2gmask(u_int32_t group)
00076 {
00077 if (group < 1 || group > 32)
00078 {
00079 ipulog_errno = IPULOG_ERR_INVGR;
00080 return 0;
00081 }
00082 return (1 << (group - 1));
00083 }
00084
00085
00086 struct ipulog_handle *ipulog_create_handle(u_int32_t gmask,
00087 u_int32_t rcvbufsize)
00088 {
00089 int rv;
00090 struct ipulog_handle *h;
00091 unsigned int group = gmask2group(gmask);
00092
00093 h = (struct ipulog_handle *) malloc(sizeof(*h)+PAYLOAD_SIZE);
00094 if (! h) {
00095 ipulog_errno = IPULOG_ERR_HANDLE;
00096 return NULL;
00097 }
00098 memset(h, 0, sizeof(*h));
00099 h->nfulh = nflog_open();
00100 if (!h->nfulh)
00101 goto out_free;
00102
00103
00104 rv = nflog_bind_pf(h->nfulh, AF_INET);
00105 if (rv < 0 && rv != -EEXIST)
00106 goto out_free;
00107
00108 h->nful_gh = nflog_bind_group(h->nfulh, group);
00109 if (!h->nful_gh)
00110 goto out_free;
00111
00112 return h;
00113
00114 out_free:
00115 ipulog_errno = IPULOG_ERR_HANDLE;
00116 free(h);
00117 return NULL;
00118 }
00119
00120 void ipulog_destroy_handle(struct ipulog_handle *h)
00121 {
00122 nflog_unbind_group(h->nful_gh);
00123 nflog_close(h->nfulh);
00124 free(h);
00125 }
00126
00127 ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h,
00128 const unsigned char *buf,
00129 size_t len)
00130 {
00131 struct nlmsghdr *nlh;
00132 struct nfattr *tb[NFULA_MAX];
00133 struct nfulnl_msg_packet_hdr *hdr;
00134
00135 if (!h->last_nlh) {
00136 printf("first\n");
00137 nlh = nfnl_get_msg_first(nflog_nfnlh(h->nfulh), buf, len);
00138 }else {
00139 next_msg: printf("next\n");
00140 nlh = nfnl_get_msg_next(nflog_nfnlh(h->nfulh), buf, len);
00141 }
00142 h->last_nlh = nlh;
00143
00144 if (!nlh)
00145 return NULL;
00146
00147 nfnl_parse_attr(tb, NFULA_MAX, NFM_NFA(NLMSG_DATA(nlh)),
00148 NFM_PAYLOAD(nlh));
00149
00150 if (!tb[NFULA_PACKET_HDR-1])
00151 goto next_msg;
00152
00153
00154 hdr = NFA_DATA(tb[NFULA_PACKET_HDR-1]);
00155 h->upmsg.hook = hdr->hook;
00156
00157 if (tb[NFULA_MARK-1])
00158 h->upmsg.mark = ntohl(*(u_int32_t *)NFA_DATA(tb[NFULA_MARK-1]));
00159 else
00160 h->upmsg.mark = 0;
00161
00162 if (tb[NFULA_TIMESTAMP]) {
00163
00164 h->upmsg.timestamp_sec = h->upmsg.timestamp_usec = 0;
00165 } else
00166 h->upmsg.timestamp_sec = h->upmsg.timestamp_usec = 0;
00167
00168 if (tb[NFULA_IFINDEX_INDEV-1]) {
00169
00170 h->upmsg.indev_name[0] = '\0';
00171 } else
00172 h->upmsg.indev_name[0] = '\0';
00173
00174 if (tb[NFULA_IFINDEX_OUTDEV-1]) {
00175
00176 h->upmsg.outdev_name[0] = '\0';
00177 } else
00178 h->upmsg.outdev_name[0] = '\0';
00179
00180 if (tb[NFULA_HWADDR-1]) {
00181 struct nfulnl_msg_packet_hw *phw = NFA_DATA(tb[NFULA_HWADDR-1]);
00182 h->upmsg.mac_len = ntohs(phw->hw_addrlen);
00183 memcpy(h->upmsg.mac, phw->hw_addr, 8);
00184 } else
00185 h->upmsg.mac_len = 0;
00186
00187 if (tb[NFULA_PREFIX-1]) {
00188 int plen = NFA_PAYLOAD(tb[NFULA_PREFIX-1]);
00189 if (ULOG_PREFIX_LEN < plen)
00190 plen = ULOG_PREFIX_LEN;
00191 memcpy(h->upmsg.prefix, NFA_DATA(tb[NFULA_PREFIX-1]), plen);
00192 h->upmsg.prefix[ULOG_PREFIX_LEN-1] = '\0';
00193 }
00194
00195 if (tb[NFULA_PAYLOAD-1]) {
00196 memcpy(h->upmsg.payload, NFA_DATA(tb[NFULA_PAYLOAD-1]),
00197 NFA_PAYLOAD(tb[NFULA_PAYLOAD-1]));
00198 h->upmsg.data_len = NFA_PAYLOAD(tb[NFULA_PAYLOAD-1]);
00199 } else
00200 h->upmsg.data_len = 0;
00201
00202 return &h->upmsg;
00203 }
00204
00205 ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf,
00206 size_t len, int timeout)
00207 {
00208
00209
00210 return nfnl_recv(nflog_nfnlh(h->nfulh), buf, len);
00211 }
00212
00213
00214 void ipulog_perror(const char *s)
00215 {
00216 if (s)
00217 fputs(s, stderr);
00218 else
00219 fputs("ERROR", stderr);
00220 if (ipulog_errno)
00221 fprintf(stderr, ": %s", ipulog_strerror(ipulog_errno));
00222 if (errno)
00223 fprintf(stderr, ": %s", strerror(errno));
00224 fputc('\n', stderr);
00225 }
00226