cybersecurity · intermediate · ~15 min · safe pentest lab

Count open ports in a saved nmap XML dump

Walk a static XML buffer with string functions and count specific tags.

Challenge

Your job

Implement int count_open_ports(const char *xml).

It walks the buffer and returns the number of <port ...> elements whose inner <state state="open"/> indicates the port is open. Skip filtered and closed.

Function signature

int count_open_ports(const char *xml);

Examples

Input Returns
"" 0
One open port 1
Two open + one filtered 2

Rules

  • Pure string parsing. No XML library, no allocation.
  • The buffer is NUL-terminated. Don't read past the NUL.
  • The harness runs only on static fixtures — never on a live nmap output.

Hints

  1. (concept) You don't need a real XML parser. strstr(p, "<port") finds the next port element.
  2. (direction) For each <port, look ahead within the same element (bounded by the next <port or a fixed window) for state="open".
  3. (common bug) Matching state="open" as a substring also catches state="open|filtered" in some old nmap versions. Use exact quote-bounded match.

Common mistakes

  • Reading past the NUL.
  • Treating malformed XML as fatal — count what you can and return.

Security note

This exercise is for defensive learning in a local lab only. Do not use any variant of this technique on systems you do not own or have explicit permission to test.

Why this matters

Defenders read scan output far more often than they run scans. A 20-line strstr walker is the canonical way to do it.

Input format

A NUL-terminated XML string.

Output format

A non-negative int — the count.

Constraints

No allocation. No XML library. Pure scan.

Starter code

#include <stddef.h>
#include <string.h>

int count_open_ports(const char *xml) {
    /* TODO */
    (void)xml;
    return 0;
}

Common mistakes

Matching state="open as a substring (catches "open|filtered"). Forgetting to bound the look-ahead.

Edge cases to handle

Empty string. No <port> tags. All closed/filtered. Malformed (unclosed tag) — count what you can.

Complexity

O(n) — single pass.

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.