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>
36 /****************************************************************************
40 ****************************************************************************/
61 #define IPQ_MAXERR IPQ_ERR_PROTOCOL
67 { IPQ_ERR_NONE
, "Unknown error" },
68 { IPQ_ERR_IMPL
, "Implementation error" },
69 { IPQ_ERR_HANDLE
, "Unable to create netlink handle" },
70 { IPQ_ERR_SOCKET
, "Unable to create netlink socket" },
71 { IPQ_ERR_BIND
, "Unable to bind netlink socket" },
72 { IPQ_ERR_BUFFER
, "Unable to allocate buffer" },
73 { IPQ_ERR_RECV
, "Failed to receive netlink message" },
74 { IPQ_ERR_NLEOF
, "Received EOF on netlink socket" },
75 { IPQ_ERR_ADDRLEN
, "Invalid peer address length" },
76 { IPQ_ERR_STRUNC
, "Sent message truncated" },
77 { IPQ_ERR_RTRUNC
, "Received message truncated" },
78 { IPQ_ERR_NLRECV
, "Received error from netlink" },
79 { IPQ_ERR_SEND
, "Failed to send netlink message" },
80 { IPQ_ERR_SUPP
, "Operation not supported" },
81 { IPQ_ERR_RECVBUF
, "Receive buffer size invalid" },
82 { IPQ_ERR_TIMEOUT
, "Timeout"},
83 { IPQ_ERR_PROTOCOL
, "Invalid protocol specified" }
86 static int ipq_errno
= IPQ_ERR_NONE
;
88 static ssize_t
ipq_netlink_sendto(const struct ipq_handle
*h
,
89 const void *msg
, size_t len
);
91 static ssize_t
ipq_netlink_recvfrom(const struct ipq_handle
*h
,
92 unsigned char *buf
, size_t len
,
95 static ssize_t
ipq_netlink_sendmsg(const struct ipq_handle
*h
,
96 const struct msghdr
*msg
,
99 static char *ipq_strerror(int errcode
);
101 static ssize_t
ipq_netlink_sendto(const struct ipq_handle
*h
,
102 const void *msg
, size_t len
)
104 int status
= sendto(h
->fd
, msg
, len
, 0,
105 (struct sockaddr
*)&h
->peer
, sizeof(h
->peer
));
107 ipq_errno
= IPQ_ERR_SEND
;
111 static ssize_t
ipq_netlink_sendmsg(const struct ipq_handle
*h
,
112 const struct msghdr
*msg
,
115 int status
= sendmsg(h
->fd
, msg
, flags
);
117 ipq_errno
= IPQ_ERR_SEND
;
121 static ssize_t
ipq_netlink_recvfrom(const struct ipq_handle
*h
,
122 unsigned char *buf
, size_t len
,
125 unsigned int addrlen
;
127 struct nlmsghdr
*nlh
;
129 if (len
< sizeof(struct nlmsgerr
)) {
130 ipq_errno
= IPQ_ERR_RECVBUF
;
133 addrlen
= sizeof(h
->peer
);
141 /* non-block non-timeout */
145 tv
.tv_sec
= timeout
/ 1000000;
146 tv
.tv_usec
= timeout
% 1000000;
150 FD_SET(h
->fd
, &read_fds
);
151 ret
= select(h
->fd
+1, &read_fds
, NULL
, NULL
, &tv
);
153 if (errno
== EINTR
) {
156 ipq_errno
= IPQ_ERR_RECV
;
160 if (!FD_ISSET(h
->fd
, &read_fds
)) {
161 ipq_errno
= IPQ_ERR_TIMEOUT
;
165 status
= recvfrom(h
->fd
, buf
, len
, 0,
166 (struct sockaddr
*)&h
->peer
, &addrlen
);
168 ipq_errno
= IPQ_ERR_RECV
;
171 if (addrlen
!= sizeof(h
->peer
)) {
172 ipq_errno
= IPQ_ERR_RECV
;
175 if (h
->peer
.nl_pid
!= 0) {
176 ipq_errno
= IPQ_ERR_RECV
;
180 ipq_errno
= IPQ_ERR_NLEOF
;
183 nlh
= (struct nlmsghdr
*)buf
;
184 if (nlh
->nlmsg_flags
& MSG_TRUNC
|| nlh
->nlmsg_len
> status
) {
185 ipq_errno
= IPQ_ERR_RTRUNC
;
191 static char *ipq_strerror(int errcode
)
193 if (errcode
< 0 || errcode
> IPQ_MAXERR
)
194 errcode
= IPQ_ERR_IMPL
;
195 return ipq_errmap
[errcode
].message
;
198 /****************************************************************************
202 ****************************************************************************/
205 * Create and initialise an ipq handle.
207 struct ipq_handle
*ipq_create_handle(u_int32_t flags
, u_int32_t protocol
)
210 struct ipq_handle
*h
;
212 h
= (struct ipq_handle
*)malloc(sizeof(struct ipq_handle
));
214 ipq_errno
= IPQ_ERR_HANDLE
;
218 memset(h
, 0, sizeof(struct ipq_handle
));
220 if (protocol
== PF_INET
)
221 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_FIREWALL
);
222 else if (protocol
== PF_INET6
)
223 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_IP6_FW
);
225 ipq_errno
= IPQ_ERR_PROTOCOL
;
231 ipq_errno
= IPQ_ERR_SOCKET
;
236 memset(&h
->local
, 0, sizeof(struct sockaddr_nl
));
237 h
->local
.nl_family
= AF_NETLINK
;
238 h
->local
.nl_pid
= getpid();
239 h
->local
.nl_groups
= 0;
240 status
= bind(h
->fd
, (struct sockaddr
*)&h
->local
, sizeof(h
->local
));
242 ipq_errno
= IPQ_ERR_BIND
;
247 memset(&h
->peer
, 0, sizeof(struct sockaddr_nl
));
248 h
->peer
.nl_family
= AF_NETLINK
;
250 h
->peer
.nl_groups
= 0;
255 * No error condition is checked here at this stage, but it may happen
256 * if/when reliable messaging is implemented.
258 int ipq_destroy_handle(struct ipq_handle
*h
)
267 int ipq_set_mode(const struct ipq_handle
*h
,
268 u_int8_t mode
, size_t range
)
275 memset(&req
, 0, sizeof(req
));
276 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
));
277 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
278 req
.nlh
.nlmsg_type
= IPQM_MODE
;
279 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
280 req
.pm
.msg
.mode
.value
= mode
;
281 req
.pm
.msg
.mode
.range
= range
;
282 return ipq_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
286 * timeout is in microseconds (1 second is 1000000 (1 million) microseconds)
289 ssize_t
ipq_read(const struct ipq_handle
*h
,
290 unsigned char *buf
, size_t len
, int timeout
)
292 return ipq_netlink_recvfrom(h
, buf
, len
, timeout
);
295 int ipq_message_type(const unsigned char *buf
)
297 return ((struct nlmsghdr
*)buf
)->nlmsg_type
;
300 int ipq_get_msgerr(const unsigned char *buf
)
302 struct nlmsghdr
*h
= (struct nlmsghdr
*)buf
;
303 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(h
);
307 ipq_packet_msg_t
*ipq_get_packet(const unsigned char *buf
)
309 return NLMSG_DATA((struct nlmsghdr
*)(buf
));
312 int ipq_set_verdict(const struct ipq_handle
*h
,
314 unsigned int verdict
,
325 memset(&nlh
, 0, sizeof(nlh
));
326 nlh
.nlmsg_flags
= NLM_F_REQUEST
;
327 nlh
.nlmsg_type
= IPQM_VERDICT
;
328 nlh
.nlmsg_pid
= h
->local
.nl_pid
;
329 memset(&pm
, 0, sizeof(pm
));
330 pm
.msg
.verdict
.value
= verdict
;
331 pm
.msg
.verdict
.id
= id
;
332 pm
.msg
.verdict
.data_len
= data_len
;
333 iov
[0].iov_base
= &nlh
;
334 iov
[0].iov_len
= sizeof(nlh
);
335 iov
[1].iov_base
= &pm
;
336 iov
[1].iov_len
= sizeof(pm
);
337 tlen
= sizeof(nlh
) + sizeof(pm
);
339 if (data_len
&& buf
) {
340 iov
[2].iov_base
= buf
;
341 iov
[2].iov_len
= data_len
;
345 msg
.msg_name
= (void *)&h
->peer
;
346 msg
.msg_namelen
= sizeof(h
->peer
);
348 msg
.msg_iovlen
= nvecs
;
349 msg
.msg_control
= NULL
;
350 msg
.msg_controllen
= 0;
352 nlh
.nlmsg_len
= tlen
;
353 return ipq_netlink_sendmsg(h
, &msg
, 0);
356 /* Not implemented yet */
357 int ipq_ctl(const struct ipq_handle
*h
, int request
, ...)
362 char *ipq_errstr(void)
364 return ipq_strerror(ipq_errno
);
367 void ipq_perror(const char *s
)
372 fputs("ERROR", stderr
);
374 fprintf(stderr
, ": %s", ipq_errstr());
376 fprintf(stderr
, ": %s", strerror(errno
));