As per mux's comment, I tried the same code on eth0
which worked. Hence I guess tun devices are different and we can't use same ioctl()
call for them.
So the way of using inet_pton
and struct ifreq
for ioctl()
for setting ip address is right, but it doesn't work on tun devices.
How to use inet_pton and struct ifreq for setting up ip address from C program
-
04-06-2022 - |
Pregunta
I am trying to set ip address of a network interface from a C program. I looked around and found out that I can do it using ioctl()
and inet_pton()
. My problem is, I am not able to figure out where in struct ifreq
am I supposed to store the converted address. I keep on getting ioctl() - invalid argument
error.
I have particularly looked at the example How to set the IP address from C in linux. This says that we can cast ifr.ifr_addr
to struct sockaddr_in
. However, after doing the address conversion, ioctl()
fails with invalid argument error.
Following is the code:
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 }
Edit: raise_error
function is:
void raise_error (const char * msg) {
perror(msg);
exit(1);
}
Output I get is:
main = 100.0.0.10, addr = 100.0.0.10
ioctl() - SIOCSIFADDR: Invalid argument
I am guessing the converted the address is getting placed at wrong location in struct ifreq
, but I am not able to figure out exactly what location it should be placed.
I also tried using ifr.ifr_addr
for address conversion but that didn't work either.
Edit: I am running the program as root.
Any help will be much appreciated. Please let me know if I need to post more code or debugging output.
Thanks
Solución 2
Otros consejos
I think you're seeing the wrong error message because raise_error
makes calls another function before perror
and you're seeing the result of that call not ioctl
.. you should always call perror
right after the function you want to test. I tried your code and ioctl()
fails with "ioctl(): Permission denied" you need to run that as root (also note that you don't need to pass the size of ifreq
)