Skip to content

Tap mode: add -n flag, activate interface on open, fix build/install - #66

Merged
grossmj merged 5 commits into
GNS3:masterfrom
yueguobin:feat/no-hostconf-flag
Oct 12, 2026
Merged

grossmj merged 5 commits into
GNS3:masterfrom
yueguobin:feat/no-hostconf-flag

Conversation

@yueguobin

@yueguobin yueguobin commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

What this does

Makes tap mode usable by callers that create and own the host side of the tap (bridges, VMs, simulators). Today vpcs assumes it owns it: every static ip command runs ifconfig tapX ... up on the host (the only system() call in the tree), and that up is also the only thing that ever brought the tap interface up.

  • -n flag — skip the host auto-configuration. Default behavior unchanged; only the static ip path is affected (ip dhcp never touched the host).
  • Activate the tap in open_tap() — TUNSETIFF leaves the interface administratively DOWN, and a down tun fd carries no frames: every outgoing packet failed with "Send packet error". Set IFF_UP via SIOCSIFFLAGS right after attach (same CAP_NET_ADMIN). This also fixes ip dhcp in tap mode, which never ran autoconf and sent into a down interface.
  • Autoconf target fix — single-instance mode now configures the -d name device instead of tap<id>.
  • Top-level Makefile — make / sudo make install / make clean, dispatching like mk.sh. Also fixes the .c.o suffix rule: GNU make ignores prerequisites on suffix rules (header changes never triggered rebuilds) and the list was stale (keys.h -> keydef.h); defaults CCOPT=-O2 so a direct make matches mk.sh.
  • install target (Makefile.linux) — installs to $(BINDIR); grants cap_net_admin+ep via setcap best-effort (warning only on failure — udp mode needs no privileges).
  • Tap name buffer — sized IFNAMSIZ instead of the local IFNAMESIZ (12); names of 12-15 chars could overflow.

Scope

-n disables the host auto-configuration only. Capabilities (cap_net_admin for /dev/net/tun + TUNSETIFF) and the tap's lifetime/teardown ordering remain the caller's concern. Attaching to a pre-created persistent tap is unchanged.

Testing

Unprivileged user, binary granted cap_net_admin+ep:

  • ip 192.168.1.2/24 on a freshly created tap completes with zero "Send packet error" (previously every outgoing packet failed); host interface is UP,LOWER_UP while vpcs runs
  • ip dhcp transmits cleanly (zero send errors)
  • with -n against a pre-created persistent tap: attach works, and the host interface's addresses and state are untouched

In tap mode, every static `ip` command runs
`ifconfig tapX <max-host-id> ... up` on the host (the only system()
call in the tree). That side effect conflicts with callers that own
the host side of the tap (bridges, addresses, admin state), such as
GNS3 anchoring a pre-created persistent tap.

- new -n option clears `hostconf` and gates the autoconf block;
  default behavior is unchanged
- fix the autoconf target in single-instance mode: use the -d tap
  name instead of tap<id>, mirroring open_tap() naming (previously
  it configured tap0 while the VPC talked to a differently named tap)
- Makefile.linux: new install target; grants cap_net_admin+ep via
  setcap when available, best-effort with a warning since udp mode
  needs no privileges and setcap may be absent
- docs: usage(), `ip ?` help text, INSTALL

With -n, vpcs never touches host state; the tap is expected to be
created and brought up by the caller. Attaching to a pre-existing
persistent tap via TUNSETIFF is unchanged.
- dispatch to the OS-specific src makefile (same mapping as src/mk.sh);
  'install' currently exists only in Makefile.linux
- export CCOPT=-O2 so a direct make matches mk.sh builds (previously
  a bare make -f Makefile.linux silently built without -O2)
- Makefile.linux: replace the .c.o suffix rule with a pattern rule.
  GNU make ignores prerequisites on suffix rules (the long-standing
  warning), so header changes never triggered rebuilds, and the
  prerequisite list itself was stale (keys.h was renamed to keydef.h
  long ago). Header dependencies now actually work.
- INSTALL: lead with make / sudo make install
globle.h defines its own IFNAMESIZ 12, and open_tap() sized its name
buffer with it while the length guard checks the kernel's IFNAMSIZ
(16). A -d name longer than 12 chars passed the guard, truncated into
the 12-byte buffer, and reached TUNSETIFF as a nonexistent device
name — which the kernel then tried to create, needing CAP_NET_ADMIN
(EPERM for an unprivileged vpcs). Use the kernel IFNAMSIZ consistently
for the buffer and the strncpy.
TUNSETIFF attaches (or creates) the interface but leaves it
administratively DOWN, and a down tun fd carries no frames: every
outgoing packet failed with "Send packet error". The only thing that
brought the interface up was the host auto-configuration's
'ifconfig ... up', so tap mode effectively required root, and even
then 'ip dhcp' (which never runs autoconf) sent its first packet
into a down interface.

Activate the interface right after TUNSETIFF via SIOCGIFFLAGS/
SIOCSIFFLAGS on an AF_INET socket - the same CAP_NET_ADMIN already
needed for TUNSETIFF. Device activation only: addresses and masks
stay with the caller (see -n). Idempotent for pre-created anchors.
@grossmj
grossmj merged commit 233596e into GNS3:master Oct 12, 2026
3 checks passed
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