Skip to content

Conversation

@nyash
Copy link

@nyash nyash commented Dec 16, 2025

The following new options are added to the config file under the ipoe section to accel-ppp.conf:

l4-redirect-nftables=family=[ip|inet],table=[name],set=[name]
^ to specify a default nftables set

attr-l4-redirect-nftables=radius_attribute
^ to specify the radius attribute name that can be used to override the default nftables set e.g. in CoA requests

This feature is analogous to the existing iptables ipset implementation and supports the same features.

Sample usage with CoA:

  1. Make sure you have a nftables set in your firewall defined

nft add set ip filter l4set { type ipv4_addr; }

  1. Make sure you have the correct corresponding config defined that matches the declared set

l4-redirect-nftables=family=ip,table=filter,set=l4set
l4-redirect=L4-Redirect
attr-l4-redirect-nftables=L4-Redirect-nftables

  1. Make sure you have the correct attributes defined in your radius dictionary read by accel-ppp and your radius client/server

ATTRIBUTE L4-Redirect 243 integer
ATTRIBUTE L4-Redirect-nftables 244 string

  • Send a CoA request to add client's ip address to nftables set l4set (as defined by l4-redirect-nftables option):

User-Name=Foobar,L4-Redirect=1

  • Send a CoA request to remove client's ip address from nftables set l4set:

User-Name=Foobar,L4-Redirect=0

  • Send a CoA request to add client's ip address from nftables set otherl4set (overrides l4-redirect-nftables option)

User-Name=Foobar,L4-Redirect=1,L4-Redirect-nftables="family=ip,table=filter,set=otherl4set"

  • Send a CoA request to remove client's ip address from nftables set otherl4set:

User-Name=Foobar,L4-Redirect=0,L4-Redirect-nftables="family=ip,table=filter,set=otherl4set"

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for L4-Redirect using nftables sets, providing a modern alternative to the existing iptables ipset implementation. The implementation allows accel-ppp to add/remove client IP addresses to nftables sets in response to RADIUS attributes, enabling dynamic firewall rule application for traffic redirection.

Key changes:

  • New nftables set manipulation functions in libnetlink with full configuration parsing support (family, table, set)
  • Integration with ipoe module to handle l4-redirect-nftables configuration and RADIUS attribute processing
  • Documentation updates including man page and example configuration

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
config.h.in Adds HAVE_NFTABLES build configuration flag
accel-pppd/CMakeLists.txt Adds nf_tables.h header check and nftables_set.c to build
accel-pppd/libnetlink/nftables_set.h Defines nftables_set_key structure and function prototypes
accel-pppd/libnetlink/nftables_set.c Implements nftables set operations (add/del/flush) and configuration parser
accel-pppd/libnetlink/libnetlink.h Declares new nlattr helper functions for netlink message building
accel-pppd/libnetlink/libnetlink.c Implements nlattr_put, nlattr_nest_start, and nlattr_nest_end helpers
accel-pppd/include/nftables_set.h Symlink to libnetlink/nftables_set.h for include path
accel-pppd/ctrl/ipoe/ipoe.h Adds l4_redirect_nftables field to ipoe_session structure
accel-pppd/ctrl/ipoe/ipoe.c Integrates nftables support into session lifecycle, RADIUS handlers, and configuration loading
accel-pppd/accel-ppp.conf.5 Documents l4-redirect-nftables configuration option format
accel-pppd/accel-ppp.conf Adds example for l4-redirect-nftables option

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nyash nyash force-pushed the nftables-l4redirect branch 4 times, most recently from 9fc3df5 to fd3c2e9 Compare December 16, 2025 15:34
@sever-sever sever-sever requested a review from Copilot December 16, 2025 23:42
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +359 to +360
- \fitable\fR: Name of the nftables table containing the set.
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

The documentation uses \fI formatting for field names but the closing tags appear inconsistent. The text says 'family\fR', 'table\fR', and 'set\fR' which suggests these should be \fIfamily\fR, \fItable\fR, and \fIset\fR. Please verify the formatting is correct for the intended man page rendering.

Suggested change
- \fitable\fR: Name of the nftables table containing the set.
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
- \fItable\fR: Name of the nftables table containing the set.
- \fIset\fR: Name of the nftables set to which client's IPv4 will be added.

Copilot uses AI. Check for mistakes.
Specifies the nftables configuration for L4-Redirect. All three fields are required and must match an existing set in your nftables rules:
- \fIfamily\fR: Either "ip" (IPv4) or "inet" (IPv4+IPv6).
- \fitable\fR: Name of the nftables table containing the set.
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

The phrase 'client's IPv4 will be added' is missing the word 'address'. It should read 'client's IPv4 address will be added' for grammatical correctness.

Suggested change
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
- \fiset\fR: Name of the nftables set to which client's IPv4 address will be added.

Copilot uses AI. Check for mistakes.
Comment on lines +202 to +217
if (key && value) {
if (strcmp(key, "family") == 0) {
if (strcmp(value, "inet") == 0) {
option.family = NFPROTO_INET;
} else if (strcmp(value, "ip") == 0) {
option.family = NFPROTO_IPV4;
} else {
log_error("l4-redirect-nftables: family=%s, but key value must be one of 'ip', 'inet'\n", value);
goto error;
}
} else if (strcmp(key, "table") == 0) {
snprintf(option.table, sizeof(option.table), "%s", value);
} else if (strcmp(key, "set") == 0) {
snprintf(option.set, sizeof(option.set), "%s", value);
}
}
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

The parsing logic does not validate that key and value are non-NULL before comparing them with strcmp. If the configuration string is malformed (e.g., 'family=' or '=value'), strtok_r could return NULL for either key or value, leading to undefined behavior when passed to strcmp. Add explicit NULL checks before the strcmp calls.

Copilot uses AI. Check for mistakes.
{
uint8_t *payload_tail = (uint8_t *)nlh + NLA_ALIGN(nlh->nlmsg_len);
struct nlattr *attr = (struct nlattr *)payload_tail;
uint16_t payload_len = NLA_ALIGN(sizeof(struct nlattr)) + len;
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

The nla_len field should be set to the actual attribute length (header + data), not the aligned payload length. According to netlink attribute conventions, nla_len should be sizeof(struct nlattr) + len (unaligned data length), not the aligned version. This could cause netlink parsing errors.

Suggested change
uint16_t payload_len = NLA_ALIGN(sizeof(struct nlattr)) + len;
uint16_t payload_len = sizeof(struct nlattr) + len;

Copilot uses AI. Check for mistakes.
Comment on lines +591 to +611
if (conf_l4_redirect_nftables_valid || ses->l4_redirect_nftables) {
struct nftables_set_key tmp;
struct nftables_set_key *key = NULL;

if (ses->l4_redirect_nftables &&
parse_nftables_set_key_conf(ses->l4_redirect_nftables, &tmp)) {
key = &tmp;
} else if (conf_l4_redirect_nftables_valid) {
key = &conf_l4_redirect_nftables;
}

if (key) {
if (del) {
nftables_set_del(key, addr);
ses->l4_redirect_set = 0;
} else {
nftables_set_add(key, addr);
ses->l4_redirect_set = 1;
}
}
}
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

The l4_redirect_set flag is being set multiple times in the same function. When both ipset and nftables logic execute (lines 581-589 and 591-611), the flag will be set twice, which is redundant. Additionally, if both mechanisms are active and only one succeeds while the other fails, the flag state may be incorrect. Consider consolidating the flag setting to occur once after all redirect mechanisms have executed.

Copilot uses AI. Check for mistakes.
Comment on lines +595 to +597
if (ses->l4_redirect_nftables &&
parse_nftables_set_key_conf(ses->l4_redirect_nftables, &tmp)) {
key = &tmp;
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

When parse_nftables_set_key_conf fails for a session-specific nftables config, the function silently falls back to the global config. This could mask configuration errors where an incorrect session-specific nftables string is provided. Consider logging a warning when the session-specific parsing fails but conf_l4_redirect_nftables_valid is true, to help administrators detect configuration issues.

Suggested change
if (ses->l4_redirect_nftables &&
parse_nftables_set_key_conf(ses->l4_redirect_nftables, &tmp)) {
key = &tmp;
if (ses->l4_redirect_nftables) {
if (parse_nftables_set_key_conf(ses->l4_redirect_nftables, &tmp)) {
key = &tmp;
} else if (conf_l4_redirect_nftables_valid) {
/* Session-specific nftables config is invalid; fall back to global config. */
fprintf(stderr,
"ipoe: failed to parse session-specific l4-redirect nftables config \"%s\", "
"falling back to global config\n",
ses->l4_redirect_nftables);
key = &conf_l4_redirect_nftables;
}

Copilot uses AI. Check for mistakes.
Comment on lines 2506 to +2551
if (!ses->l4_redirect_ipset || strcmp(ses->l4_redirect_ipset, attr->val.string))
ipset = attr->val.string;
}
} else if (attr->attr->id == conf_attr_l4_redirect_nftables) {
if (attr->attr->type == ATTR_TYPE_STRING) {
if (!ses->l4_redirect_nftables || strcmp(ses->l4_redirect_nftables, attr->val.string))
nftables = attr->val.string;
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

This code adds braces around the single else-if statement for l4_redirect_table (lines 2541-2542), which improves consistency. However, the code would benefit from also adding braces to the l4_redirect_ipset block (lines 2543-2547) and being consistently applied throughout the function. Consider ensuring all else-if blocks in this context use braces for maintainability.

Suggested change
if (!ses->l4_redirect_ipset || strcmp(ses->l4_redirect_ipset, attr->val.string))
ipset = attr->val.string;
}
} else if (attr->attr->id == conf_attr_l4_redirect_nftables) {
if (attr->attr->type == ATTR_TYPE_STRING) {
if (!ses->l4_redirect_nftables || strcmp(ses->l4_redirect_nftables, attr->val.string))
nftables = attr->val.string;
if (!ses->l4_redirect_ipset || strcmp(ses->l4_redirect_ipset, attr->val.string)) {
ipset = attr->val.string;
}
}
} else if (attr->attr->id == conf_attr_l4_redirect_nftables) {
if (attr->attr->type == ATTR_TYPE_STRING) {
if (!ses->l4_redirect_nftables || strcmp(ses->l4_redirect_nftables, attr->val.string)) {
nftables = attr->val.string;
}

Copilot uses AI. Check for mistakes.
Comment on lines +213 to +215
snprintf(option.table, sizeof(option.table), "%s", value);
} else if (strcmp(key, "set") == 0) {
snprintf(option.set, sizeof(option.set), "%s", value);
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

The snprintf calls do not check if the value string would overflow the fixed-size buffers (64 bytes for table and set). If a malicious or misconfigured RADIUS attribute provides an overly long table or set name, it will be silently truncated, potentially causing the nftables operation to target the wrong set. Consider validating the string length before copying, or at least logging a warning if truncation occurs.

Suggested change
snprintf(option.table, sizeof(option.table), "%s", value);
} else if (strcmp(key, "set") == 0) {
snprintf(option.set, sizeof(option.set), "%s", value);
int n = snprintf(option.table, sizeof(option.table), "%s", value);
if (n < 0 || (size_t)n >= sizeof(option.table)) {
log_error("l4-redirect-nftables: table name '%s' is too long (max %zu bytes)\n",
value, sizeof(option.table) - 1);
goto error;
}
} else if (strcmp(key, "set") == 0) {
int n = snprintf(option.set, sizeof(option.set), "%s", value);
if (n < 0 || (size_t)n >= sizeof(option.set)) {
log_error("l4-redirect-nftables: set name '%s' is too long (max %zu bytes)\n",
value, sizeof(option.set) - 1);
goto error;
}

Copilot uses AI. Check for mistakes.
@nyash nyash force-pushed the nftables-l4redirect branch 2 times, most recently from deab5d3 to b3d6772 Compare December 17, 2025 00:56
The following new options are added to the config file under the ipoe section to accel-ppp.conf:

l4-redirect-nftables=family=[ip|inet],table=[name],set=[name]
^ to specify a default nftables set

attr-l4-redirect-nftables=radius_attribute
^ to specify the radius attribute name that can be used to override the default nftables set e.g. in CoA requests

This feature is analogous to the existing iptables ipset implementation and supports the same features.

Sample usage with CoA:

1. Make sure you have a nftables set in your firewall defined

nft add set ip filter l4set { type ipv4_addr\; }

2. Make sure you have the correct corresponding config defined that matches the declared set

l4-redirect-nftables=family=ip,table=filter,set=l4set
l4-redirect=L4-Redirect
attr-l4-redirect-nftables=L4-Redirect-nftables

3. Make sure you have the correct attributes defined in your radius dictionary read by accel-ppp and your radius client/server
ATTRIBUTE	L4-Redirect		243	integer
ATTRIBUTE	L4-Redirect-nftables	244	string

- Send a CoA request to add client's ip address to nftables set l4set (as defined by l4-redirect-nftables option):

"User-Name=Foobar,L4-Redirect=1"

- Send a CoA request to remove client's ip address from nftables set l4set:

"User-Name=Foobar,L4-Redirect=0"

- Send a CoA request to add client's ip address from nftables set otherl4set (overrides l4-redirect-nftables option)

"User-Name=Foobar,L4-Redirect=1,L4-Redirect-nftables=\"family=ip,table=filter,set=otherl4set\""

- Send a CoA request to remove client's ip address from nftables set otherl4set:

"User-Name=Foobar,L4-Redirect=0,L4-Redirect-nftables=\"family=ip,table=filter,set=otherl4set\""
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 11 comments.

Comments suppressed due to low confidence (1)

accel-pppd/ctrl/ipoe/ipoe.c:2602

  • Incorrect CoA logic: When l4_redirect is already enabled and a CoA request arrives with l4_redirect=1 AND a new nftables configuration, the code removes the redirect (line 2583-2584), sets l4_redirect=0, then updates the nftables config (2593-2596), and finally re-adds the redirect with the new config (2599-2601). However, after line 2584, ses->l4_redirect becomes 0, so the condition at line 2599 l4_redirect != ses->l4_redirect will be true (1 != 0), correctly triggering the re-add. But this logic path sets ses->l4_redirect=0 twice and could be confusing. The same issue exists for ipset at lines 2577-2580. Consider refactoring this logic to be clearer about the intent: remove from old set, update config, add to new set.
		if (ses->l4_redirect && l4_redirect && ipset) {
			ipoe_change_l4_redirect(ses, 1);
			ses->l4_redirect = 0;
		}

		if (ses->l4_redirect && l4_redirect && nftables) {
			ipoe_change_l4_redirect(ses, 1);
			ses->l4_redirect = 0;
		}

		if (ipset) {
			if (ses->l4_redirect_ipset)
				_free(ses->l4_redirect_ipset);
			ses->l4_redirect_ipset = _strdup(ipset);
		}

		if (nftables) { 
			if (ses->l4_redirect_nftables)
				_free(ses->l4_redirect_nftables);
			ses->l4_redirect_nftables = _strdup(nftables);
		}

		if (l4_redirect != ses->l4_redirect ) {
			ipoe_change_l4_redirect(ses, l4_redirect == 0);
			ses->l4_redirect = l4_redirect;
		}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +358 to +361
- \fIfamily\fR: Either "ip" (IPv4) or "inet" (IPv4+IPv6).
- \fitable\fR: Name of the nftables table containing the set.
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
If a L4-Redirect RADIUS is received with a non-zero value, accel-ppp will automatically add the client’s IPv4 address to the specified nftables set.
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The documentation states "Either 'ip' (IPv4) or 'inet' (IPv4+IPv6)" but the implementation only adds IPv4 addresses (in_addr_t). If 'inet' family is selected, it suggests IPv6 support which is misleading since only IPv4 addresses are being added to the set. Either update the documentation to clarify that only IPv4 addresses are added regardless of family, or add a warning/validation that rejects 'inet' family.

Suggested change
- \fIfamily\fR: Either "ip" (IPv4) or "inet" (IPv4+IPv6).
- \fitable\fR: Name of the nftables table containing the set.
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
If a L4-Redirect RADIUS is received with a non-zero value, accel-ppp will automatically add the client’s IPv4 address to the specified nftables set.
- \fIfamily\fR: Either "ip" (IPv4) or "inet" (mixed IPv4/IPv6 table; only IPv4 addresses are added by accel-ppp).
- \fitable\fR: Name of the nftables table containing the set.
- \fiset\fR: Name of the nftables set to which client's IPv4 will be added.
If a L4-Redirect RADIUS attribute is received with a non-zero value, accel-ppp will automatically add the client’s IPv4 address to the specified nftables set, regardless of the selected family.

Copilot uses AI. Check for mistakes.
Comment on lines +137 to +166
uint8_t buf[4096];
uint8_t *bufptr = buf;

int buflen = 0;
int seq = time(NULL);

if (rtnl_open_byproto(&rth, 0, NETLINK_NETFILTER)) {
log_error("nftables_set: cannot open rtnetlink\n");
return -1;
}

hdr = __build_nlmsghdr(bufptr,
NFNL_MSG_BATCH_BEGIN,
AF_UNSPEC,
0, seq++, NFNL_SUBSYS_NFTABLES);

buflen += hdr->nlmsg_len;
bufptr += hdr->nlmsg_len;

hdr = __build_nlmsghdr(bufptr,
(NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_DELSETELEM,
key->family,
NLM_F_ACK, seq++, 0);

nlattr_put(hdr, NFTA_SET_ELEM_LIST_SET, strlen(key->set)+1, key->set);
nlattr_put(hdr, NFTA_SET_ELEM_LIST_TABLE, strlen(key->table)+1, key->table);

buflen += hdr->nlmsg_len;
bufptr += hdr->nlmsg_len;

Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Missing buffer overflow protection: The code builds a netlink message into a fixed 4096-byte buffer without checking if operations exceed this limit. If the table name, set name, or nested attributes cause the message to exceed 4096 bytes, memory corruption will occur. While unlikely with typical names, this should be validated. Consider adding a check after each nlattr_put operation to ensure the message length hasn't exceeded the buffer size, or use the message length to detect overflow before sending.

Copilot uses AI. Check for mistakes.
return 0;
}


Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Inconsistent trailing newlines: The file has two blank lines at the end (lines 277-278) instead of one. This is inconsistent with the style of other files in the project. Consider removing one blank line.

Suggested change

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +90
nlattr_put(hdr, NFTA_SET_ELEM_LIST_SET, strlen(key->set)+1, key->set);
nlattr_put(hdr, NFTA_SET_ELEM_LIST_TABLE, strlen(key->table)+1, key->table);
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Potential buffer overflow: Using strlen(key->set)+1 and strlen(key->table)+1 could exceed the buffer bounds if these strings are exactly 64 characters (the buffer size defined in the struct). Since the buffers are size 64, the maximum safe string length is 63 characters plus null terminator. Consider adding validation to ensure the strings don't exceed 63 characters before calling nlattr_put, or use strnlen with a maximum of 63.

Copilot uses AI. Check for mistakes.
Comment on lines +161 to +163
nlattr_put(hdr, NFTA_SET_ELEM_LIST_SET, strlen(key->set)+1, key->set);
nlattr_put(hdr, NFTA_SET_ELEM_LIST_TABLE, strlen(key->table)+1, key->table);

Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Potential buffer overflow: Using strlen(key->set)+1 and strlen(key->table)+1 could exceed the buffer bounds if these strings are exactly 64 characters (the buffer size defined in the struct). Since the buffers are size 64, the maximum safe string length is 63 characters plus null terminator. Consider adding validation to ensure the strings don't exceed 63 characters before calling nlattr_put, or use strnlen with a maximum of 63.

Suggested change
nlattr_put(hdr, NFTA_SET_ELEM_LIST_SET, strlen(key->set)+1, key->set);
nlattr_put(hdr, NFTA_SET_ELEM_LIST_TABLE, strlen(key->table)+1, key->table);
{
size_t set_len = strnlen(key->set, sizeof(key->set) - 1) + 1;
size_t table_len = strnlen(key->table, sizeof(key->table) - 1) + 1;
nlattr_put(hdr, NFTA_SET_ELEM_LIST_SET, set_len, key->set);
nlattr_put(hdr, NFTA_SET_ELEM_LIST_TABLE, table_len, key->table);
}

Copilot uses AI. Check for mistakes.
static int conf_l4_redirect_table;
static int conf_l4_redirect_on_reject;
static const char *conf_l4_redirect_ipset;
static const char *conf_l4_redirect_ipset;
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Inconsistent spacing: There's trailing whitespace at the end of this line. This is inconsistent with the rest of the codebase and should be removed for cleaner diffs.

Suggested change
static const char *conf_l4_redirect_ipset;
static const char *conf_l4_redirect_ipset;

Copilot uses AI. Check for mistakes.
Comment on lines +200 to +201
char *key = strtok_r(pair, "=", &save2);
char *value = strtok_r(NULL, "=", &save2);
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Variable name collision: The local variable key in the parsing loop shadows the function parameter key. This makes the code confusing and could lead to bugs. Consider renaming the local variable to something like param_name or key_name to avoid this shadowing.

Copilot uses AI. Check for mistakes.
#attr-l4-redirect=L4-Redirect
#attr-l4-redirect-table=4
#attr-l4-redirect-ipset=l4-redirect
#attr-l4-redirect-nftables=l4-redirect
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Inconsistent example value for attr-l4-redirect-nftables: The example shows #attr-l4-redirect-nftables=l4-redirect which is just a simple name string. However, based on the PR description and the code implementation, this should be a RADIUS attribute name that will contain the nftables set configuration string (e.g., "family=ip,table=filter,set=otherl4set"). The current example value is misleading. Consider updating it to something like #attr-l4-redirect-nftables=L4-Redirect-nftables to match the attribute name from the PR description.

Suggested change
#attr-l4-redirect-nftables=l4-redirect
#attr-l4-redirect-nftables=L4-Redirect-nftables

Copilot uses AI. Check for mistakes.
Comment on lines +64 to +100
uint8_t buf[4096];
uint8_t *bufptr = buf;

int buflen = 0;
int seq = time(NULL);

if (rtnl_open_byproto(&rth, 0, NETLINK_NETFILTER)) {
log_error("nftables_set: cannot open rtnetlink\n");
return -1;
}

hdr = __build_nlmsghdr(bufptr,
NFNL_MSG_BATCH_BEGIN,
AF_UNSPEC,
0, seq++, NFNL_SUBSYS_NFTABLES);

buflen += hdr->nlmsg_len;
bufptr += hdr->nlmsg_len;

hdr = __build_nlmsghdr(bufptr,
(NFNL_SUBSYS_NFTABLES << 8) | type,
key->family,
flags,
seq++, 0);

nlattr_put(hdr, NFTA_SET_ELEM_LIST_SET, strlen(key->set)+1, key->set);
nlattr_put(hdr, NFTA_SET_ELEM_LIST_TABLE, strlen(key->table)+1, key->table);
nest1 = nlattr_nest_start(hdr, NFTA_SET_ELEM_LIST_ELEMENTS);
nest2 = nlattr_nest_start(hdr, 1);
nest3 = nlattr_nest_start(hdr, NFTA_SET_ELEM_KEY);
nlattr_put(hdr, NFTA_DATA_VALUE, sizeof(uint32_t), &addr);
nlattr_nest_end(hdr, nest3);
nlattr_nest_end(hdr, nest2);
nlattr_nest_end(hdr, nest1);

buflen += hdr->nlmsg_len;
bufptr += hdr->nlmsg_len;
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Missing buffer overflow protection: The code builds a netlink message into a fixed 4096-byte buffer without checking if operations exceed this limit. If the table name, set name, or nested attributes cause the message to exceed 4096 bytes, memory corruption will occur. While unlikely with typical names, this should be validated. Consider adding a check after each nlattr_put operation to ensure the message length hasn't exceeded the buffer size, or use the message length to detect overflow before sending.

Copilot uses AI. Check for mistakes.
int parse_nftables_set_key_conf(const char *conf, struct nftables_set_key *key);

#endif

Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Inconsistent trailing newlines: The file has two blank lines at the end (lines 17-18) instead of one. This is inconsistent with the style of other files in the project. Consider removing one blank line.

Suggested change

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant