Linux Network Programming

From Teknologisk videncenter
Revision as of 08:18, 1 December 2023 by Heth (talk | contribs) (Python)
Jump to: navigation, search

Find IP address of an interface

c

#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <getopt.h>
int main(int argc, char *argv[]) {
 int fd;
 struct ifreq ifr;
  if (argc != 2) {
          fprintf(stderr,"Usage: %s interface\n",argv[0]);
          return(1);
  }
 fd = socket(AF_INET, SOCK_DGRAM, 0);
 /* I want to get an IPv4 IP address */
 ifr.ifr_addr.sa_family = AF_INET;
 /* I want IP address attached to interfacename in argv[1] */
 strncpy(ifr.ifr_name, argv[1], IFNAMSIZ-1);
 ioctl(fd, SIOCGIFADDR, &ifr);
 close(fd);
 /* display result */
 printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
 return 0;
}

Python - hangs if interface link down

Install netifaces either as apt module python3-netifaces or pip module netifaces

#!/usr/bin/env python3
# https://gist.github.com/EONRaider/3b7a8ca433538dc52b09099c0ea92745
__author__ = 'EONRaider, keybase.io/eonraider'

import fcntl
import socket
import struct

try:
    from netifaces import AF_INET, ifaddresses
except ModuleNotFoundError as e:
    raise SystemExit(f"Requires {e.name} module. Run 'pip install {e.name}' "
                     f"and try again.")


def get_ip_linux(interface: str) -> str:
    """
    Uses the Linux SIOCGIFADDR ioctl to find the IP address associated
    with a network interface, given the name of that interface, e.g.
    "eth0". Only works on GNU/Linux distributions.
    Source: https://bit.ly/3dROGBN
    Returns:
        The IP address in quad-dotted notation of four decimal integers.
    """

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    packed_iface = struct.pack('256s', interface.encode('utf_8'))
    packed_addr = fcntl.ioctl(sock.fileno(), 0x8915, packed_iface)[20:24]
    return socket.inet_ntoa(packed_addr)


def get_ip_cross(interface: str) -> str:
    """
    Cross-platform solution that should work under Linux, macOS and
    Windows.
    """

    return ifaddresses(interface)[AF_INET][0]['addr']

print(get_ip_linux( "eth0"))  #Testing module
print(get_ip_cross( "eth0"))  #Testing module