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