Cách đặt địa chỉ IP từ chương trình C trong Linux?
Sử dụng lệnh strace và ifconfig tôi có thể đặt được IP, tuy nhiên nó khá rối và không hoàn chỉnh. Có cách nào để đặt địa chỉ IP từ chương trình C trong Linux mà nó đơn giản, hoàn chỉnh hơn không?
- Cách cài đặt phần mềm trên Linux: Giải thích về các định dạng gói
- Cách tìm địa chỉ IP của bạn trong Linux
- Cách bắt đầu sử dụng Linux
- Internet đến từ đâu? Tại sao bạn không thể làm ra Internet của riêng mình?
- Cách thiết lập máy chủ Git riêng trên Linux
Table of Contents
Bằng cách sử dụng lệnh strace và ifconfig, tôi thấy rằng tôi có thể đặt địa chỉ IP theo cách dưới đây. Tuy nhiên, tôi không hài lòng với giải pháp này: “inet_pton(AF_INET, “10.12.0.1”, ifr.ifr_addr.sa_data + 2);”. Làm cách nào để đặt địa chỉ IP từ chương trình C trong Linux?
1. Kết quả cài đặt địa chỉ IP của tôi
#include <sys/ioctl.h> #include <arpa/inet.h> #include <net/if.h> #include <string.h> int main(int argc, const char *argv[]) { struct ifreq ifr; const char * name = “eth1”; int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); strncpy(ifr.ifr_name, name, IFNAMSIZ); ifr.ifr_addr.sa_family = AF_INET; inet_pton(AF_INET, “10.12.0.1”, ifr.ifr_addr.sa_data + 2); ioctl(fd, SIOCSIFADDR, &ifr); inet_pton(AF_INET, “255.255.0.0”, ifr.ifr_addr.sa_data + 2); ioctl(fd, SIOCSIFNETMASK, &ifr); ioctl(fd, SIOCGIFFLAGS, &ifr); strncpy(ifr.ifr_name, name, IFNAMSIZ); ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); ioctl(fd, SIOCSIFFLAGS, &ifr); return 0; } |
2. Hỗ trợ giải pháp cài đặt địa chỉ IP từ chương trình C trong Linux
2.1. Phương pháp cài đặt địa chỉ IP từ chương trình C trong Linux 1
Để cài đặt địa chỉ IP từ chương trình C trong Linux, bạn có thể thử nghiệm cách này.
Cách “đúng” cho IPv4 mà không cần phép thuật +2:
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; inet_pton(AF_INET, “10.12.0.1”, &addr->sin_addr); |
Để sử dụng IPv6, hãy truyền nó tới sockaddr_in6
2.2. Phương pháp cài đặt địa chỉ IP từ chương trình C trong Linux 2
Tạo ra một bản sao của chương trình “ip” iproute2 (in / sbin / ip) với các tham số liên quan.
Giao diện ioctl nói chung là lỗi thời và không cho phép bạn định cấu hình tất cả các tham số (ví dụ: bí danh IP chưa được đặt tên).
Ngay cả những daemon như dhcpcd cần thay đổi địa chỉ IP, thường làm điều đó bằng cách tạo ra một chương trình bên ngoài… nó không giống như bạn sẽ làm điều đó thường xuyên.
=> Xem thêm: Tạo mã chung với cài đặt Macro trong C
2.3. Phương pháp cài đặt địa chỉ IP từ chương trình C trong Linux 3
Sử dụng:
set_ip(“eth0”, “192.168.181.128”, “192.168.181.1”); |
Quá trình và kết quả cài đặt địa chỉ IP từ chương trình C trong Linux như sau:
#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; } |
Như vậy, trên Linux bạn hoàn toàn có thể cài đặt địa chỉ IP từ chương trình C cho máy tính của mình. Hãy cẩn trọng khi lựa chọn phương pháp và thực hiện các thao tác, để tránh sai sót, nhầm lẫn.
Bài gốc: https://stackoverflow.com/questions/6652384/how-to-set-the-ip-address-from-c-in-linux
Nguyễn Vân Anh (Theo Stack Overflow)
Bình luận (0
)