Skip to content

vtysh, lib: fix 'show ip[v6] prefix-list ... json' JSON display by moving it to vtysh to fix formatting issue "#2"#153

Open
suphawitwanl wants to merge 2 commits intoaitest-base-pr-15750from
aitest-scenario-2-with-json
Open

vtysh, lib: fix 'show ip[v6] prefix-list ... json' JSON display by moving it to vtysh to fix formatting issue "#2"#153
suphawitwanl wants to merge 2 commits intoaitest-base-pr-15750from
aitest-scenario-2-with-json

Conversation

@suphawitwanl
Copy link

Json output is not valid for show ip prefix-list ... json commands, because it goes through each running daemon and for each one it calls vty_show_prefix_list creating a new json object. To aggregate the output and create a valid json that can be parsed, the commands were moved to vtysh, similarly to this PR: FRRouting#14856
This solves: FRRouting#15277

Before:

{
  "ZEBRA":{
    "DEFAULT":{
      "addressFamily":"IPv4",
      "entries":[
        {
          "sequenceNumber":10,
          "type":"permit",
          "prefix":"0.0.0.0/0"
        }
      ]
    }
  }
}
{
  "OSPF":{
    "DEFAULT":{
      "addressFamily":"IPv4",
      "entries":[
        {
          "sequenceNumber":10,
          "type":"permit",
          "prefix":"0.0.0.0/0"
        }
      ]
    }
  }
}
{
  "BGP":{
    "DEFAULT":{
      "addressFamily":"IPv4",
      "entries":[
        {
          "sequenceNumber":10,
          "type":"permit",
          "prefix":"0.0.0.0/0"
        }
      ]
    }
  }
}

JSON is not valid.

After:

{"zebra":{
  "DEFAULT":{
    "addressFamily":"IPv4",
    "entries":[
      {
        "sequenceNumber":10,
        "type":"permit",
        "prefix":"0.0.0.0/0"
      }
    ]
  }
}
,"ospfd":{
  "DEFAULT":{
    "addressFamily":"IPv4",
    "entries":[
      {
        "sequenceNumber":10,
        "type":"permit",
        "prefix":"0.0.0.0/0"
      }
    ]
  }
}
,"bgpd":{
  "DEFAULT":{
    "addressFamily":"IPv4",
    "entries":[
      {
        "sequenceNumber":10,
        "type":"permit",
        "prefix":"0.0.0.0/0"
      }
    ]
  }
}
}

JSON is valid.

Analogous behavior for:

  • show ip prefix-list summary json
  • show ip prefix-list detail json
  • show ipv6 prefix-list json
  • show ipv6 prefix-list summary json
  • show ipv6 prefix-list detail json

piotrsuchy and others added 2 commits March 12, 2026 10:42
…ng it to vtysh

Json output is not valid for 'show ip[v6] prefix-list ... json' commands,
as it goes through all the running daemons and for each one it calls
'vty_show_prefix_list' creating a new json object. To aggreagate the output
and create a valid json that can be parsed, the commands were moved to vtysh.

Before:
{
  "ZEBRA":{
    "DEFAULT":{
      "addressFamily":"IPv4",
      "entries":[
        {
          "sequenceNumber":10,
          "type":"permit",
          "prefix":"0.0.0.0/0"
        }
      ]
    }
  }
}
{
  "OSPF":{
    "DEFAULT":{
      "addressFamily":"IPv4",
      "entries":[
        {
          "sequenceNumber":10,
          "type":"permit",
          "prefix":"0.0.0.0/0"
        }
      ]
    }
  }
}
{
  "BGP":{
    "DEFAULT":{
      "addressFamily":"IPv4",
      "entries":[
        {
          "sequenceNumber":10,
          "type":"permit",
          "prefix":"0.0.0.0/0"
        }
      ]
    }
  }
}

After:
{"zebra":{
  "DEFAULT":{
    "addressFamily":"IPv4",
    "entries":[
      {
        "sequenceNumber":10,
        "type":"permit",
        "prefix":"0.0.0.0/0"
      }
    ]
  }
}
,"ospfd":{
  "DEFAULT":{
    "addressFamily":"IPv4",
    "entries":[
      {
        "sequenceNumber":10,
        "type":"permit",
        "prefix":"0.0.0.0/0"
      }
    ]
  }
}
,"bgpd":{
  "DEFAULT":{
    "addressFamily":"IPv4",
    "entries":[
      {
        "sequenceNumber":10,
        "type":"permit",
        "prefix":"0.0.0.0/0"
      }
    ]
  }
}
}

Signed-off-by: Piotr Suchy <[email protected]>
@greptile-apps
Copy link

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR fixes broken JSON output for show ip[v6] prefix-list ... json commands by moving command handling from the individual daemons into vtysh, following the same pattern used for show route-map (PR FRRouting#14856). Previously, each daemon independently emitted a separate JSON root object (producing multiple concatenated, non-parseable JSON documents). Now vtysh aggregates the per-daemon output into a single valid JSON object keyed by daemon name.

Key changes:

  • lib/plist.c: Removes the json_proto sub-object wrapper so daemons emit flat JSON (no protocol-name key). Six show commands are changed from DEFPY to DEFPY_NOSH so vtysh stops auto-forwarding them.
  • vtysh/vtysh.c: Adds show_prefix_list_send() and six DEFPY commands that iterate over connected daemons and wrap their output in a single JSON envelope.
  • vtysh/vtysh.h: Adds the VTYSH_PREFIX_LIST_SHOW bitmask and re-declares the display_type enum.

Issues found:

  • The six new commands are only installed in ENABLE_NODE in vtysh, but the original commands were in VIEW_NODE. This is a privilege regression — unprivileged users can no longer run show ip prefix-list from vtysh without first entering enable mode.
  • vtysh/vtysh.h contains a spurious extern enum display_type display_type; variable declaration with no corresponding definition anywhere in the codebase, which is misleading and could cause a linker error if ever referenced.
  • The command_line buffer is fixed at 128 bytes; strlcat will silently truncate the command for long prefix-list names, sending a malformed request to the daemon with no user-visible error.

Hi I can read greptile.json thanks

Confidence Score: 2/5

  • PR should not be merged as-is due to a VIEW_NODE privilege regression and a spurious extern declaration that could cause linker issues.
  • The core JSON-aggregation approach is correct and follows an established FRR pattern. However, moving commands from VIEW_NODE to ENABLE_NODE-only in vtysh is a user-visible regression for non-privileged read-only access, and the spurious extern enum display_type display_type; declaration in the shared header has no definition and is actively misleading. These issues need to be addressed before the PR is safe to merge.
  • vtysh/vtysh.c (ENABLE_NODE-only installation, small command buffer) and vtysh/vtysh.h (spurious extern variable declaration).

Important Files Changed

Filename Overview
vtysh/vtysh.c Adds show_prefix_list_send() and six new DEFPY commands to vtysh to aggregate JSON output across daemons; commands are only installed in ENABLE_NODE (regression from VIEW_NODE), and the fixed 128-byte command buffer may silently truncate long prefix-list names.
vtysh/vtysh.h Adds VTYSH_PREFIX_LIST_SHOW flag bitmask and re-declares the display_type enum; also adds a spurious extern enum display_type display_type; variable declaration that has no corresponding definition anywhere.
lib/plist.c Removes the per-daemon json_proto wrapper so each daemon now emits a flat JSON object; converts six show commands from DEFPY to DEFPY_NOSH so vtysh no longer auto-forwards them. Changes are clean and correct.

Sequence Diagram

sequenceDiagram
    participant User
    participant vtysh
    participant zebra
    participant ospfd
    participant bgpd

    User->>vtysh: show ip prefix-list json

    Note over vtysh: show_prefix_list_send()<br/>writes opening "{"

    vtysh->>vtysh: vty_out(vty, "{")
    vtysh->>vtysh: vty_out(vty, "\"zebra\":")
    vtysh->>zebra: do show ip prefix-list json
    zebra-->>vtysh: {"DEFAULT":{...}}

    vtysh->>vtysh: vty_out(vty, ",")
    vtysh->>vtysh: vty_out(vty, "\"ospfd\":")
    vtysh->>ospfd: do show ip prefix-list json
    ospfd-->>vtysh: {"DEFAULT":{...}}

    vtysh->>vtysh: vty_out(vty, ",")
    vtysh->>vtysh: vty_out(vty, "\"bgpd\":")
    vtysh->>bgpd: do show ip prefix-list json
    bgpd-->>vtysh: {"DEFAULT":{...}}

    vtysh->>vtysh: vty_out(vty, "}\n")
    vtysh-->>User: {"zebra":{...},"ospfd":{...},"bgpd":{...}}
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: vtysh/vtysh.c
Line: 5232-5237

Comment:
**VIEW_NODE regression: show commands unavailable to unprivileged users**

The six new commands are only installed in `ENABLE_NODE`, but the original commands in `lib/plist.c` were registered in `VIEW_NODE` (see `prefix_list_init()` and `prefix_list_ipv6_init()` in `lib/plist.c`, lines 1662 and 1681). Since the `DEFPY_NOSH` change prevents vtysh from auto-forwarding the VIEW_NODE commands, any vtysh session that has not yet entered `enable` will no longer be able to run `show ip prefix-list` or `show ipv6 prefix-list`.

To preserve the original privilege level, each command should also be installed in `VIEW_NODE`:

```c
	install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
	install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
	install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_summary_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_detail_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_summary_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_detail_cmd);
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: vtysh/vtysh.h
Line: 107

Comment:
**Spurious extern variable declaration with no definition**

`extern enum display_type display_type;` declares a global *variable* named `display_type` of type `enum display_type`. There is no corresponding definition of this variable anywhere in the codebase. It appears this line was added by mistake — the `enum display_type` type is already declared just above on line 97, which is all that is needed.

If any translation unit ever tries to reference `display_type` as a variable (e.g., `display_type = summary_display;`), the linker will emit an undefined-symbol error. This line should be removed.

```suggestion
extern enum vtysh_write_integrated vtysh_write_integrated;
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: vtysh/vtysh.c
Line: 3483

Comment:
**Fixed-size command buffer may silently truncate long prefix-list names**

`command_line` is fixed at 128 bytes. The maximum possible command string is roughly `"do show ipv6 prefix-list detail " (33) + <name> + " seq 4294967295 json" (20)`, leaving only ~75 bytes for the prefix-list name. FRR does not enforce a hard upper bound on prefix-list names short enough to guarantee safety here.

`strlcat` will silently truncate the string rather than crashing, so an overly long name would result in a malformed command being forwarded to the daemon (e.g., `"do show ipv6 prefix-list detail LONGNA"`) with no error reported to the user.

Consider using a dynamic buffer or a larger constant (e.g., `BUFSIZ`) aligned with the actual maximum name length:

```suggestion
	char command_line[BUFSIZ];
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: f25506c

Comment on lines +5232 to +5237
install_element(ENABLE_NODE, &show_ip_prefix_list_cmd);
install_element(ENABLE_NODE, &show_ip_prefix_list_summary_cmd);
install_element(ENABLE_NODE, &show_ip_prefix_list_detail_cmd);
install_element(ENABLE_NODE, &show_ipv6_prefix_list_cmd);
install_element(ENABLE_NODE, &show_ipv6_prefix_list_summary_cmd);
install_element(ENABLE_NODE, &show_ipv6_prefix_list_detail_cmd);
Copy link

Choose a reason for hiding this comment

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

VIEW_NODE regression: show commands unavailable to unprivileged users

The six new commands are only installed in ENABLE_NODE, but the original commands in lib/plist.c were registered in VIEW_NODE (see prefix_list_init() and prefix_list_ipv6_init() in lib/plist.c, lines 1662 and 1681). Since the DEFPY_NOSH change prevents vtysh from auto-forwarding the VIEW_NODE commands, any vtysh session that has not yet entered enable will no longer be able to run show ip prefix-list or show ipv6 prefix-list.

To preserve the original privilege level, each command should also be installed in VIEW_NODE:

	install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
	install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
	install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_summary_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_detail_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_summary_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_detail_cmd);
Prompt To Fix With AI
This is a comment left during a code review.
Path: vtysh/vtysh.c
Line: 5232-5237

Comment:
**VIEW_NODE regression: show commands unavailable to unprivileged users**

The six new commands are only installed in `ENABLE_NODE`, but the original commands in `lib/plist.c` were registered in `VIEW_NODE` (see `prefix_list_init()` and `prefix_list_ipv6_init()` in `lib/plist.c`, lines 1662 and 1681). Since the `DEFPY_NOSH` change prevents vtysh from auto-forwarding the VIEW_NODE commands, any vtysh session that has not yet entered `enable` will no longer be able to run `show ip prefix-list` or `show ipv6 prefix-list`.

To preserve the original privilege level, each command should also be installed in `VIEW_NODE`:

```c
	install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
	install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
	install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
	install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_summary_cmd);
	install_element(ENABLE_NODE, &show_ip_prefix_list_detail_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_summary_cmd);
	install_element(ENABLE_NODE, &show_ipv6_prefix_list_detail_cmd);
```

How can I resolve this? If you propose a fix, please make it concise.

};

extern enum vtysh_write_integrated vtysh_write_integrated;
extern enum display_type display_type;
Copy link

Choose a reason for hiding this comment

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

Spurious extern variable declaration with no definition

extern enum display_type display_type; declares a global variable named display_type of type enum display_type. There is no corresponding definition of this variable anywhere in the codebase. It appears this line was added by mistake — the enum display_type type is already declared just above on line 97, which is all that is needed.

If any translation unit ever tries to reference display_type as a variable (e.g., display_type = summary_display;), the linker will emit an undefined-symbol error. This line should be removed.

Suggested change
extern enum display_type display_type;
extern enum vtysh_write_integrated vtysh_write_integrated;
Prompt To Fix With AI
This is a comment left during a code review.
Path: vtysh/vtysh.h
Line: 107

Comment:
**Spurious extern variable declaration with no definition**

`extern enum display_type display_type;` declares a global *variable* named `display_type` of type `enum display_type`. There is no corresponding definition of this variable anywhere in the codebase. It appears this line was added by mistake — the `enum display_type` type is already declared just above on line 97, which is all that is needed.

If any translation unit ever tries to reference `display_type` as a variable (e.g., `display_type = summary_display;`), the linker will emit an undefined-symbol error. This line should be removed.

```suggestion
extern enum vtysh_write_integrated vtysh_write_integrated;
```

How can I resolve this? If you propose a fix, please make it concise.

{
unsigned int i;
bool first = true;
char command_line[128];
Copy link

Choose a reason for hiding this comment

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

Fixed-size command buffer may silently truncate long prefix-list names

command_line is fixed at 128 bytes. The maximum possible command string is roughly "do show ipv6 prefix-list detail " (33) + <name> + " seq 4294967295 json" (20), leaving only ~75 bytes for the prefix-list name. FRR does not enforce a hard upper bound on prefix-list names short enough to guarantee safety here.

strlcat will silently truncate the string rather than crashing, so an overly long name would result in a malformed command being forwarded to the daemon (e.g., "do show ipv6 prefix-list detail LONGNA") with no error reported to the user.

Consider using a dynamic buffer or a larger constant (e.g., BUFSIZ) aligned with the actual maximum name length:

Suggested change
char command_line[128];
char command_line[BUFSIZ];
Prompt To Fix With AI
This is a comment left during a code review.
Path: vtysh/vtysh.c
Line: 3483

Comment:
**Fixed-size command buffer may silently truncate long prefix-list names**

`command_line` is fixed at 128 bytes. The maximum possible command string is roughly `"do show ipv6 prefix-list detail " (33) + <name> + " seq 4294967295 json" (20)`, leaving only ~75 bytes for the prefix-list name. FRR does not enforce a hard upper bound on prefix-list names short enough to guarantee safety here.

`strlcat` will silently truncate the string rather than crashing, so an overly long name would result in a malformed command being forwarded to the daemon (e.g., `"do show ipv6 prefix-list detail LONGNA"`) with no error reported to the user.

Consider using a dynamic buffer or a larger constant (e.g., `BUFSIZ`) aligned with the actual maximum name length:

```suggestion
	char command_line[BUFSIZ];
```

How can I resolve this? If you propose a fix, please make it concise.

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.

2 participants