GNU/Linux >> LINUX-Kenntnisse >  >> Linux

So stellen Sie die IP-Adresse von C in Linux ein

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>           // close()
#include <string.h>           // strcpy, memset(), and memcpy()

#include <netdb.h>            // struct addrinfo
#include <sys/types.h>        // needed for socket(), uint8_t, uint16_t
#include <sys/socket.h>       // needed for socket()
#include <netinet/in.h>       // IPPROTO_RAW, INET_ADDRSTRLEN
#include <netinet/ip.h>       // IP_MAXPACKET (which is 65535)
#include <arpa/inet.h>        // inet_pton() and inet_ntop()
#include <sys/ioctl.h>        // macro ioctl is defined
#include <bits/ioctls.h>      // defines values for argument "request" of ioctl.
#include <net/if.h>           // struct ifreq
#include <linux/if_ether.h>   // ETH_P_ARP = 0x0806
#include <linux/if_packet.h>  // struct sockaddr_ll (see man 7 packet)
#include <net/ethernet.h>

#include <errno.h>            // errno, perror()

#include <netinet/in.h>
#include <net/route.h>    


 /**
    * Create socket function
    */
    int create_socket() {

      int sockfd = 0;

      sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      if(sockfd == -1){
        fprintf(stderr, "Could not get socket.\n");
        return -1;
      }

      return sockfd;

    }

    /**
    * Generic ioctrlcall to reduce code size
    */
    int generic_ioctrlcall(int sockfd, u_long *flags, struct ifreq *ifr) {

      if (ioctl(sockfd, (long unsigned int)flags, &ifr) < 0) {
        fprintf(stderr, "ioctl: %s\n", (char *)flags);
        return -1;
      }
      return 1;
    }

    /**
    * Set route with metric 100
    */
    int set_route(int sockfd, char *gateway_addr,  struct sockaddr_in *addr) {
      struct rtentry route;
      int err = 0;
      memset(&route, 0, sizeof(route));
      addr = (struct sockaddr_in*) &route.rt_gateway;
      addr->sin_family = AF_INET;
      addr->sin_addr.s_addr = inet_addr(gateway_addr);
      addr = (struct sockaddr_in*) &route.rt_dst;
      addr->sin_family = AF_INET;
      addr->sin_addr.s_addr = inet_addr("0.0.0.0");
      addr = (struct sockaddr_in*) &route.rt_genmask;
      addr->sin_family = AF_INET;
      addr->sin_addr.s_addr = inet_addr("0.0.0.0");
      route.rt_flags = RTF_UP | RTF_GATEWAY;
      route.rt_metric = 100;
      err = ioctl(sockfd, SIOCADDRT, &route);
      if ((err) < 0) {
        fprintf(stderr, "ioctl: %s\n",  "mahdi MOAHMMADI Error");
        return -1;
      }
      return 1;
    }

    /**
    * Set ip function
    */
    int set_ip(char *iface_name, char *ip_addr, char *gateway_addr)
    {
      if(!iface_name)
        return -1;
      struct ifreq ifr;
      struct sockaddr_in sin;
      int sockfd = create_socket();

      sin.sin_family = AF_INET;

      // Convert IP from numbers and dots to binary notation
      inet_aton(ip_addr,&sin.sin_addr.s_addr);

      /* get interface name */
      strncpy(ifr.ifr_name, iface_name, IFNAMSIZ);

      /* Read interface flags */
      generic_ioctrlcall(sockfd, (u_long *)"SIOCGIFFLAGS", &ifr);
      /*
      * Expected in <net/if.h> according to
      * "UNIX Network Programming".
      */
      #ifdef ifr_flags
      # define IRFFLAGS       ifr_flags
      #else   /* Present on kFreeBSD */
      # define IRFFLAGS       ifr_flagshigh
      #endif
      // If interface is down, bring it up
      if (ifr.IRFFLAGS | ~(IFF_UP)) {
        ifr.IRFFLAGS |= IFF_UP;
        generic_ioctrlcall(sockfd, (u_long *)"SIOCSIFFLAGS", &ifr);
      }
      // Set route
      set_route(sockfd, gateway_addr    ,  &sin);
      memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); 
      // Set interface address
      if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
        fprintf(stderr, "Cannot set IP address. ");
        perror(ifr.ifr_name);
        return -1;
      }             
      #undef IRFFLAGS 

      return 0;
    }

Verwendung:

set_ip("eth0", "192.168.181.128", "192.168.181.1");

Der "richtige" Weg, dies zu tun, besteht darin, eine Kopie des iproute2-Programms "ip" (in /sbin/ip ) mit relevanten Parametern zu erzeugen.

Die ioctl-Schnittstelle ist im Allgemeinen veraltet und erlaubt Ihnen nicht, alle Parameter zu konfigurieren (z. B. unbenannte IP-Aliase).

Sogar Daemons wie dhcpcd, die die IP-Adresse ändern müssen, tun dies normalerweise, indem sie ein externes Programm starten... es ist nicht so, dass Sie das sehr oft tun werden.


Der "richtige" Weg für IPv4 ohne Magic +2:

struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
inet_pton(AF_INET, "10.12.0.1", &addr->sin_addr);

Um IPv6 zu verwenden, wandeln Sie es in sockaddr_in6 um


Hallo:In der Funktion set_ip hat es mir einen Fehler gegeben. Ich musste von :

wechseln

inet_aton(ip_addr, &sin.sin_addr.s_addr);

zu

inet_aton(ip_addr, &sin.sin_addr);

und hat gut funktioniert.


Linux
  1. So durchsuchen Sie das Web vom Terminal unter Linux

  2. Linux – Wie stellt man die Prozessoraffinität eines Prozesses unter Linux ein?

  3. Wie setze ich den Namen eines Threads in Linux pthreads?

  4. Wie erkennt man das Starten von Programmen unter Linux?

  5. Wie bekomme ich den Pfad zur aktuellen Datei (pwd) in Linux von C?

So legen Sie eine statische IP-Adresse in CentOS Linux fest

So legen Sie eine statische IP-Adresse in Rocky Linux fest

So ändern Sie die IP-Adresse unter Linux

So richten Sie den RabbitMQ-Cluster unter Ubuntu/Debian Linux ein

So richten Sie die UFW-Firewall unter Linux ein

So verbinden Sie sich vom Terminal in Ubuntu Linux mit WLAN