ipfw: make it possible to specify MTU for "unreach needfrag" action
Reviewed by: ae, pauamma Differential revision: https://reviews.freebsd.org/D36140
This commit is contained in:
parent
e7abb89701
commit
05b9737f10
@ -1,7 +1,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 4, 2022
|
||||
.Dd August 17, 2022
|
||||
.Dt IPFW 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -1080,7 +1080,7 @@ Send a copy of packets matching this rule to the
|
||||
socket bound to port
|
||||
.Ar port .
|
||||
The search continues with the next rule.
|
||||
.It Cm unreach Ar code
|
||||
.It Cm unreach Ar code Op mtu
|
||||
Discard packets that match this rule, and try to send an ICMP
|
||||
unreachable notice with code
|
||||
.Ar code ,
|
||||
@ -1093,6 +1093,12 @@ is a number from 0 to 255, or one of these aliases:
|
||||
.Cm toshost , filter-prohib , host-precedence
|
||||
or
|
||||
.Cm precedence-cutoff .
|
||||
The
|
||||
.Cm needfrag
|
||||
code may have an optional
|
||||
.Ar mtu
|
||||
parameter.
|
||||
If specified, the MTU value will be put into generated ICMP packet.
|
||||
The search terminates.
|
||||
.It Cm unreach6 Ar code
|
||||
Discard packets that match this rule, and try to send an ICMPv6
|
||||
|
@ -1890,6 +1890,10 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
|
||||
bprintf(bp, "abort");
|
||||
else if (cmd->arg1 == ICMP_UNREACH_HOST)
|
||||
bprintf(bp, "reject");
|
||||
else if (cmd->arg1 == ICMP_UNREACH_NEEDFRAG &&
|
||||
cmd->len == F_INSN_SIZE(ipfw_insn_u16))
|
||||
bprintf(bp, "needfrag %u",
|
||||
((const ipfw_insn_u16 *)cmd)->ports[0]);
|
||||
else
|
||||
print_reject_code(bp, cmd->arg1);
|
||||
break;
|
||||
@ -3992,6 +3996,17 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
||||
NEED1("missing reject code");
|
||||
fill_reject_code(&action->arg1, *av);
|
||||
av++;
|
||||
if (action->arg1 == ICMP_UNREACH_NEEDFRAG && isdigit(**av)) {
|
||||
uint16_t mtu;
|
||||
|
||||
mtu = strtoul(*av, NULL, 10);
|
||||
if (mtu < 68 || mtu >= IP_MAXPACKET)
|
||||
errx(EX_DATAERR, "illegal argument for %s",
|
||||
*(av - 1));
|
||||
action->len = F_INSN_SIZE(ipfw_insn_u16);
|
||||
((ipfw_insn_u16 *)action)->ports[0] = mtu;
|
||||
av++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_UNREACH6:
|
||||
|
@ -993,8 +993,17 @@ send_reject6(struct ip_fw_args *args, int code, u_int hlen, struct ip6_hdr *ip6)
|
||||
* sends a reject message, consuming the mbuf passed as an argument.
|
||||
*/
|
||||
static void
|
||||
send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip)
|
||||
send_reject(struct ip_fw_args *args, const ipfw_insn *cmd, int iplen,
|
||||
struct ip *ip)
|
||||
{
|
||||
int code, mtu;
|
||||
|
||||
code = cmd->arg1;
|
||||
if (code == ICMP_UNREACH_NEEDFRAG &&
|
||||
cmd->len == F_INSN_SIZE(ipfw_insn_u16))
|
||||
mtu = ((const ipfw_insn_u16 *)cmd)->ports[0];
|
||||
else
|
||||
mtu = 0;
|
||||
|
||||
#if 0
|
||||
/* XXX When ip is not guaranteed to be at mtod() we will
|
||||
@ -1008,7 +1017,7 @@ send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip)
|
||||
#endif
|
||||
if (code != ICMP_REJECT_RST && code != ICMP_REJECT_ABORT) {
|
||||
/* Send an ICMP unreach */
|
||||
icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
|
||||
icmp_error(args->m, ICMP_UNREACH, code, 0L, mtu);
|
||||
} else if (code == ICMP_REJECT_RST && args->f_id.proto == IPPROTO_TCP) {
|
||||
struct tcphdr *const tcp =
|
||||
L3HDR(struct tcphdr, mtod(args->m, struct ip *));
|
||||
@ -3042,7 +3051,7 @@ do { \
|
||||
is_icmp_query(ICMP(ulp))) &&
|
||||
!(m->m_flags & (M_BCAST|M_MCAST)) &&
|
||||
!IN_MULTICAST(ntohl(dst_ip.s_addr))) {
|
||||
send_reject(args, cmd->arg1, iplen, ip);
|
||||
send_reject(args, cmd, iplen, ip);
|
||||
m = args->m;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
@ -2000,12 +2000,17 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
|
||||
goto check_action;
|
||||
case O_CHECK_STATE:
|
||||
ci->object_opcodes++;
|
||||
goto check_size;
|
||||
case O_REJECT:
|
||||
/* "unreach needfrag" has variable len. */
|
||||
if ((cmdlen == F_INSN_SIZE(ipfw_insn) ||
|
||||
cmdlen == F_INSN_SIZE(ipfw_insn_u16)))
|
||||
goto check_action;
|
||||
/* FALLTHROUGH */
|
||||
case O_FORWARD_MAC: /* XXX not implemented yet */
|
||||
case O_COUNT:
|
||||
case O_ACCEPT:
|
||||
case O_DENY:
|
||||
case O_REJECT:
|
||||
case O_SETDSCP:
|
||||
#ifdef INET6
|
||||
case O_UNREACH6:
|
||||
|
Loading…
Reference in New Issue
Block a user