/* * Flushes given table specified by @oh->ntlv. * Returns 0 on success. */ static int table_flush(ipfw_obj_header *oh) { if (do_set3(IP_FW_TABLE_XFLUSH, &oh->opheader, sizeof(*oh)) != 0) return (-1); return (0); }
/* * Destroys given table specified by @oh->ntlv. * Returns 0 on success. */ static int table_destroy(ipfw_obj_header *oh) { if (do_set3(IP_FW_TABLE_XDESTROY, &oh->opheader, sizeof(*oh)) != 0) return (-1); return (0); }
/* * Reset NPTv6 instance statistics specified by @oh->ntlv. * Request: [ ipfw_obj_header ] */ static void nptv6_reset_stats(const char *name, uint8_t set) { ipfw_obj_header oh; memset(&oh, 0, sizeof(oh)); nptv6_fill_ntlv(&oh.ntlv, name, set); if (do_set3(IP_FW_NPTV6_RESET_STATS, &oh.opheader, sizeof(oh)) != 0) err(EX_OSERR, "failed to reset stats for instance %s", name); }
/* * Destroys NPTv6 instance. * Request: [ ipfw_obj_header ] */ static void nptv6_destroy(const char *name, uint8_t set) { ipfw_obj_header oh; memset(&oh, 0, sizeof(oh)); nptv6_fill_ntlv(&oh.ntlv, name, set); if (do_set3(IP_FW_NPTV6_DESTROY, &oh.opheader, sizeof(oh)) != 0) err(EX_OSERR, "failed to destroy nat instance %s", name); }
/* * Modifies existing table. * * Request: [ ipfw_obj_header ipfw_xtable_info ] * * Returns 0 on success. */ static int table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i) { char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)]; int error; memcpy(tbuf, oh, sizeof(*oh)); memcpy(tbuf + sizeof(*oh), i, sizeof(*i)); oh = (ipfw_obj_header *)tbuf; error = do_set3(IP_FW_TABLE_XMODIFY, &oh->opheader, sizeof(tbuf)); return (error); }
static int table_do_swap(ipfw_obj_header *oh, char *second) { char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_ntlv)]; int error; memset(tbuf, 0, sizeof(tbuf)); memcpy(tbuf, oh, sizeof(*oh)); oh = (ipfw_obj_header *)tbuf; table_fill_ntlv((ipfw_obj_ntlv *)(oh + 1), second, oh->ntlv.set, 1); error = do_set3(IP_FW_TABLE_XSWAP, &oh->opheader, sizeof(tbuf)); return (error); }
static void nptv6_create(const char *name, uint8_t set, int ac, char *av[]) { char buf[sizeof(ipfw_obj_lheader) + sizeof(ipfw_nptv6_cfg)]; struct in6_addr mask; ipfw_nptv6_cfg *cfg; ipfw_obj_lheader *olh; int tcmd, flags, plen; char *p = "\0"; plen = 0; memset(buf, 0, sizeof(buf)); olh = (ipfw_obj_lheader *)buf; cfg = (ipfw_nptv6_cfg *)(olh + 1); cfg->set = set; flags = 0; while (ac > 0) { tcmd = get_token(nptv6newcmds, *av, "option"); ac--; av++; switch (tcmd) { case TOK_INTPREFIX: NEED1("IPv6 prefix required"); nptv6_parse_prefix(*av, &cfg->internal, &plen); flags |= NPTV6_HAS_INTPREFIX; if (plen > 0) goto check_prefix; ac--; av++; break; case TOK_EXTPREFIX: if (flags & NPTV6_HAS_EXTPREFIX) errx(EX_USAGE, "Only one ext_prefix or ext_if allowed"); NEED1("IPv6 prefix required"); nptv6_parse_prefix(*av, &cfg->external, &plen); flags |= NPTV6_HAS_EXTPREFIX; if (plen > 0) goto check_prefix; ac--; av++; break; case TOK_EXTIF: if (flags & NPTV6_HAS_EXTPREFIX) errx(EX_USAGE, "Only one ext_prefix or ext_if allowed"); NEED1("Interface name required"); if (strlen(*av) >= sizeof(cfg->if_name)) errx(EX_USAGE, "Invalid interface name"); flags |= NPTV6_HAS_EXTPREFIX; cfg->flags |= NPTV6_DYNAMIC_PREFIX; strncpy(cfg->if_name, *av, sizeof(cfg->if_name)); ac--; av++; break; case TOK_PREFIXLEN: NEED1("IPv6 prefix length required"); plen = strtol(*av, &p, 10); check_prefix: if (*p != '\0' || plen < 8 || plen > 64) errx(EX_USAGE, "wrong prefix length: %s", *av); /* RFC 6296 Sec. 3.1 */ if (cfg->plen > 0 && cfg->plen != plen) { warnx("Prefix length mismatch (%d vs %d). " "It was extended up to %d", cfg->plen, plen, MAX(plen, cfg->plen)); plen = MAX(plen, cfg->plen); } cfg->plen = plen; flags |= NPTV6_HAS_PREFIXLEN; ac--; av++; break; } } /* Check validness */ if ((flags & NPTV6_HAS_INTPREFIX) != NPTV6_HAS_INTPREFIX) errx(EX_USAGE, "int_prefix required"); if ((flags & NPTV6_HAS_EXTPREFIX) != NPTV6_HAS_EXTPREFIX) errx(EX_USAGE, "ext_prefix or ext_if required"); if ((flags & NPTV6_HAS_PREFIXLEN) != NPTV6_HAS_PREFIXLEN) errx(EX_USAGE, "prefixlen required"); n2mask(&mask, cfg->plen); APPLY_MASK(&cfg->internal, &mask); if ((cfg->flags & NPTV6_DYNAMIC_PREFIX) == 0) APPLY_MASK(&cfg->external, &mask); olh->count = 1; olh->objsize = sizeof(*cfg); olh->size = sizeof(buf); strlcpy(cfg->name, name, sizeof(cfg->name)); if (do_set3(IP_FW_NPTV6_CREATE, &olh->opheader, sizeof(buf)) != 0) err(EX_OSERR, "nptv6 instance creation failed"); }
/* * Configures existing nat64clat instance * ipfw nat64clat <NAME> config <options> * Request: [ ipfw_obj_header ipfw_nat64clat_cfg ] */ static void nat64clat_config(const char *name, uint8_t set, int ac, char **av) { char buf[sizeof(ipfw_obj_header) + sizeof(ipfw_nat64clat_cfg)]; ipfw_nat64clat_cfg *cfg; ipfw_obj_header *oh; char *opt; char *p; size_t sz; int tcmd; struct in6_addr prefix; uint8_t plen; if (ac == 0) errx(EX_USAGE, "config options required"); memset(&buf, 0, sizeof(buf)); oh = (ipfw_obj_header *)buf; cfg = (ipfw_nat64clat_cfg *)(oh + 1); sz = sizeof(buf); nat64clat_fill_ntlv(&oh->ntlv, name, set); if (do_get3(IP_FW_NAT64CLAT_CONFIG, &oh->opheader, &sz) != 0) err(EX_OSERR, "failed to get config for instance %s", name); while (ac > 0) { tcmd = get_token(nat64newcmds, *av, "option"); opt = *av; ac--; av++; switch (tcmd) { case TOK_PLAT_PREFIX: case TOK_CLAT_PREFIX: if (tcmd == TOK_PLAT_PREFIX) { NEED1("IPv6 plat_prefix required"); } else { NEED1("IPv6 clat_prefix required"); } if ((p = strchr(*av, '/')) != NULL) *p++ = '\0'; if (inet_pton(AF_INET6, *av, &prefix) != 1) errx(EX_USAGE, "Bad prefix: %s", *av); plen = strtol(p, NULL, 10); if (ipfw_check_nat64prefix(&prefix, plen) != 0) errx(EX_USAGE, "Bad prefix length: %s", p); if (tcmd == TOK_PLAT_PREFIX) { cfg->plat_prefix = prefix; cfg->plat_plen = plen; } else { cfg->clat_prefix = prefix; cfg->clat_plen = plen; } ac--; av++; break; case TOK_LOG: cfg->flags |= NAT64_LOG; break; case TOK_LOGOFF: cfg->flags &= ~NAT64_LOG; break; case TOK_PRIVATE: cfg->flags |= NAT64_ALLOW_PRIVATE; break; case TOK_PRIVATEOFF: cfg->flags &= ~NAT64_ALLOW_PRIVATE; break; default: errx(EX_USAGE, "Can't change %s option", opt); } } if (do_set3(IP_FW_NAT64CLAT_CONFIG, &oh->opheader, sizeof(buf)) != 0) err(EX_OSERR, "nat64clat instance configuration failed"); }
static void nat64clat_create(const char *name, uint8_t set, int ac, char *av[]) { char buf[sizeof(ipfw_obj_lheader) + sizeof(ipfw_nat64clat_cfg)]; ipfw_nat64clat_cfg *cfg; ipfw_obj_lheader *olh; int tcmd, flags; char *p; struct in6_addr prefix; uint8_t plen; memset(buf, 0, sizeof(buf)); olh = (ipfw_obj_lheader *)buf; cfg = (ipfw_nat64clat_cfg *)(olh + 1); /* Some reasonable defaults */ inet_pton(AF_INET6, "64:ff9b::", &cfg->plat_prefix); cfg->plat_plen = 96; cfg->set = set; flags = NAT64CLAT_HAS_PLAT_PREFIX; while (ac > 0) { tcmd = get_token(nat64newcmds, *av, "option"); ac--; av++; switch (tcmd) { case TOK_PLAT_PREFIX: case TOK_CLAT_PREFIX: if (tcmd == TOK_PLAT_PREFIX) { NEED1("IPv6 plat_prefix required"); } else { NEED1("IPv6 clat_prefix required"); } if ((p = strchr(*av, '/')) != NULL) *p++ = '\0'; if (inet_pton(AF_INET6, *av, &prefix) != 1) errx(EX_USAGE, "Bad prefix: %s", *av); plen = strtol(p, NULL, 10); if (ipfw_check_nat64prefix(&prefix, plen) != 0) errx(EX_USAGE, "Bad prefix length: %s", p); if (tcmd == TOK_PLAT_PREFIX) { flags |= NAT64CLAT_HAS_PLAT_PREFIX; cfg->plat_prefix = prefix; cfg->plat_plen = plen; } else { flags |= NAT64CLAT_HAS_CLAT_PREFIX; cfg->clat_prefix = prefix; cfg->clat_plen = plen; } ac--; av++; break; case TOK_LOG: cfg->flags |= NAT64_LOG; break; case TOK_LOGOFF: cfg->flags &= ~NAT64_LOG; break; case TOK_PRIVATE: cfg->flags |= NAT64_ALLOW_PRIVATE; break; case TOK_PRIVATEOFF: cfg->flags &= ~NAT64_ALLOW_PRIVATE; break; } } /* Check validness */ if ((flags & NAT64CLAT_HAS_PLAT_PREFIX) != NAT64CLAT_HAS_PLAT_PREFIX) errx(EX_USAGE, "plat_prefix required"); if ((flags & NAT64CLAT_HAS_CLAT_PREFIX) != NAT64CLAT_HAS_CLAT_PREFIX) errx(EX_USAGE, "clat_prefix required"); olh->count = 1; olh->objsize = sizeof(*cfg); olh->size = sizeof(buf); strlcpy(cfg->name, name, sizeof(cfg->name)); if (do_set3(IP_FW_NAT64CLAT_CREATE, &olh->opheader, sizeof(buf)) != 0) err(EX_OSERR, "nat64clat instance creation failed"); }
/* * Configures existing nat64lsn instance * ipfw nat64lsn <NAME> config <options> * Request: [ ipfw_obj_header ipfw_nat64lsn_cfg ] */ static void nat64lsn_config(const char *name, uint8_t set, int ac, char **av) { char buf[sizeof(ipfw_obj_header) + sizeof(ipfw_nat64lsn_cfg)]; ipfw_nat64lsn_cfg *cfg; ipfw_obj_header *oh; size_t sz; char *opt; int tcmd; if (ac == 0) errx(EX_USAGE, "config options required"); memset(&buf, 0, sizeof(buf)); oh = (ipfw_obj_header *)buf; cfg = (ipfw_nat64lsn_cfg *)(oh + 1); sz = sizeof(buf); nat64lsn_fill_ntlv(&oh->ntlv, name, set); if (do_get3(IP_FW_NAT64LSN_CONFIG, &oh->opheader, &sz) != 0) err(EX_OSERR, "failed to get config for instance %s", name); while (ac > 0) { tcmd = get_token(nat64newcmds, *av, "option"); opt = *av; ac--; av++; switch (tcmd) { case TOK_MAX_PORTS: NEED1("Max per-user ports required"); cfg->max_ports = nat64lsn_parse_int(*av, opt); ac--; av++; break; case TOK_JMAXLEN: NEED1("job queue length required"); cfg->jmaxlen = nat64lsn_parse_int(*av, opt); ac--; av++; break; case TOK_HOST_DEL_AGE: NEED1("host delete delay required"); cfg->nh_delete_delay = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_PG_DEL_AGE: NEED1("portgroup delete delay required"); cfg->pg_delete_delay = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_TCP_SYN_AGE: NEED1("tcp syn age required"); cfg->st_syn_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_TCP_CLOSE_AGE: NEED1("tcp close age required"); cfg->st_close_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_TCP_EST_AGE: NEED1("tcp est age required"); cfg->st_estab_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_UDP_AGE: NEED1("udp age required"); cfg->st_udp_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_ICMP_AGE: NEED1("icmp age required"); cfg->st_icmp_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_LOG: cfg->flags |= NAT64_LOG; break; case TOK_LOGOFF: cfg->flags &= ~NAT64_LOG; break; default: errx(EX_USAGE, "Can't change %s option", opt); } } if (do_set3(IP_FW_NAT64LSN_CONFIG, &oh->opheader, sizeof(buf)) != 0) err(EX_OSERR, "nat64lsn instance configuration failed"); }
static void nat64lsn_create(const char *name, uint8_t set, int ac, char **av) { char buf[sizeof(ipfw_obj_lheader) + sizeof(ipfw_nat64lsn_cfg)]; ipfw_nat64lsn_cfg *cfg; ipfw_obj_lheader *olh; int tcmd, flags; char *opt; memset(&buf, 0, sizeof(buf)); olh = (ipfw_obj_lheader *)buf; cfg = (ipfw_nat64lsn_cfg *)(olh + 1); /* Some reasonable defaults */ inet_pton(AF_INET6, "64:ff9b::", &cfg->prefix6); cfg->plen6 = 96; cfg->set = set; cfg->max_ports = NAT64LSN_MAX_PORTS; cfg->jmaxlen = NAT64LSN_JMAXLEN; cfg->nh_delete_delay = NAT64LSN_HOST_AGE; cfg->pg_delete_delay = NAT64LSN_PG_AGE; cfg->st_syn_ttl = NAT64LSN_TCP_SYN_AGE; cfg->st_estab_ttl = NAT64LSN_TCP_EST_AGE; cfg->st_close_ttl = NAT64LSN_TCP_FIN_AGE; cfg->st_udp_ttl = NAT64LSN_UDP_AGE; cfg->st_icmp_ttl = NAT64LSN_ICMP_AGE; flags = NAT64LSN_HAS_PREFIX6; while (ac > 0) { tcmd = get_token(nat64newcmds, *av, "option"); opt = *av; ac--; av++; switch (tcmd) { case TOK_PREFIX4: NEED1("IPv4 prefix required"); nat64lsn_parse_prefix(*av, AF_INET, &cfg->prefix4, &cfg->plen4); flags |= NAT64LSN_HAS_PREFIX4; ac--; av++; break; #if 0 case TOK_PREFIX6: NEED1("IPv6 prefix required"); nat64lsn_parse_prefix(*av, AF_INET6, &cfg->prefix6, &cfg->plen6); ac--; av++; break; case TOK_AGG_LEN: NEED1("Aggregation prefix len required"); cfg->agg_prefix_len = nat64lsn_parse_int(*av, opt); ac--; av++; break; case TOK_AGG_COUNT: NEED1("Max per-prefix count required"); cfg->agg_prefix_max = nat64lsn_parse_int(*av, opt); ac--; av++; break; case TOK_PORT_RANGE: NEED1("port range x[:y] required"); if ((p = strchr(*av, ':')) == NULL) cfg->min_port = (uint16_t)nat64lsn_parse_int( *av, opt); else { *p++ = '\0'; cfg->min_port = (uint16_t)nat64lsn_parse_int( *av, opt); cfg->max_port = (uint16_t)nat64lsn_parse_int( p, opt); } ac--; av++; break; case TOK_JMAXLEN: NEED1("job queue length required"); cfg->jmaxlen = nat64lsn_parse_int(*av, opt); ac--; av++; break; #endif case TOK_MAX_PORTS: NEED1("Max per-user ports required"); cfg->max_ports = nat64lsn_parse_int(*av, opt); ac--; av++; break; case TOK_HOST_DEL_AGE: NEED1("host delete delay required"); cfg->nh_delete_delay = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_PG_DEL_AGE: NEED1("portgroup delete delay required"); cfg->pg_delete_delay = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_TCP_SYN_AGE: NEED1("tcp syn age required"); cfg->st_syn_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_TCP_CLOSE_AGE: NEED1("tcp close age required"); cfg->st_close_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_TCP_EST_AGE: NEED1("tcp est age required"); cfg->st_estab_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_UDP_AGE: NEED1("udp age required"); cfg->st_udp_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_ICMP_AGE: NEED1("icmp age required"); cfg->st_icmp_ttl = (uint16_t)nat64lsn_parse_int( *av, opt); ac--; av++; break; case TOK_LOG: cfg->flags |= NAT64_LOG; break; case TOK_LOGOFF: cfg->flags &= ~NAT64_LOG; break; } } /* Check validness */ if ((flags & NAT64LSN_HAS_PREFIX4) != NAT64LSN_HAS_PREFIX4) errx(EX_USAGE, "prefix4 required"); olh->count = 1; olh->objsize = sizeof(*cfg); olh->size = sizeof(buf); strlcpy(cfg->name, name, sizeof(cfg->name)); if (do_set3(IP_FW_NAT64LSN_CREATE, &olh->opheader, sizeof(buf)) != 0) err(EX_OSERR, "nat64lsn instance creation failed"); }