4 * IPQ userspace library.
6 * Please note that this library is still developmental, and there may
9 * Author: James Morris <jmorris@intercode.com.au>
11 * 07-11-2001 Modified by Fernando Anton to add support for IPv6.
13 * Copyright (c) 2000-2001 Netfilter Core Team
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
32 #include <sys/types.h>
34 #include <libipq/libipq.h>
35 #include <netinet/in.h>
36 #include <linux/netfilter.h>
38 /****************************************************************************
42 ****************************************************************************/
63 #define IPQ_MAXERR IPQ_ERR_PROTOCOL
69 { IPQ_ERR_NONE
, "Unknown error" },
70 { IPQ_ERR_IMPL
, "Implementation error" },
71 { IPQ_ERR_HANDLE
, "Unable to create netlink handle" },
72 { IPQ_ERR_SOCKET
, "Unable to create netlink socket" },
73 { IPQ_ERR_BIND
, "Unable to bind netlink socket" },
74 { IPQ_ERR_BUFFER
, "Unable to allocate buffer" },
75 { IPQ_ERR_RECV
, "Failed to receive netlink message" },
76 { IPQ_ERR_NLEOF
, "Received EOF on netlink socket" },
77 { IPQ_ERR_ADDRLEN
, "Invalid peer address length" },
78 { IPQ_ERR_STRUNC
, "Sent message truncated" },
79 { IPQ_ERR_RTRUNC
, "Received message truncated" },
80 { IPQ_ERR_NLRECV
, "Received error from netlink" },
81 { IPQ_ERR_SEND
, "Failed to send netlink message" },
82 { IPQ_ERR_SUPP
, "Operation not supported" },
83 { IPQ_ERR_RECVBUF
, "Receive buffer size invalid" },
84 { IPQ_ERR_TIMEOUT
, "Timeout"},
85 { IPQ_ERR_PROTOCOL
, "Invalid protocol specified" }
88 static int ipq_errno
= IPQ_ERR_NONE
;
90 static ssize_t
ipq_netlink_sendto(const struct ipq_handle
*h
,
91 const void *msg
, size_t len
);
93 static ssize_t
ipq_netlink_recvfrom(const struct ipq_handle
*h
,
94 unsigned char *buf
, size_t len
,
97 static ssize_t
ipq_netlink_sendmsg(const struct ipq_handle
*h
,
98 const struct msghdr
*msg
,
101 static char *ipq_strerror(int errcode
);
103 static ssize_t
ipq_netlink_sendto(const struct ipq_handle
*h
,
104 const void *msg
, size_t len
)
106 int status
= sendto(h
->fd
, msg
, len
, 0,
107 (struct sockaddr
*)&h
->peer
, sizeof(h
->peer
));
109 ipq_errno
= IPQ_ERR_SEND
;
113 static ssize_t
ipq_netlink_sendmsg(const struct ipq_handle
*h
,
114 const struct msghdr
*msg
,
117 int status
= sendmsg(h
->fd
, msg
, flags
);
119 ipq_errno
= IPQ_ERR_SEND
;
123 static ssize_t
ipq_netlink_recvfrom(const struct ipq_handle
*h
,
124 unsigned char *buf
, size_t len
,
127 unsigned int addrlen
;
129 struct nlmsghdr
*nlh
;
131 if (len
< sizeof(struct nlmsgerr
)) {
132 ipq_errno
= IPQ_ERR_RECVBUF
;
135 addrlen
= sizeof(h
->peer
);
143 /* non-block non-timeout */
147 tv
.tv_sec
= timeout
/ 1000000;
148 tv
.tv_usec
= timeout
% 1000000;
152 FD_SET(h
->fd
, &read_fds
);
153 ret
= select(h
->fd
+1, &read_fds
, NULL
, NULL
, &tv
);
155 if (errno
== EINTR
) {
158 ipq_errno
= IPQ_ERR_RECV
;
162 if (!FD_ISSET(h
->fd
, &read_fds
)) {
163 ipq_errno
= IPQ_ERR_TIMEOUT
;
167 status
= recvfrom(h
->fd
, buf
, len
, 0,
168 (struct sockaddr
*)&h
->peer
, &addrlen
);
170 ipq_errno
= IPQ_ERR_RECV
;
173 if (addrlen
!= sizeof(h
->peer
)) {
174 ipq_errno
= IPQ_ERR_RECV
;
177 if (h
->peer
.nl_pid
!= 0) {
178 ipq_errno
= IPQ_ERR_RECV
;
182 ipq_errno
= IPQ_ERR_NLEOF
;
185 nlh
= (struct nlmsghdr
*)buf
;
186 if (nlh
->nlmsg_flags
& MSG_TRUNC
|| nlh
->nlmsg_len
> status
) {
187 ipq_errno
= IPQ_ERR_RTRUNC
;
193 static char *ipq_strerror(int errcode
)
195 if (errcode
< 0 || errcode
> IPQ_MAXERR
)
196 errcode
= IPQ_ERR_IMPL
;
197 return ipq_errmap
[errcode
].message
;
200 /****************************************************************************
204 ****************************************************************************/
207 * Create and initialise an ipq handle.
209 struct ipq_handle
*ipq_create_handle(u_int32_t flags
, u_int32_t protocol
)
212 struct ipq_handle
*h
;
214 h
= (struct ipq_handle
*)malloc(sizeof(struct ipq_handle
));
216 ipq_errno
= IPQ_ERR_HANDLE
;
220 memset(h
, 0, sizeof(struct ipq_handle
));
222 if (protocol
== NFPROTO_IPV4
)
223 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_FIREWALL
);
224 else if (protocol
== NFPROTO_IPV6
)
225 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_IP6_FW
);
227 ipq_errno
= IPQ_ERR_PROTOCOL
;
233 ipq_errno
= IPQ_ERR_SOCKET
;
238 memset(&h
->local
, 0, sizeof(struct sockaddr_nl
));
239 h
->local
.nl_family
= AF_NETLINK
;
240 h
->local
.nl_pid
= getpid();
241 h
->local
.nl_groups
= 0;
242 status
= bind(h
->fd
, (struct sockaddr
*)&h
->local
, sizeof(h
->local
));
244 ipq_errno
= IPQ_ERR_BIND
;
249 memset(&h
->peer
, 0, sizeof(struct sockaddr_nl
));
250 h
->peer
.nl_family
= AF_NETLINK
;
252 h
->peer
.nl_groups
= 0;
257 * No error condition is checked here at this stage, but it may happen
258 * if/when reliable messaging is implemented.
260 int ipq_destroy_handle(struct ipq_handle
*h
)
269 int ipq_set_mode(const struct ipq_handle
*h
,
270 u_int8_t mode
, size_t range
)
277 memset(&req
, 0, sizeof(req
));
278 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
));
279 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
280 req
.nlh
.nlmsg_type
= IPQM_MODE
;
281 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
282 req
.pm
.msg
.mode
.value
= mode
;
283 req
.pm
.msg
.mode
.range
= range
;
284 return ipq_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
288 * timeout is in microseconds (1 second is 1000000 (1 million) microseconds)
291 ssize_t
ipq_read(const struct ipq_handle
*h
,
292 unsigned char *buf
, size_t len
, int timeout
)
294 return ipq_netlink_recvfrom(h
, buf
, len
, timeout
);
297 int ipq_message_type(const unsigned char *buf
)
299 return ((struct nlmsghdr
*)buf
)->nlmsg_type
;
302 int ipq_get_msgerr(const unsigned char *buf
)
304 struct nlmsghdr
*h
= (struct nlmsghdr
*)buf
;
305 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
309 ipq_packet_msg_t
*ipq_get_packet(const unsigned char *buf
)
311 return NLMSG_DATA((struct nlmsghdr
*)(buf
));
314 int ipq_set_verdict(const struct ipq_handle
*h
,
316 unsigned int verdict
,
327 memset(&nlh
, 0, sizeof(nlh
));
328 nlh
.nlmsg_flags
= NLM_F_REQUEST
;
329 nlh
.nlmsg_type
= IPQM_VERDICT
;
330 nlh
.nlmsg_pid
= h
->local
.nl_pid
;
331 memset(&pm
, 0, sizeof(pm
));
332 pm
.msg
.verdict
.value
= verdict
;
333 pm
.msg
.verdict
.id
= id
;
334 pm
.msg
.verdict
.data_len
= data_len
;
335 iov
[0].iov_base
= &nlh
;
336 iov
[0].iov_len
= sizeof(nlh
);
337 iov
[1].iov_base
= &pm
;
338 iov
[1].iov_len
= sizeof(pm
);
339 tlen
= sizeof(nlh
) + sizeof(pm
);
341 if (data_len
&& buf
) {
342 iov
[2].iov_base
= buf
;
343 iov
[2].iov_len
= data_len
;
347 msg
.msg_name
= (void *)&h
->peer
;
348 msg
.msg_namelen
= sizeof(h
->peer
);
350 msg
.msg_iovlen
= nvecs
;
351 msg
.msg_control
= NULL
;
352 msg
.msg_controllen
= 0;
354 nlh
.nlmsg_len
= tlen
;
355 return ipq_netlink_sendmsg(h
, &msg
, 0);
358 /* Not implemented yet */
359 int ipq_ctl(const struct ipq_handle
*h
, int request
, ...)
364 char *ipq_errstr(void)
366 return ipq_strerror(ipq_errno
);
369 void ipq_perror(const char *s
)
374 fputs("ERROR", stderr
);
376 fprintf(stderr
, ": %s", ipq_errstr());
378 fprintf(stderr
, ": %s", strerror(errno
));