/** * ipset_print_ip - print IPv4|IPv6 address to string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print IPv4|IPv6 address, address/cidr or address range to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_ip(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env) { const union nf_inet_addr *ip; uint8_t family, cidr; int flags, size, offset = 0; enum ipset_opt cidropt; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2); D("len: %u", len); family = ipset_data_family(data); cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2; if (ipset_data_test(data, cidropt)) { cidr = *(const uint8_t *) ipset_data_get(data, cidropt); D("CIDR: %u", cidr); } else cidr = family == AF_INET6 ? 128 : 32; flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST; ip = ipset_data_get(data, opt); assert(ip); if (family == AF_INET) size = snprintf_ipv4(buf, len, flags, ip, cidr); else if (family == AF_INET6) size = snprintf_ipv6(buf, len, flags, ip, cidr); else return -1; D("size %i, len %u", size, len); SNPRINTF_FAILURE(size, len, offset); D("len: %u, offset %u", len, offset); if (!ipset_data_test(data, IPSET_OPT_IP_TO)) return offset; size = snprintf(buf + offset, len, "%s", IPSET_RANGE_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); ip = ipset_data_get(data, IPSET_OPT_IP_TO); if (family == AF_INET) size = snprintf_ipv4(buf + offset, len, flags, ip, cidr); else if (family == AF_INET6) size = snprintf_ipv6(buf + offset, len, flags, ip, cidr); else return -1; SNPRINTF_FAILURE(size, len, offset); return offset; }
/** * ipset_print_elem - print ADT elem according to settype * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print (multipart) element according to settype * * Return lenght of printed string or error size. */ int ipset_print_elem(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt UNUSED, uint8_t env) { const struct ipset_type *type; int size, offset = 0; assert(buf); assert(len > 0); assert(data); type = ipset_data_get(data, IPSET_OPT_TYPE); if (!type) return -1; size = type->elem[IPSET_DIM_ONE - 1].print(buf, len, data, type->elem[IPSET_DIM_ONE - 1].opt, env); SNPRINTF_FAILURE(size, len, offset); IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt), "print second elem"); if (type->dimension == IPSET_DIM_ONE || (type->last_elem_optional && !ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt))) return offset; size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); size = type->elem[IPSET_DIM_TWO - 1].print(buf + offset, len, data, type->elem[IPSET_DIM_TWO - 1].opt, env); SNPRINTF_FAILURE(size, len, offset); if (type->dimension == IPSET_DIM_TWO || (type->last_elem_optional && !ipset_data_test(data, type->elem[IPSET_DIM_THREE - 1].opt))) return offset; size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); size = type->elem[IPSET_DIM_THREE - 1].print(buf + offset, len, data, type->elem[IPSET_DIM_THREE - 1].opt, env); SNPRINTF_FAILURE(size, len, offset); if (type->dimension == IPSET_DIM_THREE || (type->last_elem_optional && !ipset_data_test(data, type->elem[IPSET_DIM_FOUR - 1].opt))) return offset; size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); size = type->elem[IPSET_DIM_FOUR - 1].print(buf + offset, len, data, type->elem[IPSET_DIM_FOUR - 1].opt, env); SNPRINTF_FAILURE(size, len, offset); return offset; }
/** * ipset_print_port - print port or port range * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print port or port range to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_port(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt ASSERT_UNUSED, uint8_t env UNUSED) { const uint16_t *port; int size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_PORT); if (len < 2*strlen("65535") + 2) return -1; port = ipset_data_get(data, IPSET_OPT_PORT); assert(port); size = snprintf(buf, len, "%u", *port); SNPRINTF_FAILURE(size, len, offset); if (ipset_data_test(data, IPSET_OPT_PORT_TO)) { port = ipset_data_get(data, IPSET_OPT_PORT_TO); size = snprintf(buf + offset, len, "%s%u", IPSET_RANGE_SEPARATOR, *port); SNPRINTF_FAILURE(size, len, offset); } return offset; }
/** * ipset_print_ipaddr - print IPv4|IPv6 address to string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print IPv4|IPv6 address or address/cidr to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_ipaddr(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env) { const union nf_inet_addr *ip; uint8_t family, cidr; enum ipset_opt cidropt; int flags; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP_TO || opt == IPSET_OPT_IP2); family = ipset_data_family(data); cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2; if (ipset_data_test(data, cidropt)) cidr = *(const uint8_t *) ipset_data_get(data, cidropt); else cidr = family == AF_INET6 ? 128 : 32; flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST; ip = ipset_data_get(data, opt); assert(ip); if (family == AF_INET) return snprintf_ipv4(buf, len, flags, ip, cidr); else if (family == AF_INET6) return snprintf_ipv6(buf, len, flags, ip, cidr); return -1; }
/** * ipset_print_iface - print interface element string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print interface element string to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_iface(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env UNUSED) { const char *name; int size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_IFACE); if (len < IFNAMSIZ + strlen("physdev:")) return -1; if (ipset_data_test(data, IPSET_OPT_PHYSDEV)) { size = snprintf(buf, len, "physdev:"); SNPRINTF_FAILURE(size, len, offset); } name = ipset_data_get(data, opt); assert(name); size = snprintf(buf, len, "%s", name); SNPRINTF_FAILURE(size, len, offset); return offset; }
/** * ipset_print_name - print setname element string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print setname element string to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_name(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env UNUSED) { const char *name; int size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_NAME); if (len < 2*IPSET_MAXNAMELEN + 2 + strlen("before")) return -1; name = ipset_data_get(data, opt); assert(name); size = snprintf(buf, len, "%s", name); SNPRINTF_FAILURE(size, len, offset); if (ipset_data_test(data, IPSET_OPT_NAMEREF)) { bool before = false; if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FLAGS))) { const uint32_t *flags = ipset_data_get(data, IPSET_OPT_FLAGS); before = (*flags) & IPSET_FLAG_BEFORE; } size = snprintf(buf + offset, len, " %s %s", before ? "before" : "after", (const char *) ipset_data_get(data, IPSET_OPT_NAMEREF)); SNPRINTF_FAILURE(size, len, offset); } return offset; }