Index: sbin/ipfw/ipfw2.c =================================================================== RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v retrieving revision 1.118 diff -u -r1.118 ipfw2.c --- sbin/ipfw/ipfw2.c 27 Feb 2008 13:52:33 -0000 1.118 +++ sbin/ipfw/ipfw2.c 24 Mar 2008 11:44:33 -0000 @@ -177,6 +177,18 @@ { NULL, 0 } }; +static struct _s_x f_iptospre[] = { + { "netcontrol", IPTOS_PREC_NETCONTROL}, + { "intercontrol", IPTOS_PREC_INTERNETCONTROL}, + { "criticecp", IPTOS_PREC_CRITIC_ECP}, + { "flashover", IPTOS_PREC_FLASHOVERRIDE}, + { "flash", IPTOS_PREC_FLASH}, + { "immediate", IPTOS_PREC_IMMEDIATE}, + { "priority", IPTOS_PREC_PRIORITY}, + { "routine", IPTOS_PREC_ROUTINE}, + { NULL, 0} +}; + static struct _s_x f_iptos[] = { { "lowdelay", IPTOS_LOWDELAY}, { "throughput", IPTOS_THROUGHPUT}, @@ -188,6 +200,31 @@ { NULL, 0 } }; +static struct _s_x f_ipdscp[] = { + { "AF11", 40 }, + { "AF12", 48 }, + { "AF13", 56 }, + { "AF21", 72 }, + { "AF22", 80 }, + { "AF23", 88 }, + { "AF31", 104 }, + { "AF32", 112 }, + { "AF33", 120 }, + { "AF41", 136 }, + { "AF42", 144 }, + { "AF43", 152 }, + { "EF", 184 }, + { "CS0", 0 }, + { "CS1", 32 }, + { "CS2", 64 }, + { "CS3", 96 }, + { "CS4", 128 }, + { "CS5", 160 }, + { "CS6", 192 }, + { "CS7", 224 }, + { NULL, 0 } +}; + static struct _s_x limit_masks[] = { {"all", DYN_SRC_ADDR|DYN_SRC_PORT|DYN_DST_ADDR|DYN_DST_PORT}, {"src-addr", DYN_SRC_ADDR}, @@ -255,6 +292,7 @@ TOK_RESET, TOK_UNREACH, TOK_CHECKSTATE, + TOK_SETDF, TOK_NAT, TOK_ALTQ, @@ -282,7 +320,9 @@ TOK_IPLEN, TOK_IPID, TOK_IPPRECEDENCE, + TOK_MODIP, TOK_IPTOS, + TOK_IPDSCP, TOK_IPTTL, TOK_IPVER, TOK_ESTAB, @@ -317,6 +357,9 @@ TOK_GRED, TOK_DROPTAIL, TOK_PROTO, + TOK_SETMODIP, + TOK_SETDSCP, + TOK_SETIPTOS, TOK_WEIGHT, TOK_IP, TOK_IF, @@ -411,6 +454,8 @@ { "unreach6", TOK_UNREACH6 }, { "unreach", TOK_UNREACH }, { "check-state", TOK_CHECKSTATE }, + { "modip", TOK_SETMODIP }, + { "iptos", TOK_SETIPTOS }, { "//", TOK_COMMENT }, { "nat", TOK_NAT }, { NULL, 0 } /* terminator */ @@ -449,6 +494,8 @@ { "ipid", TOK_IPID }, { "ipprecedence", TOK_IPPRECEDENCE }, { "iptos", TOK_IPTOS }, + { "modip", TOK_MODIP }, + { "dscp", TOK_IPDSCP }, { "ipttl", TOK_IPTTL }, { "ipversion", TOK_IPVER }, { "ipver", TOK_IPVER }, @@ -1599,6 +1646,26 @@ } break; + case O_SETIPTOSPRE: + printf("modip ippre:%s", match_value(f_iptospre, cmd->arg1)); + break; + + case O_SETMODIP: + printf("modip right."); + break; + + case O_SET_IPTOS: + printf("modip tos:%s", match_value(f_iptos, cmd->arg1)); + break; + + case O_SETDSCP: + printf("modip dscp:%s", match_value(f_ipdscp, cmd->arg1)); + break; + + case O_SET_IPDF: + PRINT_UINT_ARG("modip df:", cmd->arg1); + break; + case O_LOG: /* O_LOG is printed last */ logptr = (ipfw_insn_log *)cmd; break; @@ -1910,6 +1977,14 @@ printf(" established"); break; + case O_IPTOSPRE: + printf(" iptospre %s", match_value(f_iptospre, cmd->arg1)); + break; + + case O_IPDSCP: + //printf(" dscp %s", match_value(f_ipdscp, cmd->arg1)); + break; + case O_TCPDATALEN: if (F_LEN(cmd) == 1) printf(" tcpdatalen %u", cmd->arg1 ); @@ -4861,6 +4936,49 @@ action->opcode = O_COUNT; break; + case TOK_SETIPTOS: + NEED1("need iptos arg\n"); + fill_flags(action, O_SET_IPTOS, f_iptos, *av); + ac--; av++; + break; + + case TOK_SETMODIP: { + char *s; + NEED1("need modip [DF|TOS|IPPRE|DSCP]:code arg\n"); + s = strchr(*av, ':'); + if (s != NULL) { + *(s++) = '\0'; + if (_substrcmp(*av, "DF") == 0 || + _substrcmp(*av, "df") == 0) { + int df; + df = strtoul(s, NULL, 0); + if (df < 0 || df > 1) + errx(EX_DATAERR, "illegal argument for %s", + *(av - 1)); + fill_cmd(action, O_SET_IPDF, 0, df); + ac--; av++; + } else if (_substrcmp(*av, "TOS") == 0 || + _substrcmp(*av, "tos") == 0) { + fill_flags(action, O_IPTOS, f_iptos, s); + ac--; av++; + } else if (_substrcmp(*av, "IPPRE") == 0 || + _substrcmp(*av, "ippre") == 0) { + fill_flags(action, O_SETIPTOSPRE, f_iptospre, s); + ac--; av++; + } else if (_substrcmp(*av, "dp") == 0 || + _substrcmp(*av, "dp") == 0) { + printf("S: %s\n", s); + printf("AV: %s\n", *av); + fill_flags(action, O_SETDSCP, f_ipdscp, s); + printf("S: %s\n", s); + ac--; av++; + } + } else { + errx(EX_DATAERR, "Where is the code point"); + } +} + break; + case TOK_NAT: action->opcode = O_NAT; action->len = F_INSN_SIZE(ipfw_insn_nat); Index: sys/netinet/ip_fw.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v retrieving revision 1.112 diff -u -r1.112 ip_fw.h --- sys/netinet/ip_fw.h 29 Feb 2008 22:27:19 -0000 1.112 +++ sys/netinet/ip_fw.h 24 Mar 2008 11:44:34 -0000 @@ -157,9 +157,16 @@ O_IP4, O_UNREACH6, /* arg1=icmpv6 code arg (deny) */ - + O_IPTOSPRE, + O_SET_IPTOS, + O_SETIPTOSPRE, + O_SET_IPDF, + O_SETMODIP, + O_SETDSCP, + O_IPDSCP, O_TAG, /* arg1=tag number */ O_TAGGED, /* arg1=tag number */ + O_SET_DSCP, O_LAST_OPCODE /* not an opcode! */ }; @@ -177,6 +184,8 @@ #define EXT_RTHDR0 0x40 #define EXT_RTHDR2 0x80 +#define DSCP_AF11 40 + /* * Template for instructions. * @@ -342,9 +351,9 @@ u_short pport_cnt; /* number of public ports */ u_short rport_cnt; /* number of remote ports */ int proto; /* protocol: tcp/udp */ - struct alias_link **alink; + struct alias_link **alink; /* num of entry in spool chain */ - u_int16_t spool_cnt; + u_int16_t spool_cnt; /* chain of spool instances */ LIST_HEAD(spool_chain, cfg_spool) spool_chain; }; @@ -363,9 +372,9 @@ int mode; /* aliasing mode */ struct libalias *lib; /* libalias instance */ /* number of entry in spool chain */ - int redir_cnt; + int redir_cnt; /* chain of redir instances */ - LIST_HEAD(redir_chain, cfg_redir) redir_chain; + LIST_HEAD(redir_chain, cfg_redir) redir_chain; }; #endif @@ -376,7 +385,7 @@ /* Nat command. */ typedef struct _ipfw_insn_nat { ipfw_insn o; - struct cfg_nat *nat; + struct cfg_nat *nat; } ipfw_insn_nat; /* Apply ipv6 mask on ipv6 addr */ @@ -399,7 +408,7 @@ uint32_t d[7]; /* XXX This number si related to the netinet/icmp6.h * define ICMP6_MAXTYPE * as follows: n = ICMP6_MAXTYPE/32 + 1 - * Actually is 203 + * Actually is 203 */ } ipfw_insn_icmp6; @@ -626,6 +635,21 @@ extern ip_fw_chk_t *ip_fw_chk_ptr; #define IPFW_LOADED (ip_fw_chk_ptr != NULL) +#define ADJUST_CHECKSUM(acc, cksum) \ + do { \ + acc += cksum; \ + if (acc < 0) { \ + acc = -acc; \ + acc = (acc >> 16) + (acc & 0xffff); \ + acc += acc >> 16; \ + cksum = (u_short) ~acc; \ + } else { \ + acc = (acc >> 16) + (acc & 0xffff); \ + acc += acc >> 16; \ + cksum = (u_short) acc; \ + } \ + } while (0) + #ifdef IPFW_INTERNAL #define IPFW_TABLES_MAX 128 Index: sys/netinet/ip_fw2.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v retrieving revision 1.183 diff -u -r1.183 ip_fw2.c --- sys/netinet/ip_fw2.c 17 Mar 2008 23:02:56 -0000 1.183 +++ sys/netinet/ip_fw2.c 24 Mar 2008 11:44:35 -0000 @@ -161,6 +161,19 @@ extern int ipfw_chg_hook(SYSCTL_HANDLER_ARGS); +static __inline int +twowords(void *p) { + uint8_t *c = p; +#if BYTE_ORDER == LITTLE_ENDIAN + uint16_t s1 = ((uint16_t)c[1] << 8) + (uint16_t)c[0]; + uint16_t s2 = ((uint16_t)c[3] << 8) + (uint16_t)c[2]; +#else + uint16_t s1 = ((uint16_t)c[0] << 8) + (uint16_t)c[1]; + uint16_t s2 = ((uint16_t)c[2] << 8) + (uint16_t)c[3]; +#endif + return (s1 + s2); +} + #ifdef SYSCTL_NODE SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall"); SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, enable, @@ -2502,6 +2515,7 @@ for (; f; f = f->next) { ipfw_insn *cmd; uint32_t tablearg = 0; + int accumulate; int l, cmdlen, skip_or; /* skip rest of OR block */ again: @@ -2808,6 +2822,16 @@ flags_match(cmd, ip->ip_tos)); break; + case O_IPTOSPRE: + match = (is_ipv4 && + flags_match(cmd, ip->ip_tos)); + break; + + case O_IPDSCP: + match = (is_ipv4 && + (cmd->arg1 == (mtod(m, struct ip *)->ip_tos & 0xfc)) ); + break; + case O_TCPDATALEN: if (proto == IPPROTO_TCP && offset == 0) { struct tcphdr *tcp; @@ -3124,6 +3148,36 @@ match = 1; break; + case O_SETIPTOSPRE: + accumulate = twowords(&ip->ip_tos); + ip->ip_tos = cmd->arg1; + accumulate -= twowords(&ip->ip_tos); + ADJUST_CHECKSUM(accumulate, ip->ip_sum); + f->pcnt++; + f->bcnt += pktlen; + f->timestamp = time_second; + goto next_rule; + + case O_SET_IPTOS: + accumulate = twowords(&ip->ip_tos); + ip->ip_tos = cmd->arg1; + accumulate -= twowords(&ip->ip_tos); + ADJUST_CHECKSUM(accumulate, ip->ip_sum); + f->pcnt++; + f->bcnt += pktlen; + f->timestamp = time_second; + goto next_rule; + + case O_SETDSCP: + accumulate = twowords(&ip->ip_tos); + ip->ip_tos = ip->ip_tos | cmd->arg1; + accumulate -= twowords(&ip->ip_tos); + ADJUST_CHECKSUM(accumulate, ip->ip_sum); + f->pcnt++; + f->bcnt += pktlen; + f->timestamp = time_second; + goto next_rule; + case O_PROBE_STATE: case O_CHECK_STATE: /* @@ -3204,6 +3258,24 @@ goto done; } + case O_SET_IPDF: + { + switch (cmd->arg1) { + case 0: + ip->ip_off &= ~IP_DF; + break; + case 1: + ip->ip_off |= IP_DF; + break; + default: + goto next_rule; + } + f->pcnt++; + f->bcnt += pktlen; + f->timestamp = time_second; + goto next_rule; + } + case O_COUNT: case O_SKIPTO: f->pcnt++; /* update stats */ @@ -3771,6 +3843,8 @@ case O_DIVERTED: case O_IPOPT: case O_IPTOS: + case O_IPTOSPRE: + case O_IPDSCP: case O_IPPRECEDENCE: case O_IPVER: case O_TCPWIN: @@ -3793,6 +3867,14 @@ goto bad_size; break; + case O_SETIPTOSPRE: + case O_SET_IPTOS: + case O_SETDSCP: + case O_SET_IPDF: + case O_SETMODIP: + have_action = 1; + break; + case O_UID: case O_GID: case O_JAIL: