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$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd June 4, 2022
|
.Dd August 17, 2022
|
||||||
.Dt IPFW 8
|
.Dt IPFW 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1080,7 +1080,7 @@ Send a copy of packets matching this rule to the
|
|||||||
socket bound to port
|
socket bound to port
|
||||||
.Ar port .
|
.Ar port .
|
||||||
The search continues with the next rule.
|
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
|
Discard packets that match this rule, and try to send an ICMP
|
||||||
unreachable notice with code
|
unreachable notice with code
|
||||||
.Ar 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
|
.Cm toshost , filter-prohib , host-precedence
|
||||||
or
|
or
|
||||||
.Cm precedence-cutoff .
|
.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.
|
The search terminates.
|
||||||
.It Cm unreach6 Ar code
|
.It Cm unreach6 Ar code
|
||||||
Discard packets that match this rule, and try to send an ICMPv6
|
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");
|
bprintf(bp, "abort");
|
||||||
else if (cmd->arg1 == ICMP_UNREACH_HOST)
|
else if (cmd->arg1 == ICMP_UNREACH_HOST)
|
||||||
bprintf(bp, "reject");
|
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
|
else
|
||||||
print_reject_code(bp, cmd->arg1);
|
print_reject_code(bp, cmd->arg1);
|
||||||
break;
|
break;
|
||||||
@ -3992,6 +3996,17 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
|||||||
NEED1("missing reject code");
|
NEED1("missing reject code");
|
||||||
fill_reject_code(&action->arg1, *av);
|
fill_reject_code(&action->arg1, *av);
|
||||||
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;
|
break;
|
||||||
|
|
||||||
case TOK_UNREACH6:
|
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.
|
* sends a reject message, consuming the mbuf passed as an argument.
|
||||||
*/
|
*/
|
||||||
static void
|
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
|
#if 0
|
||||||
/* XXX When ip is not guaranteed to be at mtod() we will
|
/* 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
|
#endif
|
||||||
if (code != ICMP_REJECT_RST && code != ICMP_REJECT_ABORT) {
|
if (code != ICMP_REJECT_RST && code != ICMP_REJECT_ABORT) {
|
||||||
/* Send an ICMP unreach */
|
/* 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) {
|
} else if (code == ICMP_REJECT_RST && args->f_id.proto == IPPROTO_TCP) {
|
||||||
struct tcphdr *const tcp =
|
struct tcphdr *const tcp =
|
||||||
L3HDR(struct tcphdr, mtod(args->m, struct ip *));
|
L3HDR(struct tcphdr, mtod(args->m, struct ip *));
|
||||||
@ -3042,7 +3051,7 @@ do { \
|
|||||||
is_icmp_query(ICMP(ulp))) &&
|
is_icmp_query(ICMP(ulp))) &&
|
||||||
!(m->m_flags & (M_BCAST|M_MCAST)) &&
|
!(m->m_flags & (M_BCAST|M_MCAST)) &&
|
||||||
!IN_MULTICAST(ntohl(dst_ip.s_addr))) {
|
!IN_MULTICAST(ntohl(dst_ip.s_addr))) {
|
||||||
send_reject(args, cmd->arg1, iplen, ip);
|
send_reject(args, cmd, iplen, ip);
|
||||||
m = args->m;
|
m = args->m;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
@ -2000,12 +2000,17 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
|
|||||||
goto check_action;
|
goto check_action;
|
||||||
case O_CHECK_STATE:
|
case O_CHECK_STATE:
|
||||||
ci->object_opcodes++;
|
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 */
|
/* FALLTHROUGH */
|
||||||
case O_FORWARD_MAC: /* XXX not implemented yet */
|
case O_FORWARD_MAC: /* XXX not implemented yet */
|
||||||
case O_COUNT:
|
case O_COUNT:
|
||||||
case O_ACCEPT:
|
case O_ACCEPT:
|
||||||
case O_DENY:
|
case O_DENY:
|
||||||
case O_REJECT:
|
|
||||||
case O_SETDSCP:
|
case O_SETDSCP:
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case O_UNREACH6:
|
case O_UNREACH6:
|
||||||
|
Loading…
Reference in New Issue
Block a user