2011-03-15 232 views
6

我想在Linux上使用IOCTL接口獲取和設置IP地址。 我成功地獲得並設置了它。當我設置IP地址時, ifconfig eth0顯示正確的IP地址,但系統斷開連接。 即系統不可連接。 這是我設定IP地址的代碼。請讓我知道如果我失去了一些東西。使用SIOCSIFADDR設置IP地址ioctl


    struct ifreq ifr; 
    in_addr_t in_addr; 
    struct sockaddr_in sin; 

    memset(&ifr, 0, sizeof(struct ifreq)); 
    memset(&sin, 0, sizeof(struct sockaddr_in)); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    sprintf(ifr.ifr_name, "eth0"); 
    in_addr = inet_addr("192.168.101.17"); 
    sin.sin_addr.s_addr = in_addr; 
    memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); 
    io = ioctl(sockfd, SIOCSIFADDR, (char *)&ifr); 

回答

10

這將適用於接口或別名。使用 「strace的」 驗證正確操作:

strace ./ifconfig 

socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5 
ioctl(5, SIOCSIFADDR, {ifr_name="eth0:8", ifr_addr={AF_INET, inet_addr("192.168.1.202")}}) = 0 
ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0:8", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0 
ioctl(5, SIOCSIFFLAGS, {ifr_name="eth0:8", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0 
close(5)        = 0 

完整的源代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stddef.h>    /* offsetof */ 
#include <net/if.h> 
#include <net/if.h> 
#include <linux/sockios.h> 
#include <netinet/in.h> 
#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 
#include <netpacket/packet.h> 
#include <net/ethernet.h> 
#else 
#include <asm/types.h> 
#include <linux/if_ether.h> 
#endif 

#define IFNAME "eth0:2" 
#define HOST "192.168.1.204" 
#define ifreq_offsetof(x) offsetof(struct ifreq, x) 

int main(int argc, char **argv) { 

     struct ifreq ifr; 
     struct sockaddr_in sai; 
     int sockfd;      /* socket fd we use to manipulate stuff with */ 
     int selector; 
     unsigned char mask; 

     char *p; 


     /* Create a channel to the NET kernel. */ 
     sockfd = socket(AF_INET, SOCK_DGRAM, 0); 

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

     memset(&sai, 0, sizeof(struct sockaddr)); 
     sai.sin_family = AF_INET; 
     sai.sin_port = 0; 

     sai.sin_addr.s_addr = inet_addr(HOST); 

     p = (char *) &sai; 
     memcpy((((char *)&ifr + ifreq_offsetof(ifr_addr))), 
         p, sizeof(struct sockaddr)); 

     ioctl(sockfd, SIOCSIFADDR, &ifr); 
     ioctl(sockfd, SIOCGIFFLAGS, &ifr); 

     ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 
     // ifr.ifr_flags &= ~selector; // unset something 

     ioctl(sockfd, SIOCSIFFLAGS, &ifr); 
     close(sockfd); 
     return 0; 
} 
5

也許你忘了設置界面了?

ioctl(sockfd, SIOCGIFFLAGS, &ifr); 
ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 
ioctl(sockfd, SIOCSIFFLAGS, &ifr);