A Zig library for interacting with Linux netlink sockets, providing a type-safe interface for network configuration and monitoring.
- Core Netlink Socket Support: Low-level netlink socket operations
- Route Netlink Protocol: Query network interfaces, addresses, and routes
- Network Namespace Management: Create, delete, enter, and list network namespaces
- Message Parsing: Parse netlink messages and attributes
- Error Handling: Comprehensive error handling with custom error types
- Memory Safety: RAII-style resource management
src/
├── root.zig # Core netlink functionality
├── route.zig # Route netlink protocol implementation
├── netns.zig # Network namespace management
└── main.zig # Example application
The main socket interface for netlink communication:
const socket = try NetlinkSocket.init(NetlinkFamily.route, 0);
defer socket.close();
try socket.bind();High-level interface for network information:
const route_socket = try RouteSocket.init(0);
defer route_socket.close();
// Get network interfaces
const links = try route_socket.getLinks(allocator);
defer {
for (links.items) |*link| {
link.deinit(allocator);
}
links.deinit();
}
// Get addresses
const addresses = try route_socket.getAddresses(allocator);
defer {
for (addresses.items) |*addr| {
addr.deinit(allocator);
}
addresses.deinit();
}
// Get routes
const routes = try route_socket.getRoutes(allocator);
defer {
for (routes.items) |*route| {
route.deinit(allocator);
}
routes.deinit();
}
// List routes with formatting
try route_socket.listRoutes(allocator, stdout);
// List routes with filtering
const filter = RouteFilter.init()
.withFamily(std.posix.AF.INET)
.withGateway(true);
try route_socket.listRoutesFiltered(allocator, stdout, filter);zig build # Build library and example
zig build test # Run tests
zig build run # Run example (requires root)The library provides both low-level netlink socket operations and high-level protocol-specific interfaces.
The included example demonstrates querying network interfaces, addresses, and routes:
sudo ./zig-out/bin/znetlinkNote: Netlink sockets require root privileges for most operations.
- NETLINK_ROUTE: Network interface and routing information
- NETLINK_GENERIC: Generic netlink protocol
- NETLINK_AUDIT: Audit subsystem
- NETLINK_NETFILTER: Netfilter subsystem
- And many more...
The library defines comprehensive error types:
pub const NetlinkError = error{
InvalidMessage,
InvalidMessageType,
InvalidMessageLength,
SocketError,
BindError,
SendError,
ReceiveError,
InsufficientBuffer,
InvalidPid,
InvalidSeq,
PermissionDenied,
AddressNotAvailable,
NoSuchDevice,
OperationNotSupported,
NamespaceNotFound,
NamespaceSwitchFailed,
};Network interface information:
- Interface index and name
- MTU and flags
- Hardware addresses
Network address information:
- Address family and prefix length
- Interface index and scope
- Address data
Routing table information:
- Route family and table
- Destination and gateway
- Priority and flags
Route filtering configuration:
- Family (IPv4/IPv6)
- Table and protocol
- Interface and gateway presence
Network namespace management:
- Name and filesystem path
- Creation and deletion operations
- Namespace switching capabilities
- Existence checking
The library provides convenient functions for listing and filtering routes:
// List all routes with formatted output
try route_socket.listRoutes(allocator, writer);
// Filter routes by various criteria
const filter = RouteFilter.init()
.withFamily(std.posix.AF.INET) // IPv4 only
.withTable(254) // Main routing table
.withProtocol(2) // Kernel routes
.withInterface(1) // Specific interface
.withGateway(true); // Routes with gateway
try route_socket.listRoutesFiltered(allocator, writer, filter);Manage Linux network namespaces for network isolation:
const netns = @import("netns.zig");
// Create a new network namespace
var network_ns = try netns.NetworkNamespace.init(allocator, "my-netns");
defer network_ns.deinit();
// Create the namespace
try network_ns.create();
// Check if namespace exists
if (network_ns.exists()) {
std.debug.print("Namespace exists!\n", .{});
}
// Enter the namespace
try network_ns.enter();
// Delete the namespace when done
try network_ns.delete();
// List all available namespaces
var namespaces = try netns.listNamespaces(allocator);
defer netns.cleanupNamespaceList(allocator, &namespaces);
for (namespaces.items) |ns_name| {
std.debug.print("Found namespace: {s}\n", .{ns_name});
}- withFamily(family): Filter by address family (IPv4/IPv6)
- withTable(table): Filter by routing table
- withProtocol(protocol): Filter by routing protocol
- withInterface(interface): Filter by output interface
- withGateway(has_gateway): Filter by gateway presence
Network namespaces provide network isolation, allowing multiple independent network stacks on a single Linux system. The library provides comprehensive namespace management:
const netns = @import("netns.zig");
// Initialize a namespace handler
var ns = try netns.NetworkNamespace.init(allocator, "test-ns");
defer ns.deinit();
// Create namespace (requires root privileges)
try ns.create();
// Check existence
const exists = ns.exists();
// Enter namespace (affects current process)
try ns.enter();
// Clean up when done
try ns.delete();// Get all available namespaces
var namespaces = try netns.listNamespaces(allocator);
defer netns.cleanupNamespaceList(allocator, &namespaces);
for (namespaces.items) |name| {
std.debug.print("Namespace: {s}\n", .{name});
}- Root Privileges: Network namespace operations require root privileges
- Process Context: Entering a namespace affects the current process and its children
- Persistence: Created namespaces persist in
/var/run/netns/until explicitly deleted - Isolation: Each namespace has its own network interfaces, routing tables, and firewall rules
This project is available under the MIT License.