Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как установить новый ip-адрес интерфейса программно?
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Linux
Atridies
Здравствуйте!

Есть задача - установить новый ip-адрес интерфейса из работающей программы. Из консоли делается просто: "ifconfig eth0 inet 192.168.1.10".
Попробовал аналогично вызвать ifconfig из пользовательской программы:

Код
int main(int argc, char* argv[], char* enpv[])
{
    pid_t num;
    int status;
    num = fork();
    if(num == 0)
    {
        execl("ifconfig", "eth0", "inet", "10.0.2.16");
    }
    else
    {
        wait(&status);
        printf("ending");
    }
    return 0;
}


Запускаю, проверяю - адрес не меняется. Что я делают не так? Запускаю эту программу под рутом.
Менять адрес через перезапись в файлах конфигурации - не хочу, т.к. у разных дистрибутивов эти файлы лежат в разных папках.

Заранее спасибо.
krux
зависит от того, чем управляются интерфейсы в системе в принципе. у разных дистрибутивов разные подходы, поэтому придётся адаптироваться.
Если в системе установлен пакет NetworkManager, то надо работать через него, вернее с ним через D-Bus. Потому как он может в любой момент изменить то что вы там наделали вручную без его ведома.
Если через скрипты, то либо дорабатывать скрипты, либо убирать их совсем и делать все дела самому.

в крайнем случае:
https://www.kernel.org/pub/linux/utils/net/...2-3.17.0.tar.gz
смотреть исходник ip/ipaddr.c
Lagman
смотрите как надо вызывать execl, там что то как то не все так просто т.к. при вызове main(int argc, char *argv[])
Цитата
argv[0] указывает на первую символьную строку, которой всегда является имя программы; argv[1] указывает на первый аргумент и так далее.

а в execl присутвует path.
psL
Код
struct sockaddr_in sin;
int s;

s = socket(AF_INET,SOCK_DGRAM,0); //temporary socket

memset(&ifr, 0, sizeof(struct ifreq));
memset(&sin, 0, sizeof(struct sockaddr));
strncpy(ifr.ifr_name, iface, IF_NAMESIZE-1);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("192.168.0.123");

memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));

if(ioctl(s, SIOCSIFADDR, &ifr)< 0){ //set IP-Adress and check for errors
    close(s);
    perror("ioctl()");
    exit(1);
}

как-то так. Но это до первой перезагрузки, если init запускает стартовые скрипты.
alx2
Добавлю, что установить (изменить) адрес интерфейса также можно через ioctl функцию SIOCSIFADDR.
Atridies
Спасибо за ответы. Несколько дней понадобилось, чтобы разобраться с ioctl.

Код - как у psL:

Код
s = socket(AF_INET,SOCK_DGRAM,0); //temporary socket

memset(&ifr, 0, sizeof(struct ifreq));
memset(&sin, 0, sizeof(struct sockaddr));
strncpy(ifr.ifr_name, "eth0", IF_NAMESIZE-1);
sin.sin_family = AF_INET;

sin.sin_addr.s_addr = inet_addr("192.168.0.123");

memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));

if(ioctl(s, SIOCSIFADDR, &ifr)< 0) //set IP-Adress and check for errors
{ /*close(s);*/ }
close(s);



Но проблема в том, что опять ничего не работает. На машине Ubuntu все отлично работает: адрес меняется. Когда запускаю этот код в Angstrom - нифига не пашет. Вот что пишет ifconfig -a.

Код
eth0      Link encap:Ethernet  HWaddr BC:6A:29:57:11:80
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth1      Link encap:Ethernet  HWaddr BC:6A:29:57:11:81
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


Запускаю из-под рута. Может разрешений не хватает ? Но ведь из sh - все задается.
Tanya
Цитата(Atridies @ Dec 5 2014, 18:39) *
Запускаю из-под рута. Может разрешений не хватает ? Но ведь из sh - все задается.

А в программу вставить system (/path_to_script/changeIP.sh)?
Или нужно предварительно вызвать процессор? Я в linux'e не разбираюсь...
Atridies
Команда:
Код
system("ifconfig eth0 10.0.5.20");

действительно позволила установить новый ip. Но во-первых: это странно, а во-вторых: мне кажется - это неправильно - использовать sh для работы прикладного ПО.

Если ничего не получится - буду так делать. Но может быть - есть еще какие-нибудь идеи: почему не работает ioctl?
Tanya
Цитата(Atridies @ Dec 5 2014, 20:21) *
Но во-первых: это странно, а во-вторых: мне кажется - это неправильно - использовать sh для работы прикладного ПО.

Не хотите использовать стандартные подпрограммы (ifconfig) - пишите сами. Только, возможно это придется делать каждый раз для новой системы. А зачем тогда шелловский процессор нужен?
А если бы захотелось письмом извещать, - тоже бы стали для этого свою программу писать?
Jury093
Цитата(Atridies @ Dec 5 2014, 20:21) *
действительно позволила установить новый ip. Но во-первых: это странно, а во-вторых: мне кажется - это неправильно - использовать sh для работы прикладного ПО.
Если ничего не получится - буду так делать. Но может быть - есть еще какие-нибудь идеи: почему не работает ioctl?

что мешало еще 30 ноября выудить пакет, содержащий исходники ifconfig (или другой утилиты, умеющей менять адрес) из любимого дистрибутива, и посмотреть как там это сделано?
зачем изобретать то, что давно надежно и качественно написано до вас?
это однокристаллочникам приходится барахтаться, прилаживая ДВС к изобретенному велосипеду..
alx2
Цитата(Atridies @ Dec 5 2014, 21:39) *
Но проблема в том, что опять ничего не работает.
Запускаю из-под рута. Может разрешений не хватает ?

В Вашем коде два системных вызова. Очевидно, один из них завершается ошибкой. Так обработайте должным образом эту ошибку и выведите ее на экран. Тогда и не придется гадать о том, чего программе не хватает. Хотя бы как-то так:
Код
s = socket(...);
if(s < 0) {
  perror("socket");
  exit(1);
}
...
if(ioctl(...) < 0)
  perror("ioctl");

psL
Цитата(Atridies @ Dec 5 2014, 18:39) *
Но проблема в том, что опять ничего не работает.

Посмотрите:
Код
strace ifconfig eth0


Возможно нужно поднять интерфейс:
Код
        ioctl(s, SIOCGIFFLAGS, &ifr);
        // флаги интерфейса
        ifr.ifr_flags |= IFF_UP | IFF_RUNNING;

        ioctl(s, SIOCSIFFLAGS, &ifr);
        close(s);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.