如何使用inet_pton和struct ifreq从C程序设置ip地址

时间:2013-07-27 02:35:35

标签: c network-programming ioctl

我正在尝试从C程序设置网络接口的IP地址。我环顾四周,发现我可以使用ioctl()inet_pton()来做到这一点。我的问题是,我无法确定struct ifreq我应该在哪里存储转换后的地址。我不断收到ioctl() - invalid argument错误。

我特别关注了示例How to set the IP address from C in linux。这表示我们可以将ifr.ifr_addr投射到struct sockaddr_in。但是,在执行地址转换后,ioctl()失败并出现无效参数错误。

以下是代码:

280 void setip (int fd) {
281 
282     struct ifreq ifr;
283     struct sockaddr_in * addr;
284     int stat;
285 
286     strcpy(ifr.ifr_name, in.dev.device);          // in.dev.device = tun2
287     addr = (struct sockaddr_in *) &ifr.ifr_addr;
288 
289     addr->sin_family = AF_INET;
290 
291     stat = inet_pton(addr->sin_family, in.dev.ip_addr, &addr->sin_addr); // in.dev.ip_addr = "100.0.0.10"
292     if (stat == 0)
293         raise_error("inet_pton() - invalid ip");
294     if (stat == -1)
295         raise_error("inet_pton() - invalid family");
296 
297     if (stat == 1);
298     else
299         raise_error("inet_pton()");
300 
301     /* This is just to test if address conversion happened properly */
302     char buff[BUFF_SIZE];
303     char * foo;
304     foo = inet_ntop(AF_INET, &addr->sin_addr, buff, BUFF_SIZE);
305     if (foo == NULL)
306         raise_error("inet_ntop()");
307     else
308         printf("main = %s, addr = %s\n",in.dev.ip_addr, buff);
309     
310     if (ioctl(fd, SIOCSIFADDR, &ifr, sizeof(ifr)) == -1)
311         raise_error("ioctl() - SIOCSIFADDR");
312 }

编辑:raise_error功能是:

void raise_error (const char * msg) {

    perror(msg);
    exit(1);
}

我得到的输出是:

main = 100.0.0.10, addr = 100.0.0.10
ioctl() - SIOCSIFADDR: Invalid argument

我猜测转换后的地址会被放置在struct ifreq的错误位置,但我无法弄清楚应该放置的确切位置。 我也尝试使用ifr.ifr_addr进行地址转换,但这也无效。

编辑:我正在以root身份运行该程序。

任何帮助将不胜感激。如果我需要发布更多代码或调试输出,请告诉我。

由于

2 个答案:

答案 0 :(得分:0)

我认为您发现了错误的错误消息,因为raise_error会在perror之前调用另一个函数,并且您看到该调用的结果不是ioctl。你应该在想要测试的功能之后立即调用perror。我尝试了你的代码,ioctl()失败了" ioctl():Permission denied"你需要以root身份运行它(还要注意你不需要传递ifreq的大小)

答案 1 :(得分:0)

根据mux的评论,我在eth0上尝试了相同的代码。因此我认为tun设备是不同的,我们不能对它们使用相同的ioctl()调用。 因此,使用inet_ptonstruct ifreqioctl()设置IP地址的方式是正确的,但它不适用于tun设备。