2017-12-19 14 views
0

VLANインターフェイスのプロパティを作成および設定するコードを記述しました。私はIPアドレスを設定することができますが、私はゲートウェイのアドレスを設定し、デバイスフラグを読み取る際に問題に直面しています。コードを見て、間違っている可能性があることを示唆してください。IOCTLはそのようなデバイスを返しません

関数generic_ioctrlcallでエラーが発生します。

/** 
* 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; 

    if ((err = ioctl(sockfd, SIOCADDRT, &route)) < 0) { 
    fprintf(stderr, "ioctl: %s\n", (char *)flags); 
    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; 
} 
+0

エラーが発生した場合は、他のシステムコールの前に 'perrot()'を呼び出す必要があります。さもなければ、あなたは正しいメッセージをここで得ることができません。 – EJP

答えて

0

多くの問題があります。文字列へのポインタではなく、ioctlの2番目の引数が長い整数であることが原因です。

generic_ioctrlcall(sockfd, (u_long *)"SIOCGIFFLAGS", &ifr); 

SIOCGIFFLAGSの整数値へのポインタは、意図したとおりのものではありません。その他の問題:

(1)ioctlは2番目の引数として長い整数を使用するため、なぜ整数へのポインタを渡したかったのですか?整数を引数として渡すだけです。

(2)あなたは、整数へのポインタを渡す願いを行う場合、あなたはこのような何かをする必要があります:

u_long ioctl_arg = SIOCGIFFLAGS; 
generic_ioctrlcall(sockfd, &ioctl_arg, &ifr); 

(3)あなたは変換できません尖った-するまでの整数単純にそれをキャストすることで整数になります。ポインタを逆参照する必要があります。それは次のとおりです。

Change: 
    if (ioctl(sockfd, (long unsigned int)flags, &ifr) < 0) { 
to: 
    if (ioctl(sockfd, *flags, &ifr) < 0) { 

(4)ioctl失敗した場合、あなたは何が悪かったのかを把握するために、(、いっそのか、そのテキスト翻訳)障害が発生した後にerrnoをプリントアウトする必要があります。

if (ioctl(sockfd, *flags, &ifr) < 0) { 
    fprintf(stderr, "ioctl: flags %ld errno %d/%s\n", *flags, errno, strerror(errno)); 

ところで、あなたのgeneric_ioctlコールのerrnoは、ENODEV(このようなデバイスはありません)となる可能性は低い - タイトルに示されているとおりです。 errnoEINVALである可能性が高いようです。有効なioctl整数引数を形成するポインタ文字列の可能性は非常に低いからです。

+0

私は上記のすべての点を試しました。しかし、私はまだ同じエラーが表示されます。他の可能性はありますか? –

+0

また、set_routeでエラーが発生しました。無効な引数 –

関連する問題