From 63317b935350df5ae80ee49526b054d70d733e60 Mon Sep 17 00:00:00 2001 From: Bill Yuan Date: Sat, 27 Jun 2015 21:38:17 +0800 Subject: [PATCH] ipfw3: filter from/to supports me/any/subnet usage: ipfw3 add allow udp to any ipfw3 add allow icmp from me ipfw3 add allow icmp from 192.168.1.0/24 --- lib/libipfw3/basic/ipfw3_basic.c | 280 +++++++++++++++-------------- sys/net/ipfw3_basic/ip_fw3_basic.c | 109 ++++++++++- 2 files changed, 251 insertions(+), 138 deletions(-) diff --git a/lib/libipfw3/basic/ipfw3_basic.c b/lib/libipfw3/basic/ipfw3_basic.c index c12ebc2067..a267e7f49a 100644 --- a/lib/libipfw3/basic/ipfw3_basic.c +++ b/lib/libipfw3/basic/ipfw3_basic.c @@ -235,140 +235,6 @@ contigmask(u_char *p, int len) return i; } -static void -fill_ip(ipfw_insn_ip *cmd, char *av) -{ - char *p = NULL, md = 0; - u_int32_t i; - - cmd->o.len &= ~F_LEN_MASK; /* zero len */ - - if (!strncmp(av, "any", strlen(av))) - return; - - if (!strncmp(av, "me", strlen(av))) { - cmd->o.len |= F_INSN_SIZE(ipfw_insn); - return; - } - - p = strchr(av, '/'); - if (!p) - p = strchr(av, ':'); - - if (p) { - md = *p; - *p++ = '\0'; - } - - if (lookup_host(av, &cmd->addr) != 0) - errx(EX_NOHOST, "hostname ``%s'' unknown", av); - switch (md) { - case ':': - if (!inet_aton(p, &cmd->mask)) - errx(EX_DATAERR, "bad netmask ``%s''", p); - break; - case '/': - i = atoi(p); - if (i == 0) - cmd->mask.s_addr = htonl(0); - else if (i > 32) - errx(EX_DATAERR, "bad width ``%s''", p); - else - cmd->mask.s_addr = htonl(~0 << (32 - i)); - break; - default: - cmd->mask.s_addr = htonl(~0); - break; - } - cmd->addr.s_addr &= cmd->mask.s_addr; - - if (p) - p = strchr(p, '{'); - if (p) { - u_int32_t *d; - int low, high; - int i = contigmask((u_char *)&(cmd->mask), 32); - - if (i < 24 || i > 31) { - fprintf(stderr, "invalid set with mask %d\n", i); - exit(0); - } - cmd->o.arg1 = 1<<(32-i); - cmd->addr.s_addr = ntohl(cmd->addr.s_addr); - d = (u_int32_t *)&cmd->mask; - cmd->o.opcode = O_BASIC_IP_DST_SET; /* default */ - cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + (cmd->o.arg1+31)/32; - for (i = 0; i < (cmd->o.arg1+31)/32 ; i++) - d[i] = 0; /* clear masks */ - - av = p+1; - low = cmd->addr.s_addr & 0xff; - high = low + cmd->o.arg1 - 1; - while (isdigit(*av)) { - char *s; - u_int16_t a = strtol(av, &s, 0); - - if (s == av) /* no parameter */ - break; - if (a < low || a > high) { - fprintf(stderr, - "addr %d out of range [%d-%d]\n", - a, low, high); - exit(0); - } - a -= low; - d[ a/32] |= 1<<(a & 31); - if (*s != ',') - break; - av = s+1; - } - return; - } - - if (cmd->mask.s_addr == 0) { - if (cmd->o.len & F_NOT) - errx(EX_DATAERR, "not any never matches"); - else /* useless, nuke it */ - return; - } else if (cmd->mask.s_addr == IP_MASK_ALL) { - cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32); - } else { /* addr/mask */ - cmd->o.len |= F_INSN_SIZE(ipfw_insn_ip); - printf("cmd->o.len=%d\n", cmd->o.len); - } -} - - -static ipfw_insn *add_srcip(ipfw_insn *cmd, char *av) -{ - fill_ip((ipfw_insn_ip *)cmd, av); - if ((int)cmd->opcode == O_BASIC_IP_DST_SET) /* set */ - cmd->opcode = O_BASIC_IP_SRC_SET; - else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) /* me */ - cmd->opcode = O_BASIC_IP_SRC_ME; - else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) /* one IP */ - cmd->opcode = O_BASIC_IP_SRC; - else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_ip)) /* addr/mask */ - cmd->opcode = O_BASIC_IP_SRC_MASK; - return cmd; -} - - -static ipfw_insn *add_dstip(ipfw_insn *cmd, char *av) -{ - fill_ip((ipfw_insn_ip *)cmd, av); - if ((int)cmd->opcode == O_BASIC_IP_DST_SET) - cmd->opcode = O_BASIC_IP_DST_SET; - else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) - cmd->opcode = O_BASIC_IP_DST_ME; - else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) - cmd->opcode = O_BASIC_IP_DST; - else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_ip)) - cmd->opcode = O_BASIC_IP_DST_MASK; - return cmd; -} - - static ipfw_insn *add_proto(ipfw_insn *cmd, char *av) { struct protoent *pe; @@ -508,21 +374,110 @@ parse_via(ipfw_insn **cmd, int *ac, char **av[]) NEXT_ARG1; } +/* + * Below formats are supported: + * from any return 0 len instruction + * from me O_BASIC_IP_SRC_ME + * from 1.2.3.4 O_BASIC_IP_SRC + * from 1.2.3.4/24 O_BASIC_IP_SRC_MASK + */ void parse_from(ipfw_insn **cmd, int *ac, char **av[]) { + ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd); + int i; + (*cmd)->module = MODULE_BASIC_ID; NEXT_ARG1; - add_srcip(*cmd, **av); + if (strcmp(**av, "any") == 0) { + (*cmd)->len &= ~F_LEN_MASK; + } else if (strcmp(**av, "me") == 0) { + (*cmd)->len |= F_INSN_SIZE(ipfw_insn); + (*cmd)->opcode = O_BASIC_IP_SRC_ME; + } else { + char *c = NULL, md = 0; + c = strchr(**av, '/'); + if (c) { + md = *c; + *c++ = '\0'; + } + if (lookup_host(**av, &p->addr) != 0) + errx(EX_NOHOST, "hostname ``%s'' unknown", **av); + switch (md) { + case '/': + i = atoi(c); + if (i == 0) + p->mask.s_addr = htonl(0); + else if (i > 32) + errx(EX_DATAERR, "bad width ``%s''", c); + else + p->mask.s_addr = htonl(~0 << (32 - i)); + break; + default: + p->mask.s_addr = htonl(~0); + break; + } + p->addr.s_addr &= p->mask.s_addr; + if (p->mask.s_addr == 0) { + /* high kneel */ + } else if (p->mask.s_addr == IP_MASK_ALL) { + (*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32); + (*cmd)->opcode = O_BASIC_IP_SRC; + } else { + (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip); + (*cmd)->opcode = O_BASIC_IP_SRC_MASK; + } + } NEXT_ARG1; } void parse_to(ipfw_insn **cmd, int *ac, char **av[]) { + ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd); + int i; + (*cmd)->module = MODULE_BASIC_ID; NEXT_ARG1; - add_dstip(*cmd, **av); + if (strcmp(**av, "any") == 0) { + (*cmd)->len &= ~F_LEN_MASK; + } else if (strcmp(**av, "me") == 0) { + (*cmd)->len |= F_INSN_SIZE(ipfw_insn); + (*cmd)->opcode = O_BASIC_IP_DST_ME; + } else { + char *c = NULL, md = 0; + c = strchr(**av, '/'); + if (c) { + md = *c; + *c++ = '\0'; + } + if (lookup_host(**av, &p->addr) != 0) + errx(EX_NOHOST, "hostname ``%s'' unknown", **av); + switch (md) { + case '/': + i = atoi(c); + if (i == 0) + p->mask.s_addr = htonl(0); + else if (i > 32) + errx(EX_DATAERR, "bad width ``%s''", c); + else + p->mask.s_addr = htonl(~0 << (32 - i)); + break; + default: + p->mask.s_addr = htonl(~0); + break; + } + p->addr.s_addr &= p->mask.s_addr; + if (p->mask.s_addr == 0) { + /* high kneel */ + } else if (p->mask.s_addr == IP_MASK_ALL) { + (*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32); + (*cmd)->opcode = O_BASIC_IP_DST; + } else { + (*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip); + (*cmd)->opcode = O_BASIC_IP_DST_MASK; + } + } NEXT_ARG1; } @@ -717,12 +672,48 @@ show_from(ipfw_insn *cmd) printf(" from %s", inet_ntoa(((ipfw_insn_ip *)cmd)->addr)); } +void +show_from_me(ipfw_insn *cmd) +{ + printf(" from me"); +} + +void +show_from_mask(ipfw_insn *cmd) +{ + int mask; + ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; + printf(" from %s", inet_ntoa(p->addr)); + + mask = contigmask((u_char *)&(p->mask.s_addr), 32); + if (mask < 32) + printf("/%d", mask); +} + void show_to(ipfw_insn *cmd) { printf(" to %s", inet_ntoa(((ipfw_insn_ip *)cmd)->addr)); } +void +show_to_me(ipfw_insn *cmd) +{ + printf(" to me"); +} + +void +show_to_mask(ipfw_insn *cmd) +{ + int mask; + ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; + printf(" to %s", inet_ntoa(p->addr)); + + mask = contigmask((u_char *)&(p->mask.s_addr), 32); + if (mask < 32) + printf("/%d", mask); +} + void show_proto(ipfw_insn *cmd) { @@ -826,11 +817,26 @@ load_module(register_func function, register_keyword keyword) IPFW_KEYWORD_TYPE_FILTER); function(MODULE_BASIC_ID, O_BASIC_IP_SRC, (parser_func)parse_from, (shower_func)show_from); - + keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME, "[from me]", + IPFW_KEYWORD_TYPE_FILTER); + function(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME, + (parser_func)parse_from, (shower_func)show_from_me); + keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK, "[from mask]", + IPFW_KEYWORD_TYPE_FILTER); + function(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK, + (parser_func)parse_from, (shower_func)show_from_mask); keyword(MODULE_BASIC_ID, O_BASIC_IP_DST, "to", IPFW_KEYWORD_TYPE_FILTER); function(MODULE_BASIC_ID, O_BASIC_IP_DST, (parser_func)parse_to, (shower_func)show_to); + keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_ME, "[to me]", + IPFW_KEYWORD_TYPE_FILTER); + function(MODULE_BASIC_ID, O_BASIC_IP_DST_ME, + (parser_func)parse_to, (shower_func)show_to_me); + keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK, "[to mask]", + IPFW_KEYWORD_TYPE_FILTER); + function(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK, + (parser_func)parse_to, (shower_func)show_to_mask); keyword(MODULE_BASIC_ID, O_BASIC_PROTO, "proto", IPFW_KEYWORD_TYPE_FILTER); diff --git a/sys/net/ipfw3_basic/ip_fw3_basic.c b/sys/net/ipfw3_basic/ip_fw3_basic.c index 05a2b613a7..1718231154 100644 --- a/sys/net/ipfw3_basic/ip_fw3_basic.c +++ b/sys/net/ipfw3_basic/ip_fw3_basic.c @@ -194,8 +194,16 @@ void check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); void check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); +void check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); +void check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); void check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); +void check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); +void check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); void check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len); void check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, @@ -540,6 +548,52 @@ check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, *cmd_ctl = IP_FW_CTL_NO; } +void +check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) +{ + struct in_addr src_ip; + u_int hlen = 0; + struct mbuf *m = (*args)->m; + struct ip *ip = mtod(m, struct ip *); + src_ip = ip->ip_src; + if ((*args)->eh == NULL || + (m->m_pkthdr.len >= sizeof(struct ip) && + ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { + hlen = ip->ip_hl << 2; + } + *cmd_ctl = IP_FW_CTL_NO; + if (hlen > 0) { + struct ifnet *tif; + tif = INADDR_TO_IFP(&src_ip); + *cmd_val = (tif != NULL); + } else { + *cmd_val = IP_FW_NOT_MATCH; + } +} + +void +check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) +{ + struct in_addr src_ip; + u_int hlen = 0; + struct mbuf *m = (*args)->m; + struct ip *ip = mtod(m, struct ip *); + src_ip = ip->ip_src; + if ((*args)->eh == NULL || + (m->m_pkthdr.len >= sizeof(struct ip) && + ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { + hlen = ip->ip_hl << 2; + } + + *cmd_ctl = IP_FW_CTL_NO; + *cmd_val = (hlen > 0 && + ((ipfw_insn_ip *)cmd)->addr.s_addr == + (src_ip.s_addr & + ((ipfw_insn_ip *)cmd)->mask.s_addr)); +} + void check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) @@ -559,6 +613,52 @@ check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, *cmd_ctl = IP_FW_CTL_NO; } +void +check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) +{ + struct in_addr dst_ip; + u_int hlen = 0; + struct mbuf *m = (*args)->m; + struct ip *ip = mtod(m, struct ip *); + dst_ip = ip->ip_src; + if ((*args)->eh == NULL || + (m->m_pkthdr.len >= sizeof(struct ip) && + ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { + hlen = ip->ip_hl << 2; + } + *cmd_ctl = IP_FW_CTL_NO; + if (hlen > 0) { + struct ifnet *tif; + tif = INADDR_TO_IFP(&dst_ip); + *cmd_val = (tif != NULL); + } else { + *cmd_val = IP_FW_NOT_MATCH; + } +} + +void +check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, + struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) +{ + struct in_addr dst_ip; + u_int hlen = 0; + struct mbuf *m = (*args)->m; + struct ip *ip = mtod(m, struct ip *); + dst_ip = ip->ip_src; + if ((*args)->eh == NULL || + (m->m_pkthdr.len >= sizeof(struct ip) && + ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) { + hlen = ip->ip_hl << 2; + } + + *cmd_ctl = IP_FW_CTL_NO; + *cmd_val = (hlen > 0 && + ((ipfw_insn_ip *)cmd)->addr.s_addr == + (dst_ip.s_addr & + ((ipfw_insn_ip *)cmd)->mask.s_addr)); +} + void check_keep_state(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) @@ -841,9 +941,16 @@ ipfw_basic_init(void) O_BASIC_PROB, (filter_func)check_prob); register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_IP_SRC, (filter_func)check_from); + register_ipfw_filter_funcs(MODULE_BASIC_ID, + O_BASIC_IP_SRC_ME, (filter_func)check_from_me); + register_ipfw_filter_funcs(MODULE_BASIC_ID, + O_BASIC_IP_SRC_MASK, (filter_func)check_from_mask); register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_IP_DST, (filter_func)check_to); - + register_ipfw_filter_funcs(MODULE_BASIC_ID, + O_BASIC_IP_DST_ME, (filter_func)check_to_me); + register_ipfw_filter_funcs(MODULE_BASIC_ID, + O_BASIC_IP_DST_MASK, (filter_func)check_to_mask); register_ipfw_filter_funcs(MODULE_BASIC_ID, O_BASIC_TAG, (filter_func)check_tag); register_ipfw_filter_funcs(MODULE_BASIC_ID, -- 2.41.0