/** * ipset_print_ether - print ethernet address to string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print Ethernet address to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_ether(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env UNUSED) { const unsigned char *ether; int i, size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_ETHER); if (len < ETH_ALEN*3) return -1; ether = ipset_data_get(data, opt); assert(ether); size = snprintf(buf, len, "%02X", ether[0]); SNPRINTF_FAILURE(size, len, offset); for (i = 1; i < ETH_ALEN; i++) { size = snprintf(buf + offset, len, ":%02X", ether[i]); SNPRINTF_FAILURE(size, len, offset); } return offset; }
/** * 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_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_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; }
int ipset_print_skbmark(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env UNUSED) { int size, offset = 0; const uint64_t *skbmark; uint32_t mark, mask; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_SKBMARK); skbmark = ipset_data_get(data, IPSET_OPT_SKBMARK); assert(skbmark); mark = *skbmark >> 32; mask = *skbmark & 0xffffffff; if (mask == 0xffffffff) size = snprintf(buf + offset, len, "0x%"PRIx32, mark); else size = snprintf(buf + offset, len, "0x%"PRIx32"/0x%"PRIx32, mark, mask); SNPRINTF_FAILURE(size, len, offset); return offset; }
/** * ipset_print_proto_port - print proto:port * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print protocol and port to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_proto_port(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt ASSERT_UNUSED, uint8_t env UNUSED) { int size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT2); if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) { uint8_t proto = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO); size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env); SNPRINTF_FAILURE(size, len, offset); if (len < 2) return -ENOSPC; size = snprintf(buf + offset, len, IPSET_PROTO_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); switch (proto) { case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_UDP: case IPPROTO_UDPLITE: break; case IPPROTO_ICMP: size = ipset_print_icmp(buf + offset, len, data, opt, env); goto out; case IPPROTO_ICMPV6: size = ipset_print_icmpv6(buf + offset, len, data, opt, env); goto out; default: break; } } size = ipset_print_port(buf + offset, len, data, opt, env); out: 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].print(buf, len, data, type->elem[IPSET_DIM_ONE].opt, env); SNPRINTF_FAILURE(size, len, offset); IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt), "print second elem"); if (type->dimension == IPSET_DIM_ONE || (type->last_elem_optional && !ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt))) return offset; size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); size = type->elem[IPSET_DIM_TWO].print(buf + offset, len, data, type->elem[IPSET_DIM_TWO].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].opt))) return offset; size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR); SNPRINTF_FAILURE(size, len, offset); size = type->elem[IPSET_DIM_THREE].print(buf + offset, len, data, type->elem[IPSET_DIM_THREE].opt, env); 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; }
/** * ipset_print_comment - print arbitrary parameter string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print arbitrary string to output buffer. * * Return length of printed string or error size. */ int ipset_print_comment(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env UNUSED) { const char *comment; int size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_ADT_COMMENT); comment = ipset_data_get(data, opt); assert(comment); size = snprintf(buf + offset, len, "\"%s\"", comment); SNPRINTF_FAILURE(size, len, offset); return offset; }
int ipset_print_skbprio(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, uint8_t env UNUSED) { int size, offset = 0; const uint32_t *skbprio; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_SKBPRIO); skbprio = ipset_data_get(data, opt); assert(skbprio); size = snprintf(buf + offset, len, "%x:%x", *skbprio >> 16, *skbprio & 0xffff); SNPRINTF_FAILURE(size, len, offset); return offset; }
/** * ipset_print_mark - print mark to string * @buf: printing buffer * @len: length of available buffer space * @data: data blob * @opt: the option kind * @env: environment flags * * Print mark to output buffer. * * Return lenght of printed string or error size. */ int ipset_print_mark(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt ASSERT_UNUSED, uint8_t env UNUSED) { const uint32_t *mark; int size, offset = 0; assert(buf); assert(len > 0); assert(data); assert(opt == IPSET_OPT_MARK || opt == IPSET_OPT_MARKMASK); mark = ipset_data_get(data, opt); assert(mark); size = snprintf(buf, len, "0x%08"PRIx32, *mark); SNPRINTF_FAILURE(size, len, offset); return offset; }