summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.coderabbit.yaml29
l---------.github/copilot-instructions.md1
-rw-r--r--.github/mergify.yml22
-rw-r--r--.github/workflows/cla-check.yml18
-rw-r--r--.github/workflows/pr-mirror-repo-sync.yml30
-rw-r--r--.github/workflows/trigger-rebuild-repo-package.yml4
-rw-r--r--.gitignore79
-rw-r--r--AGENTS.md47
-rw-r--r--Jenkinsfile23
-rw-r--r--configure.ac2
-rw-r--r--debian/changelog15
-rw-r--r--debian/control4
-rw-r--r--src/Makefile.am6
-rw-r--r--src/ipaddrcheck_functions.c87
-rw-r--r--src/ipaddrcheck_functions.h7
-rw-r--r--src/ipaddrcheck_functions.obin55552 -> 0 bytes
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/check_ipaddrcheck.c21
-rwxr-xr-xtests/integration_tests.sh54
19 files changed, 365 insertions, 88 deletions
diff --git a/.coderabbit.yaml b/.coderabbit.yaml
new file mode 100644
index 0000000..bb10f3a
--- /dev/null
+++ b/.coderabbit.yaml
@@ -0,0 +1,29 @@
+# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
+#
+# Per-repo CodeRabbit override for vyos/ipaddrcheck.
+#
+# Most behavior is inherited from the org-level central baseline at
+# https://github.com/vyos/coderabbit/blob/production/.coderabbit.yaml
+# (loaded automatically because the central repo is named `coderabbit`
+# under the same GitHub org as this repo).
+#
+# When this repo has a VyOS-Networks mirror, this file is propagated by
+# the gen-1 mirror pipeline. CodeRabbit's Atlassian/Jira OAuth grant is
+# attached to the VyOS-Networks org only (one GitHub-org → Jira-tenant
+# link per install), so `usage: auto` self-disables on the public source
+# and activates on the private mirror — one file, both orgs.
+
+# Opt this repo into the inheritance chain. Without this, the file below
+# would entirely REPLACE the central baseline rather than merge per-field
+# on top of it — inheritance is disabled by default per CodeRabbit's
+# schema (https://docs.coderabbit.ai/configuration/configuration-inheritance).
+inheritance: true
+
+knowledge_base:
+ jira:
+ # `auto` is the cross-org-safe value: enabled on private/internal
+ # mirror repos where Jira OAuth is connected, disabled on the public
+ # source where it is not.
+ usage: auto
+ project_keys:
+ - VD
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 120000
index 0000000..be77ac8
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1 @@
+../AGENTS.md \ No newline at end of file
diff --git a/.github/mergify.yml b/.github/mergify.yml
new file mode 100644
index 0000000..0617580
--- /dev/null
+++ b/.github/mergify.yml
@@ -0,0 +1,22 @@
+# yaml-language-server: $schema=https://docs.mergify.com/configuration/file-format/
+# Mergify configuration for vyos/ipaddrcheck.
+#
+# Inherits the central baseline from vyos/mergify:.mergify.yml. The central
+# baseline provides:
+# - `defaults.actions.backport.ignore_conflicts: false`
+# - `pull_request_rules` → label conflicting PRs with `conflicts`;
+# T-ID format checks on PR title and commit messages.
+# - `commands_restrictions` → restrict @Mergifyio slash commands to the
+# org Maintainers team + vyosbot. Resolves correctly on both sides of
+# the cross-org mirror: vyos/mergify uses @vyos/maintainers,
+# VyOS-Networks/mergify uses @VyOS-Networks/maintainers.
+#
+# Replaces the inline T8531 predecessor config. Rollout context:
+# T8782 (Mergify central-config rollout), T8852 (fleet migration to
+# `extends:`). See https://vyos.dev/T8782, https://vyos.dev/T8852,
+# and the Confluence spec at
+# https://vyos.atlassian.net/wiki/spaces/VYOS/pages/849477640.
+
+extends: mergify
+merge_protections_settings:
+ reporting_method: check-runs
diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml
new file mode 100644
index 0000000..625ff78
--- /dev/null
+++ b/.github/workflows/cla-check.yml
@@ -0,0 +1,18 @@
+name: "CLA Check"
+
+permissions:
+ actions: write
+ contents: read
+ pull-requests: write
+ statuses: write
+
+on:
+ pull_request_target:
+ types: [opened, synchronize, closed]
+ issue_comment:
+ types: [created]
+
+jobs:
+ call-cla-assistant:
+ uses: vyos/vyos-cla-signatures/.github/workflows/cla-reusable.yml@current
+ secrets: inherit \ No newline at end of file
diff --git a/.github/workflows/pr-mirror-repo-sync.yml b/.github/workflows/pr-mirror-repo-sync.yml
new file mode 100644
index 0000000..0f6c449
--- /dev/null
+++ b/.github/workflows/pr-mirror-repo-sync.yml
@@ -0,0 +1,30 @@
+# .github/workflows/pr-mirror-repo-sync.yml
+# DO NOT EDIT — managed by mirror-pipeline rollout.
+# To opt out: set vars.MIRROR_ENABLED=false in this repo's Actions variables.
+name: PR Mirror and Repo Sync
+
+on:
+ pull_request_target:
+ types: [closed]
+ branches: [current]
+ workflow_dispatch:
+ inputs:
+ sync_branch:
+ required: true
+ type: string
+
+permissions:
+ contents: write
+ pull-requests: write
+ issues: write
+
+jobs:
+ call:
+ if: |
+ github.repository_owner == 'vyos'
+ && (github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch')
+ && vars.MIRROR_ENABLED != 'false'
+ uses: vyos/.github/.github/workflows/pr-mirror-repo-sync.yml@current
+ with:
+ sync_branch: ${{ inputs.sync_branch || github.event.pull_request.base.ref }}
+ secrets: inherit
diff --git a/.github/workflows/trigger-rebuild-repo-package.yml b/.github/workflows/trigger-rebuild-repo-package.yml
index 37ec832..e26669b 100644
--- a/.github/workflows/trigger-rebuild-repo-package.yml
+++ b/.github/workflows/trigger-rebuild-repo-package.yml
@@ -6,6 +6,8 @@ on:
- closed
branches:
- current
+ - circinus
+ - sagitta
workflow_dispatch:
jobs:
@@ -23,7 +25,7 @@ jobs:
needs: get_repo_name
uses: vyos/.github/.github/workflows/trigger-rebuild-repo-package.yml@current
with:
- branch: ${{ github.ref_name }}
+ branch: ${{ github.event.pull_request.base.ref }}
package_name: ${{ needs.get_repo_name.outputs.PACKAGE_NAME }}
secrets:
REMOTE_OWNER: ${{ secrets.REMOTE_OWNER }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6f267c1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,79 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Autotools-generated files
+
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache/
+compile
+config.status
+configure
+depcomp
+install-sh
+man/Makefile
+man/Makefile.in
+missing
+src/.deps/
+src/.dirstamp
+src/Makefile
+src/Makefile.in
+src/config.h
+src/config.h.in
+src/stamp-h1
+test-driver
+tests/.deps/
+tests/Makefile
+tests/Makefile.in
+
+# Misc
+
+*.log
+*.trs
+
+# Build artifacts
+
+src/ipaddrcheck
+tests/check_ipaddrcheck
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..ba2e3e5
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,47 @@
+# AGENTS.md
+
+## Project purpose
+
+C utility for IPv4/IPv6 address and prefix validation in shell scripts. Used by VyOS as the canonical "is this string a valid IP / network / host / CIDR?" checker invoked from XML validators and conf-mode scripts. Fast and exit-status-driven (intended for `if ipaddrcheck --is-ipv4...; then...`).
+
+## Tech stack
+
+- C, autotools (`configure.ac`, `Makefile.am`, autoconf 2.x).
+- Dependencies: `libcidr` (parsing), `libpcre2-8` (regex), `check >= 0.9.4` (test framework).
+- Debian packaging under `debian/`. Upstream autotools version `1.1` (`configure.ac`); current Debian package version `1.4` (`debian/changelog`).
+
+## Build / test / run
+
+```
+autoreconf -fi # generate configure
+./configure
+make
+make check # uses libcheck unit tests under tests/
+make install # installs into AC_PREFIX_DEFAULT (/usr)
+# Debian package
+dpkg-buildpackage -uc -us -tc -b
+```
+
+## Repository layout
+
+- `src/` — C sources (`ipaddrcheck.c`, headers, autotools `Makefile.am`).
+- `tests/` — libcheck C unit tests (`check_ipaddrcheck.c`) and shell integration tests (`assert.sh`, `integration_tests.sh`).
+- `man/` — manpages.
+- `debian/` — Debian packaging.
+- `configure.ac`, `Makefile.am`, `INSTALL`, `NEWS`, `ChangeLog`, `AUTHORS`, `COPYING` (GPL-2), `COPYING-LGPL` (LGPL-2.1).
+
+## Cross-repo context
+
+One of the canonical 14 VyOS-image build packages, listed in an internal repository. Built into VyOS images by `vyos-build` and invoked at runtime by `vyos-1x` validators and conf-mode scripts. Sits in the §3.5 native-libraries category alongside `hvinfo`, `udp-broadcast-relay`, etc.
+
+## Conventions
+
+- Commit / PR title format: `component: T12345: description` (Phorge task ID at https://vyos.dev mandatory). Enforced by `vyos/.github` reusable workflows where consumed.
+- Branch model: `current` (rolling), `circinus` (1.5 LTS), `sagitta` (1.4 LTS), `equuleus` (1.3 LTS).
+- Maintained by the VyOS team (`maintainers@vyos.net`); license is GPL-2 + LGPL-2.1 dual.
+
+## Notes for future contributors
+
+- Used as a CLI-level validator — exit status 0/1 is the contract. Don't break stdout/stderr conventions or add chatty output.
+- `libcidr` is by Matthew Fuller (http://www.over-yonder.net/~fullermd/projects/libcidr) — Debian-packaged.
+- Adding a new flag: extend `src/ipaddrcheck.c`'s argument table and add a libcheck test under `tests/`.
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 21a6829..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2020-2021 VyOS maintainers and contributors
-//
-// This program is free software; you can redistribute it and/or modify
-// in order to easy exprort images built to "external" world
-// it under the terms of the GNU General Public License version 2 or later as
-// published by the Free Software Foundation.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-@NonCPS
-
-// Using a version specifier library, use 'current' branch. The underscore (_)
-// is not a typo! You need this underscore if the line immediately after the
-// @Library annotation is not an import statement!
-@Library('vyos-build@current')_
-
-// Start package build using library function from https://github.com/vyos/vyos-build
-buildPackage(null, null, null, true)
diff --git a/configure.ac b/configure.ac
index 567bfd9..482523c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,6 @@ AC_COPYRIGHT([Copyright (c) 2024 VyOS maintainers and contributors.])
#AC_PROG_CC
AM_PROG_CC_C_O
-AC_CHECK_HEADER([pcre.h], [], [AC_MSG_FAILURE([pcre.h is not found.])])
AC_CHECK_HEADER([libcidr.h], [], [AC_MSG_FAILURE([libcidr.h is not found.])])
AM_INIT_AUTOMAKE([gnu no-dist-gzip dist-bzip2 subdir-objects])
@@ -14,5 +13,6 @@ AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile man/Makefile])
AC_CONFIG_HEADERS([src/config.h])
PKG_CHECK_MODULES([CHECK], [check >= 0.9.4])
+PKG_CHECK_MODULES([PCRE2], [libpcre2-8])
AC_OUTPUT
diff --git a/debian/changelog b/debian/changelog
index 6405fd7..d51c754 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+ipaddrcheck (1.4) unstable; urgency=medium
+
+ * Do not disallow all-zero host part IPv6 addresses for host and interface address checks (Daniil Baturin).
+
+ -- Daniil Baturin <daniil@vyos.io> Fri, 05 Dec 2025 15:04:03 +0000
+
+ipaddrcheck (1.3) unstable; urgency=medium
+
+ * New option --range-prefix-length to require ranges to be within a subnet (Daniil Baturin).
+ * Options for checking IP ranges: --is-ipv4-range and --is-ipv6-range (Daniil Baturin).
+ * Fixed linker flags to build correctly on Debian Bullseye (John Eastabrook).
+ * Removed stale dependency on libcidr0-dev (Christian Breunig).
+
+ -- Daniil Baturin <daniil@vyos.io> Tue, 25 Feb 2025 18:21:43 +0000
+
ipaddrcheck (1.2) unstable; urgency=medium
* Correct recognition of IPv4 /31 and IPv6 /127 as valid host addresses.
diff --git a/debian/control b/debian/control
index ac61240..bc6785a 100644
--- a/debian/control
+++ b/debian/control
@@ -2,11 +2,11 @@ Source: ipaddrcheck
Section: contrib/net
Priority: extra
Maintainer: VyOS Package Maintainers <maintainers@vyos.net>
-Build-Depends: autoconf, debhelper (>= 9), libpcre3-dev, libcidr-dev, check
+Build-Depends: autoconf, debhelper (>= 9), libpcre2-dev, libcidr-dev, check
Standards-Version: 3.9.6
Package: ipaddrcheck
Architecture: any
-Depends: libpcre3, libcidr0, ${shlibs:Depends}, ${misc:Depends}
+Depends: libpcre2-8-0, libcidr0, ${shlibs:Depends}, ${misc:Depends}
Description: IPv4 and IPv6 address validation utility
A validation utility for IPv4 and IPv6 addresses.
diff --git a/src/Makefile.am b/src/Makefile.am
index 1c43bae..ce8ea59 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
-AM_CFLAGS = --pedantic -Wall -Werror -Wno-error=format-overflow= -std=c99 -O2
-AM_LDFLAGS =
+AM_CFLAGS = --pedantic -Wall -Werror -std=c99 -O2
+AM_CPPFLAGS = $(PCRE2_CFLAGS)
ipaddrcheck_SOURCES = ipaddrcheck.c ipaddrcheck_functions.c
-ipaddrcheck_LDADD = -lcidr -lpcre
+ipaddrcheck_LDADD = -lcidr $(PCRE2_LIBS)
bin_PROGRAMS = ipaddrcheck
diff --git a/src/ipaddrcheck_functions.c b/src/ipaddrcheck_functions.c
index 2d2dff3..09830a1 100644
--- a/src/ipaddrcheck_functions.c
+++ b/src/ipaddrcheck_functions.c
@@ -2,7 +2,7 @@
* ipaddrcheck_functions.c: IPv4/IPv6 validation functions for ipaddrcheck
*
* Copyright (C) 2013 Daniil Baturin
- * Copyright (C) 2018-2024 VyOS maintainers and contributors
+ * Copyright (C) 2018-2025 VyOS maintainers and contributors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -41,25 +41,31 @@
int regex_matches(const char* regex, const char* str)
{
- int offsets[1];
- pcre *re;
+ pcre2_code *re;
int rc;
- const char *error;
- int erroffset;
+ int out;
+ int error;
+ PCRE2_SIZE erroffset;
- re = pcre_compile(regex, 0, &error, &erroffset, NULL);
+ re = pcre2_compile((PCRE2_SPTR)regex, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, NULL);
assert(re != NULL);
- rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, offsets, 1);
+ pcre2_match_data *match = pcre2_match_data_create_from_pattern(re, NULL);
+
+ rc = pcre2_match(re, (PCRE2_SPTR)str, strlen(str), 0, 0, match, NULL);
if( rc >= 0)
{
- return RESULT_SUCCESS;
+ out = RESULT_SUCCESS;
}
else
{
- return RESULT_FAILURE;
+ out = RESULT_FAILURE;
}
+
+ pcre2_match_data_free(match);
+ pcre2_code_free(re);
+ return out;
}
@@ -319,29 +325,15 @@ int is_ipv6(CIDR *address)
return(result);
}
-/* Is it a correct IPv6 host address? */
+/* Is it a correct IPv6 host address?
+ Everything except the unspecified address is.
+ */
int is_ipv6_host(CIDR *address)
{
int result;
- /* We reuse the same logic that prevents IPv4 network addresses
- from being assigned to interfaces (address == network_address),
- but the reason is slightly differnt.
-
- As per https://www.rfc-editor.org/rfc/rfc4291 section 2.6.1,
- >[Subnet-Router anycast address] is syntactically
- >the same as a unicast address for an interface on the link with the
- >interface identifier set to zero.
-
- So, the first address of the subnet must not be used for link addresses,
- even if the semantic reason is different.
- There's absolutely nothing wrong with assigning the last address, though,
- since there's no broadcast in IPv6.
- */
-
if( (cidr_get_proto(address) == CIDR_IPV6) &&
- ((cidr_equals(address, cidr_addr_network(address)) < 0) ||
- (cidr_get_pflen(address) >= 127)) )
+ (cidr_equals(address, cidr_from_str(IPV6_UNSPECIFIED)) != 0) )
{
result = RESULT_SUCCESS;
}
@@ -546,7 +538,10 @@ int is_ipv4_range(char* range_str, int prefix_length, int verbose)
If the regex check succeeded, we know the hyphen is there. */
split_range(range_str, left, right);
- if( !is_ipv4_single(left) )
+ CIDR* left_addr = cidr_from_str(left);
+ CIDR* right_addr = cidr_from_str(right);
+
+ if( !(is_ipv4_single(left) && is_valid_address(left_addr)) )
{
if( verbose )
{
@@ -554,7 +549,7 @@ int is_ipv4_range(char* range_str, int prefix_length, int verbose)
}
result = RESULT_FAILURE;
}
- else if( !is_ipv4_single(right) )
+ else if( !(is_ipv4_single(right) && is_valid_address(right_addr)) )
{
if( verbose )
{
@@ -564,12 +559,10 @@ int is_ipv4_range(char* range_str, int prefix_length, int verbose)
}
else
{
- CIDR* left_addr = cidr_from_str(left);
- CIDR* right_addr = cidr_from_str(right);
struct in_addr* left_in_addr = cidr_to_inaddr(left_addr, NULL);
struct in_addr* right_in_addr = cidr_to_inaddr(right_addr, NULL);
- if( left_in_addr->s_addr <= right_in_addr->s_addr )
+ if( ntohl(left_in_addr->s_addr) <= ntohl(right_in_addr->s_addr) )
{
/* If non-zero prefix_length is given,
check if the right address is within the network of the first one. */
@@ -577,10 +570,13 @@ int is_ipv4_range(char* range_str, int prefix_length, int verbose)
{
char left_pref_str[19];
- /* XXX: Prefix length size is checked elsewhere, so it can't be more than 2 characters (32)
+ /* XXX: Prefix length size is checked elsewhere with a regex, so it can't be more than 2 characters (32)
and overflow cannot occur.
*/
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wformat-overflow="
sprintf(left_pref_str, "%s/%u", left, prefix_length);
+ #pragma GCC diagnostic pop
CIDR* left_addr_with_pref = cidr_from_str(left_pref_str);
CIDR* left_net = cidr_addr_network(left_addr_with_pref);
if( cidr_contains(left_net, right_addr) == 0 )
@@ -608,9 +604,9 @@ int is_ipv4_range(char* range_str, int prefix_length, int verbose)
result = RESULT_FAILURE;
}
- cidr_free(left_addr);
- cidr_free(right_addr);
}
+ cidr_free(left_addr);
+ cidr_free(right_addr);
}
return(result);
@@ -644,7 +640,11 @@ int is_ipv6_range(char* range_str, int prefix_length, int verbose)
If the regex check succeeded, we know the hyphen is there. */
split_range(range_str, left, right);
- if( !is_ipv6_single(left) )
+ CIDR* left_addr = cidr_from_str(left);
+ CIDR* right_addr = cidr_from_str(right);
+
+ if( !(is_ipv6_single(left) &&
+ is_valid_address(left_addr) && !duplicate_double_colons(left)) )
{
if( verbose )
{
@@ -652,7 +652,8 @@ int is_ipv6_range(char* range_str, int prefix_length, int verbose)
}
result = RESULT_FAILURE;
}
- else if( !is_ipv6_single(right) )
+ else if( !(is_ipv6_single(right) &&
+ is_valid_address(right_addr) && !duplicate_double_colons(right)) )
{
if( verbose )
{
@@ -662,8 +663,6 @@ int is_ipv6_range(char* range_str, int prefix_length, int verbose)
}
else
{
- CIDR* left_addr = cidr_from_str(left);
- CIDR* right_addr = cidr_from_str(right);
struct in6_addr* left_in6_addr = cidr_to_in6addr(left_addr, NULL);
struct in6_addr* right_in6_addr = cidr_to_in6addr(right_addr, NULL);
@@ -675,10 +674,13 @@ int is_ipv6_range(char* range_str, int prefix_length, int verbose)
{
char left_pref_str[44];
- /* XXX: Prefix length size is checked elsewhere, so it can't be more than 3 characters (128)
+ /* XXX: Prefix length size is checked elsewhere with a regex, so it can't be more than 3 characters (128)
and overflow cannot occur.
*/
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wformat-overflow="
sprintf(left_pref_str, "%s/%u", left, prefix_length);
+ #pragma GCC diagnostic pop
CIDR* left_addr_with_pref = cidr_from_str(left_pref_str);
CIDR* left_net = cidr_addr_network(left_addr_with_pref);
if( cidr_contains(left_net, right_addr) == 0 )
@@ -705,10 +707,9 @@ int is_ipv6_range(char* range_str, int prefix_length, int verbose)
}
result = RESULT_FAILURE;
}
-
- cidr_free(left_addr);
- cidr_free(right_addr);
}
+ cidr_free(left_addr);
+ cidr_free(right_addr);
}
return(result);
diff --git a/src/ipaddrcheck_functions.h b/src/ipaddrcheck_functions.h
index 9b5e55f..bd131cf 100644
--- a/src/ipaddrcheck_functions.h
+++ b/src/ipaddrcheck_functions.h
@@ -2,7 +2,7 @@
* ipaddrcheck_functions.h: macros and prototypes for ipaddrcheck
*
* Copyright (C) 2013 Daniil Baturin
- * Copyright (C) 2018-2024 VyOS maintainers and contributors
+ * Copyright (C) 2018-2025 VyOS maintainers and contributors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,11 +23,13 @@
#ifndef IPADDRCHECK_FUNCTIONS_H
#define IPADDRCHECK_FUNCTIONS_H
+#define PCRE2_CODE_UNIT_WIDTH 8
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
-#include <pcre.h>
+#include <pcre2.h>
#include <libcidr.h>
#define INVALID_PROTO -1
@@ -48,6 +50,7 @@
#define IPV6_MULTICAST "ff00::/8"
#define IPV6_LINKLOCAL "fe80::/64"
#define IPV6_LOOPBACK "::1/128"
+#define IPV6_UNSPECIFIED "::/0"
#define NO_LOOPBACK 0
#define LOOPBACK_ALLOWED 1
diff --git a/src/ipaddrcheck_functions.o b/src/ipaddrcheck_functions.o
deleted file mode 100644
index a689dac..0000000
--- a/src/ipaddrcheck_functions.o
+++ /dev/null
Binary files differ
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5c0a09a..f7b824a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,3 +1,5 @@
+AM_CPPFLAGS = $(PCRE2_CFLAGS)
+
TESTS = check_ipaddrcheck integration_tests.sh
TESTS_ENVIRONMENT = top_srcdir=$(top_srcdir) PATH=.:$(top_srcdir)/src:$$PATH
@@ -5,4 +7,4 @@ TESTS_ENVIRONMENT = top_srcdir=$(top_srcdir) PATH=.:$(top_srcdir)/src:$$PATH
check_PROGRAMS = check_ipaddrcheck
check_ipaddrcheck_SOURCES = check_ipaddrcheck.c ../src/ipaddrcheck_functions.c
check_ipaddrcheck_CFLAGS = @CHECK_CFLAGS@
-check_ipaddrcheck_LDADD = -lcidr -lpcre @CHECK_LIBS@
+check_ipaddrcheck_LDADD = -lcidr $(PCRE2_LIBS) @CHECK_LIBS@
diff --git a/tests/check_ipaddrcheck.c b/tests/check_ipaddrcheck.c
index ebae1e1..fe3876c 100644
--- a/tests/check_ipaddrcheck.c
+++ b/tests/check_ipaddrcheck.c
@@ -2,7 +2,7 @@
* check_ipaddrcheck.c: ipaddrcheck unit tests
*
* Copyright (C) 2013 Daniil Baturin
- * Copyright (C) 2018-2024 VyOS maintainers and contributors
+ * Copyright (C) 2018-2025 VyOS maintainers and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 or later as
@@ -289,11 +289,6 @@ START_TEST (test_is_ipv6_host)
CIDR* good_address_cidr = cidr_from_str(good_address_str_cidr);
ck_assert_int_eq(is_ipv6_host(good_address_cidr), RESULT_SUCCESS);
cidr_free(good_address_cidr);
-
- char* bad_address_str = "2001:db8:f::/48";
- CIDR* bad_address = cidr_from_str(bad_address_str);
- ck_assert_int_eq(is_ipv6_host(bad_address), RESULT_FAILURE);
- cidr_free(bad_address);
}
END_TEST
@@ -367,15 +362,20 @@ START_TEST (test_is_any_host)
ck_assert_int_eq(is_any_host(good_address_v6), RESULT_SUCCESS);
cidr_free(good_address_v6);
+ char* good_address_str_v6_all_zero = "2001:db8::/32";
+ CIDR* good_address_v6_all_zero = cidr_from_str(good_address_str_v6_all_zero);
+ ck_assert_int_eq(is_any_host(good_address_v6_all_zero), RESULT_SUCCESS);
+ cidr_free(good_address_v6_all_zero);
+
char* bad_address_str_v4 = "192.0.2.0/24";
CIDR* bad_address_v4 = cidr_from_str(bad_address_str_v4);
ck_assert_int_eq(is_any_host(bad_address_v4), RESULT_FAILURE);
cidr_free(bad_address_v4);
- char* bad_address_str_v6 = "2001:db8::/32";
- CIDR* bad_address_v6 = cidr_from_str(bad_address_str_v6);
- ck_assert_int_eq(is_any_host(bad_address_v6), RESULT_FAILURE);
- cidr_free(bad_address_v6);
+ char* bad_address_str_v6_unspec = "::/0";
+ CIDR* bad_address_v6_unspec = cidr_from_str(bad_address_str_v6_unspec);
+ ck_assert_int_eq(is_any_host(bad_address_v6_unspec), RESULT_FAILURE);
+ cidr_free(bad_address_v6_unspec);
}
END_TEST
@@ -408,6 +408,7 @@ START_TEST (test_is_ipv4_range)
ck_assert_int_eq(is_ipv4_range("192.0.2.0-192.0.2.10", 0, 1), RESULT_SUCCESS);
ck_assert_int_eq(is_ipv4_range("192.0.2.-", 0, 1), RESULT_FAILURE);
ck_assert_int_eq(is_ipv4_range("192.0.2.99-192.0.2.11", 0, 1), RESULT_FAILURE);
+ ck_assert_int_eq(is_ipv4_range("192.0.2.0-1.8.2.1", 0, 1), RESULT_FAILURE);
}
END_TEST
diff --git a/tests/integration_tests.sh b/tests/integration_tests.sh
index 3a1e4ea..9c937df 100755
--- a/tests/integration_tests.sh
+++ b/tests/integration_tests.sh
@@ -3,7 +3,7 @@
# integration_tests.sh: ipaddrcheck integration tests
#
# Copyright (C) 2013 Daniil Baturin
-# Copyright (C) 2018-2024 VyOS maintainers and contributors
+# Copyright (C) 2018-2025 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -56,6 +56,29 @@ ipv4_range_negative=(
192.0.2.-192.0.2.100
192.0.2.0-
192.0.2.200-192.0.2.100
+ 192.0.2.1-192.0.2.500
+)
+
+ipv4_interface_address_positive=(
+ 192.0.2.1/24
+ 192.168.1.0/23
+)
+
+ipv4_interface_address_negative=(
+ 192.0.2.0/24 # Network address
+ 192.0.2.255/24 # Broadcast
+ 224.0.0.1/24 # Multicast
+ 0.0.0.0/0 # Unspecified
+)
+
+ipv6_interface_address_positive=(
+ 2001:db8::1/64
+ 2001:db8::/64
+)
+
+ipv6_interface_address_negative=(
+ ff02::1:2 # Multicast
+ ::/0 # Unspecified
)
ipv6_range_positive=(
@@ -66,6 +89,8 @@ ipv6_range_negative=(
2001:db8:xx-2001:db8::99
2001:db:-
2001:db8::99-2001:db8::1
+ 2001::db8::1:1-2001::db8::1::10
+ 2001:db8:pqrs::1-2001:db8:uvwx::100
)
ipv6_single_positive=(
@@ -108,10 +133,11 @@ ipv4_host_negative=(
ipv6_host_positive=(
2001:db8:1::1/64
2001:db8:1::1/127
+ 2001:db8:1::/64 # All-zero IPv6 addresses are valid host addresses
)
ipv6_host_negative=(
- 2001:db8::/32
+ ::/0
)
string="garbage"
@@ -269,7 +295,31 @@ done
# --is-ipv6-net
# --is-ipv6-multicast
# --is-ipv6-link-local
+
# --is-valid-intf-address
+for address in \
+ ${ipv4_interface_address_positive[*]}
+do
+ assert_raises "$IPADDRCHECK --is-valid-intf-address $address" 0
+done
+
+for address in \
+ ${ipv4_interface_address_negative[*]}
+do
+ assert_raises "$IPADDRCHECK --is-valid-intf-address $address" 1
+done
+
+for address in \
+ ${ipv6_interface_address_positive[*]}
+do
+ assert_raises "$IPADDRCHECK --is-valid-intf-address $address" 0
+done
+
+for address in \
+ ${ipv6_interface_address_negative[*]}
+do
+ assert_raises "$IPADDRCHECK --is-valid-intf-address $address" 1
+done
# --is-ipv4-range
for range in \