1d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#ifndef _LIBXT_SET_H
2d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#define _LIBXT_SET_H
3d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
4d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#include <unistd.h>
5c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski#include <fcntl.h>
6d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#include <sys/types.h>
7d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#include <sys/socket.h>
8d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#include <errno.h>
9cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik#include "../iptables/xshared.h"
10d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
11d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#ifdef DEBUG
12d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#define DEBUGP(x, args...) fprintf(stderr, x , ## args)
13d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#else
14d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#define DEBUGP(x, args...)
15d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#endif
16d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
17d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikstatic int
18d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikget_version(unsigned *version)
19d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik{
20d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
21d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	struct ip_set_req_version req_version;
22d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	socklen_t size = sizeof(req_version);
23d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
24d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (sockfd < 0)
25d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
26d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			      "Can't open socket to ipset.\n");
27d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
28c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
29c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski		xtables_error(OTHER_PROBLEM,
30c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski			      "Could not set close on exec: %s\n",
31c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski			      strerror(errno));
32c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski	}
33c0aa38e22e8a09fcb1898ad0e042eaf6314d2d42Maciej Żenczykowski
34d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	req_version.op = IP_SET_OP_VERSION;
35d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
36d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (res != 0)
37d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
38d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			      "Kernel module xt_set is not loaded in.\n");
39d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
40d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	*version = req_version.version;
41d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
42d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	return sockfd;
43d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik}
44d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
45d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikstatic void
46d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikget_set_byid(char *setname, ip_set_id_t idx)
47d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik{
48d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	struct ip_set_req_get_set req;
49d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	socklen_t size = sizeof(struct ip_set_req_get_set);
50d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	int res, sockfd;
51d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
52d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	sockfd = get_version(&req.version);
53d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	req.op = IP_SET_OP_GET_BYINDEX;
54d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	req.set.index = idx;
55d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
56d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	close(sockfd);
57d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
58d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (res != 0)
59d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
60d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"Problem when communicating with ipset, errno=%d.\n",
61d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			errno);
62d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (size != sizeof(struct ip_set_req_get_set))
63d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
64d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"Incorrect return size from kernel during ipset lookup, "
65d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"(want %zu, got %zu)\n",
66d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			sizeof(struct ip_set_req_get_set), (size_t)size);
67d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (req.set.name[0] == '\0')
68d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(PARAMETER_PROBLEM,
69d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"Set with index %i in kernel doesn't exist.\n", idx);
70d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
71d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	strncpy(setname, req.set.name, IPSET_MAXNAMELEN);
72d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik}
73d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
74d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikstatic void
75cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsikget_set_byname_only(const char *setname, struct xt_set_info *info,
76cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		    int sockfd, unsigned int version)
77d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik{
78cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	struct ip_set_req_get_set req = { .version = version };
79d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	socklen_t size = sizeof(struct ip_set_req_get_set);
80cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	int res;
81d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
82d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	req.op = IP_SET_OP_GET_BYNAME;
83d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	strncpy(req.set.name, setname, IPSET_MAXNAMELEN);
84d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	req.set.name[IPSET_MAXNAMELEN - 1] = '\0';
85d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
86d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	close(sockfd);
87d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
88d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (res != 0)
89d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
90d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"Problem when communicating with ipset, errno=%d.\n",
91d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			errno);
92d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (size != sizeof(struct ip_set_req_get_set))
93d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
94d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"Incorrect return size from kernel during ipset lookup, "
95d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			"(want %zu, got %zu)\n",
96d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			sizeof(struct ip_set_req_get_set), (size_t)size);
97d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (req.set.index == IPSET_INVALID_ID)
98d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(PARAMETER_PROBLEM,
99d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			      "Set %s doesn't exist.\n", setname);
100d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
101d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	info->index = req.set.index;
102d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik}
103d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
104d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikstatic void
105cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsikget_set_byname(const char *setname, struct xt_set_info *info)
106cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik{
107cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	struct ip_set_req_get_set_family req;
108cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	socklen_t size = sizeof(struct ip_set_req_get_set_family);
109cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	int res, sockfd, version;
110cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik
111cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	sockfd = get_version(&req.version);
112cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	version = req.version;
113cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	req.op = IP_SET_OP_GET_FNAME;
114cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	strncpy(req.set.name, setname, IPSET_MAXNAMELEN);
115cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	req.set.name[IPSET_MAXNAMELEN - 1] = '\0';
116cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
117cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik
118cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	if (res != 0 && errno == EBADMSG)
119cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		/* Backward compatibility */
120cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		return get_set_byname_only(setname, info, sockfd, version);
121cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik
122cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	close(sockfd);
123cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	if (res != 0)
124cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
125cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			"Problem when communicating with ipset, errno=%d.\n",
126cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			errno);
127cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	if (size != sizeof(struct ip_set_req_get_set_family))
128cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		xtables_error(OTHER_PROBLEM,
129cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			"Incorrect return size from kernel during ipset lookup, "
130cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			"(want %zu, got %zu)\n",
131cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			sizeof(struct ip_set_req_get_set_family),
132cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			(size_t)size);
133cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	if (req.set.index == IPSET_INVALID_ID)
134cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		xtables_error(PARAMETER_PROBLEM,
135cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			      "Set %s doesn't exist.\n", setname);
136cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	if (!(req.family == afinfo->family ||
137cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	      req.family == NFPROTO_UNSPEC))
138cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik		xtables_error(PARAMETER_PROBLEM,
139cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			      "The protocol family of set %s is %s, "
140cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			      "which is not applicable.\n",
141cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			      setname,
142cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik			      req.family == NFPROTO_IPV4 ? "IPv4" : "IPv6");
143cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik
144cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik	info->index = req.set.index;
145cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik}
146cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsik
147cf1f03f8f3cf2db577a9ddee254cc7f886129d18Jozsef Kadlecsikstatic void
148d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikparse_dirs_v0(const char *opt_arg, struct xt_set_info_v0 *info)
149d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik{
150d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	char *saved = strdup(opt_arg);
151d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	char *ptr, *tmp = saved;
152d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	int i = 0;
153d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
154d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	while (i < (IPSET_DIM_MAX - 1) && tmp != NULL) {
155d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		ptr = strsep(&tmp, ",");
156d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		if (strncmp(ptr, "src", 3) == 0)
157d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			info->u.flags[i++] |= IPSET_SRC;
158d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		else if (strncmp(ptr, "dst", 3) == 0)
159d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			info->u.flags[i++] |= IPSET_DST;
160d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		else
161d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			xtables_error(PARAMETER_PROBLEM,
162d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik				"You must spefify (the comma separated list of) 'src' or 'dst'.");
163d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	}
164d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
165d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (tmp)
166d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(PARAMETER_PROBLEM,
167d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			      "Can't be more src/dst options than %i.",
168aeb8af909befedbfc85e9f184471b219e4ea191aJozsef Kadlecsik			      IPSET_DIM_MAX);
169d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
170d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	free(saved);
171d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik}
172d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
173d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikstatic void
174d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsikparse_dirs(const char *opt_arg, struct xt_set_info *info)
175d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik{
176d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	char *saved = strdup(opt_arg);
177d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	char *ptr, *tmp = saved;
178d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
179aeb8af909befedbfc85e9f184471b219e4ea191aJozsef Kadlecsik	while (info->dim < IPSET_DIM_MAX && tmp != NULL) {
180d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		info->dim++;
181d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		ptr = strsep(&tmp, ",");
182d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		if (strncmp(ptr, "src", 3) == 0)
183d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			info->flags |= (1 << info->dim);
184d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		else if (strncmp(ptr, "dst", 3) != 0)
185d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			xtables_error(PARAMETER_PROBLEM,
186d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik				"You must spefify (the comma separated list of) 'src' or 'dst'.");
187d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	}
188d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
189d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	if (tmp)
190d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik		xtables_error(PARAMETER_PROBLEM,
191d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik			      "Can't be more src/dst options than %i.",
192aeb8af909befedbfc85e9f184471b219e4ea191aJozsef Kadlecsik			      IPSET_DIM_MAX);
193d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
194d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik	free(saved);
195d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik}
196d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik
197d40f1628c3717daebc437a398a285e371b5b6f7fJozsef Kadlecsik#endif /*_LIBXT_SET_H*/
198