liboping: An Open Source Library Based on C

liboping is a library written in C for generating ICMP ECHO_REQUEST (i.e., ping packets). It supports parallel probing of multiple hosts and can transparently handle both IPv4 and IPv6 addresses. This library is designed with a object-oriented interface, making it very useful in network monitoring applications or other scenarios that require frequent ping operations.

Here are some of the main features of liboping:

Feature Description
Parallel Multi-host Ping Can send ping requests to multiple hosts simultaneously, improving efficiency.
Dual Stack Support Supports both IPv4 and IPv6 transparently.
Object-oriented Interface Provides an easy-to-use object-oriented interface.
Command Line Tools Included Includes oping and an ncurses-based noping tool.

Installing liboping

On Debian-based systems, you can install liboping using apt:

# Install shared library
sudo apt install liboping0

# Install development files (header files and static libraries) for compiling your own programs
sudo apt install liboping-dev

On Fedora systems, you can use dnf to install:

sudo dnf install liboping

Permission Settings: To allow liboping to create ICMP sockets without root privileges, you typically need to set the cap_net_raw capability on Linux:

sudo setcap cap_net_raw+ep /path/to/your/compiled/binary

On other UNIX-like systems, the traditional set-UID root method may be used.

Basic Usage

1. Initialization and Cleanup

When using the liboping library, you first need to create a ping object, and it should be destroyed after use to free resources.

#include <oping.h>

pingobj_t *ping = NULL;
ping = ping_construct();
if (ping == NULL) {
    // Handle construction failure
}

// ... Use the ping object for operations ...

ping_destroy(ping);

2. Adding Hosts

Use the ping_host_add function to add hosts to the ping object. Hostnames can be domain names, IPv4, or IPv6 addresses.

int ret;
ret = ping_host_add(ping, "example.com");
if (ret != 0) {
    // Handle host addition failure, e.g., use ping_get_error(ping) to get error information
}

ret = ping_host_add(ping, "192.0.2.1");
ret = ping_host_add(ping, "2001:db8::1");

3. Sending Requests and Getting Results

Use the ping_send function to send ICMP requests to all added hosts, and then iterate through the host list to get each host’s latency information.

// Send ping requests
if (ping_send(ping) < 0) {
    // Handle send failure
}

// Iterate through hosts and get information
ping_iter_t *iter;
for (iter = ping_iterator_get(ping); iter != NULL; iter = ping_iterator_next(iter)) {
    char host[128];
    double latency;
    size_t len = sizeof(host);

    // Get hostname
    if (ping_iterator_get_info(iter, PING_INFO_HOSTNAME, host, &len) == 0) {
        printf("Host: %s\n", host);
    }

    // Get latency (in seconds)
    len = sizeof(latency);
    if (ping_iterator_get_info(iter, PING_INFO_LATENCY, &latency, &len) == 0) {
        printf("Latency: %.2f ms\n", latency * 1000.0); // Convert to milliseconds
    }
}

Complete Code Example

Below is a complete C program example that demonstrates how to use liboping to ping multiple hosts.

#include <stdio.h>
#include <oping.h>

int main(void) {
    pingobj_t *ping;
    int ret;
    const char *hosts[] = {"google.com", "github.com", "example.com"};
    int num_hosts = 3;

    // 1. Initialize ping object
    ping = ping_construct();
    if (ping == NULL) {
        fprintf(stderr, "Error: Unable to create ping object.\n");
        return 1;
    }

    // 2. Add hosts
    for (int i = 0; i < num_hosts; i++) {
        ret = ping_host_add(ping, hosts[i]);
        if (ret != 0) {
            fprintf(stderr, "Error: Unable to add host %s: %s\n",
                    hosts[i], ping_get_error(ping));
            // Note: Here we continue execution instead of returning directly
        }
    }

    // 3. Send ping requests
    if (ping_send(ping) < 0) {
        fprintf(stderr, "Error: Failed to send ping: %s\n",
                ping_get_error(ping));
        ping_destroy(ping);
        return 1;
    }

    // 4. Iterate and print results
    ping_iter_t *iter;
    printf("Ping Results:\n");
    printf("-------------\n");

    for (iter = ping_iterator_get(ping); iter != NULL; iter = ping_iterator_next(iter)) {
        char host[128];
        double latency;
        size_t len = sizeof(host);

        if (ping_iterator_get_info(iter, PING_INFO_HOSTNAME, host, &len) == 0) {
            len = sizeof(latency);
            if (ping_iterator_get_info(iter, PING_INFO_LATENCY, &latency, &len) == 0) {
                printf("%-15s : %.2f ms\n", host, latency * 1000.0);
            } else {
                printf("%-15s : (No response or error)\n", host);
            }
        }
    }

    // 5. Cleanup
    ping_destroy(ping);
    return 0;
}

Compile this program using gcc:

gcc -o ping_example ping_example.c -loping

Error Handling

When using liboping, proper error handling is very important. Many functions in the library return values indicating success or error. You can use the ping_get_error function to get a human-readable error description.

ret = ping_host_add(ping, "invalid-hostname-!!");
if (ret != 0) {
    fprintf(stderr, "Error adding host: %s\n", ping_get_error(ping));
}

Command Line Tools

liboping also comes with some command line tools that make it easy to use its functionality directly:

  • oping: A command similar to the traditional ping tool, but supports pinging multiple hosts simultaneously.

    oping google.com github.com
  • noping: A full-screen tool based on ncurses that can display ping statistics in real-time and highlight abnormal round-trip times.

    noping google.com

Conclusion

liboping is a powerful and easy-to-use library, ideal for developers who need to integrate ping functionality into their applications or for tasks that require parallel monitoring of the network status of many hosts. Its object-oriented design and transparent support for IPv4/IPv6 make it very practical in modern network environments.

Leave a Comment