Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vlan: add vlan.id keyword - v3 #12273

Closed
wants to merge 1 commit into from

Conversation

AkakiAlice
Copy link
Contributor

Ticket: #1065

Make sure these boxes are checked accordingly before submitting your Pull Request -- thank you.

Contribution style:

Our Contribution agreements:

Changes (if applicable):

Link to ticket: https://redmine.openinfosecfoundation.org/issues/1065

Describe changes:

  • Introduce vlan.id keyword

Provide values to any of the below to override the defaults.

  • To use an LibHTP, Suricata-Verify or Suricata-Update pull request,
    link to the pull request in the respective _BRANCH variable.
  • Leave unused overrides blank or remove.

SV_BRANCH= OISF/suricata-verify#2183
Previous PR= #12103

and filter network packets based on Virtual Local Area Network IDs. By default,
it matches all VLAN IDs. However, if a specific layer is defined, it will only match that layer.

vlan.id uses :ref:`unsigned 32-bit integer <rules-integer-keywords>`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why 32 bit? Iirc we can have a 12bit number max, so should we use u16?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see the code uses u16

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, doc should state u16 as used in the code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also mention here the max value, and the specification that defines that?

Copy link
Contributor

@catenacyber catenacyber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work Alice

CI : red, could you investigate ?
Code : looking into it now
Commits segmentation : ok
Commit messages : title could be detect: add vlan.id keyword
Git ID set : looks fine for me
CLA : you already contributed
Doc update : good, some remark inline
Redmine ticket : ok
Rustfmt : looks ok for vlan_id.rs
Tests : nice, thanks, added a remark there
Dependencies added: none


Suricata has a ``vlan.id`` keyword that can be used in signatures to identify
and filter network packets based on Virtual Local Area Network IDs. By default,
it matches all VLAN IDs. However, if a specific layer is defined, it will only match that layer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean all layers if a packet has multiple vlan layers

@@ -29,6 +29,8 @@ pub enum RuleParseError<I> {
InvalidTransformBase64(String),
InvalidByteExtract(String),

InvalidGeneric(String),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be removed

const PrefilterPacketHeaderCtx *ctx = pectx;

for (int i = 0; i < p->vlan_idx; i++) {
if (p->vlan_id[i] == ctx->v1.u16[0] && (ctx->v1.u8[0] == 0 || ctx->v1.u8[0] - 1 == i))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should use some more similar logic as DetectVlanIdMatch with DetectU16Match...

static void DetectVlanIdFree(DetectEngineCtx *de_ctx, void *ptr)
{
DetectVlanIdData *data = ptr;
SCFree(data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid that we have to do the free in the rust side, so we need to call a rust function here

}

const DetectVlanIdData *vdata = (const DetectVlanIdData *)ctx;
if (vdata->layer == INT8_MIN) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should name this constant INT8_MIN with some name containing vlan

}
} else {
if (vdata->layer < 0) {
if (((int16_t)p->vlan_idx) + vdata->layer < 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add some comment here

if du16.is_err() {
return None;
}
let du16 = du16.unwrap().1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasonish do you have proposals for better rust style here ?


alert ip any any -> any any (msg:"Vlan ID is equal to 400"; vlan.id:400,-1; sid:1;)

In this example, we use the negative value -1 to represent the last layer of the VLAN IDs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jufajardini what do you think about the doc ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bi nitty here, I'd suggest:

Suggested change
In this example, we use the negative value -1 to represent the last layer of the VLAN IDs.
In the last example, we use the negative value -1 to represent the last layer of the VLAN IDs.

It's probably also a good idea to mention this in the description, not just here when explaining the example.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jufajardini what do you think about the doc ?

It's looking good :) I've made some suggestions, but we're going on the right direction /o/

Should we add if vlan.id supports prefiltering or not?

Copy link
Contributor

@jufajardini jufajardini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shared some comments to help with the docs, mostly. ^^

We're missing adding the new file to doc/userguide/rules/index.rst, too, otherwise it won't be added, and the docs won't be generated, throwing an error.

@@ -0,0 +1,32 @@
Vlan.id Keyword
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering what was brought up in the call we had:

Thinking about the structure we have for other keywords, I do think we should prepare the doc for the possibility of other vlan keywords being added. I'll point out in the files the changes needed for that.

That said, My suggestion is that we name the file vlan-keywords - and then the first title in this file would be VLAN Keywords -, and then have a section vlan.id for this description of the keyword itself.


vlan.id: [op]id[,layer];

The id can be matched exactly, or compared using the _op_ setting::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for bold, you can use **, for italic, *, and `` for inline code

Suggested change
The id can be matched exactly, or compared using the _op_ setting::
The id can be matched exactly, or compared using the ``op`` setting::

Comment on lines +21 to +31

alert ip any any -> any any (msg:"Vlan ID is equal to 300"; vlan.id:300; sid:1;)

::

alert ip any any -> any any (msg:"Vlan ID is equal to 300"; vlan.id:300,1; sid:1;)

::

alert ip any any -> any any (msg:"Vlan ID is equal to 400"; vlan.id:400,-1; sid:1;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a few directives that help with formatting rule examples. You can add them in the first lines of your document, and then benefit from some neat options.

More on this: https://docs.suricata.io/en/latest/devguide/contributing/contribution-process.html#rule-examples (and then you can take advantage of that to highlight your keyword on the examples, for instance ) usage example in our docs: https://raw.githubusercontent.com/OISF/suricata/refs/heads/master/doc/userguide/rules/http-keywords.rst

and filter network packets based on Virtual Local Area Network IDs. By default,
it matches all VLAN IDs. However, if a specific layer is defined, it will only match that layer.

vlan.id uses :ref:`unsigned 32-bit integer <rules-integer-keywords>`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also mention here the max value, and the specification that defines that?


alert ip any any -> any any (msg:"Vlan ID is equal to 400"; vlan.id:400,-1; sid:1;)

In this example, we use the negative value -1 to represent the last layer of the VLAN IDs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bi nitty here, I'd suggest:

Suggested change
In this example, we use the negative value -1 to represent the last layer of the VLAN IDs.
In the last example, we use the negative value -1 to represent the last layer of the VLAN IDs.

It's probably also a good idea to mention this in the description, not just here when explaining the example.


alert ip any any -> any any (msg:"Vlan ID is equal to 400"; vlan.id:400,-1; sid:1;)

In this example, we use the negative value -1 to represent the last layer of the VLAN IDs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jufajardini what do you think about the doc ?

It's looking good :) I've made some suggestions, but we're going on the right direction /o/

Should we add if vlan.id supports prefiltering or not?

{
sigmatch_table[DETECT_VLAN_ID].name = "vlan.id";
sigmatch_table[DETECT_VLAN_ID].desc = "match vlan id";
sigmatch_table[DETECT_VLAN_ID].url = "/rules/vlan-id.html";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we agree to having a file more generic for vlan keywords, then this one becomes:

Suggested change
sigmatch_table[DETECT_VLAN_ID].url = "/rules/vlan-id.html";
sigmatch_table[DETECT_VLAN_ID].url = "/rules/vlan-keywords.html#vlan-id";

return None;
}
let layer = if parts.len() == 2 {
i8::from_str(parts[1])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion for even more expressivity : add support vlan.id: >100,all which matches only if all vlan layers match

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants