All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexey Kashavkin <akashavkin@gmail.com>
To: netfilter@vger.kernel.org
Cc: pablo@netfilter.org, ssuryaextr@gmail.com
Subject: Clarification of the procedure for filtering IP option fields
Date: Tue, 31 Dec 2024 15:54:50 +0500	[thread overview]
Message-ID: <8647C646-1BE2-4956-9598-27CCADD44315@gmail.com> (raw)

Hi,

I am investigating ip options filtering using the exthdr expression and exploring the code in the kernel and the following is not quite clear to me:  

> On 19 Aug 2019, at 17:58, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> 
> * Match on IPv4 options, e.g.
> 
>        add rule x y ip option rr exists drop
> 
>  You can also match on type, ptr, length and addr fields of routing
>  options, e.g.
> 
>        add rule x y ip option rr type 1 drop
> 
>  lsrr, rr, ssrr and ra IPv4 options are supported.

What is meant by type in this example? As you can read in RFC791[1], the Record Route (rr) designation in this example is the type of the ip option. The first octet defines the option type, which is a constant and cannot have any other value. For clarity: 

> IPOPT_LSRR       (3 | IPOPT_CONTROL | IPOPT_COPY)  = type 131
> IPOPT_RR (7 | IPOPT_CONTROL)  = type 7
> IPOPT_SSRR       (9 | IPOPT_CONTROL | IPOPT_COPY)  = type 137
> IPOPT_RA         (20 | IPOPT_CONTROL | IPOPT_COPY)  = type 148


Based on the ipv4_find_option() function I can see that it only returns the value whether the option is present in the IP header or not and if it is present then its offset in the buffer is taken, but how is the addr field checked? For example, I want to filter traffic with LSRR option and certain addresses in the route data of this option, but I don't see in the kernel where it will be checked.

> static int ipv4_find_option(struct net *net, struct sk_buff *skb,
> 			    unsigned int *offset, int target)
> {
> 	unsigned char optbuf[sizeof(struct ip_options) + 40];
> 	struct ip_options *opt = (struct ip_options *)optbuf;
> 	struct iphdr *iph, _iph;
> 	unsigned int start;
> 	bool found = false;
> 	__be32 info;
> 	int optlen;
> 	iph = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
> 	if (!iph)
> 		return -EBADMSG;
> 	start = sizeof(struct iphdr);
> 	optlen = iph->ihl * 4 - (int)sizeof(struct iphdr);
> 	if (optlen <= 0)
> 		return -ENOENT;
> 	memset(opt, 0, sizeof(struct ip_options));
> 	/* Copy the options since __ip_options_compile() modifies
> 	 * the options.
> 	 */
> 	if (skb_copy_bits(skb, start, opt->__data, optlen))
> 		return -EBADMSG;
> 	opt->optlen = optlen;
> 	if (__ip_options_compile(net, opt, NULL, &info))
> 		return -EBADMSG;
> 	switch (target) {
> 	case IPOPT_SSRR:
> 	case IPOPT_LSRR:
> 		if (!opt->srr)
> 			break;
> 		found = target == IPOPT_SSRR ? opt->is_strictroute :
> 					       !opt->is_strictroute;
> 		if (found)
> 			*offset = opt->srr + start;
> 		break;
> 	case IPOPT_RR:
> 		if (!opt->rr)
> 			break;
> 		*offset = opt->rr + start;
> 		found = true;
> 		break;
> 	case IPOPT_RA:
> 		if (!opt->router_alert)
> 			break;
> 		*offset = opt->router_alert + start;
> 		found = true;
> 		break;
> 	default:
> 		return -EOPNOTSUPP;
> 	}
> 	return found ? target : -ENOENT;
> }

I also don't see a check in the nft_exthdr_ipv4_eval() function.

If you can make this point more transparent with a code example, I would really appreciate it. I need this for further writing my module for nftables.

1. https://www.rfc-editor.org/rfc/rfc791.html

Regards, 
Alexey.

             reply	other threads:[~2024-12-31 10:55 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-31 10:54 Alexey Kashavkin [this message]
2025-01-30 13:52 ` Clarification of the procedure for filtering IP option fields Alexey Kashavkin
2025-01-30 17:49   ` Pablo Neira Ayuso
2025-01-30 17:52     ` Pablo Neira Ayuso
2025-01-30 18:06       ` Pablo Neira Ayuso
2025-01-30 23:23         ` Alexey Kashavkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8647C646-1BE2-4956-9598-27CCADD44315@gmail.com \
    --to=akashavkin@gmail.com \
    --cc=netfilter@vger.kernel.org \
    --cc=pablo@netfilter.org \
    --cc=ssuryaextr@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.