Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/34: Рейтинг темы: голосов - 34, средняя оценка - 4.59
0 / 0 / 0
Регистрация: 20.12.2009
Сообщений: 15

Выполнение и считывание popen команды ipfw в FreeBSD

21.03.2011, 02:17. Показов 9553. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!

задачка такая:

есть система FreeBSD, на ней фаервол ipfw. Нужно взять ип адрес, и проверить есть ли он в таблице правил, если да то удалить, если нет то пройти далее;

написал:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sprintf(ip_buff, "%s", "ipfw table 1 list | grep 192.168.1.1");
ipfw = popen(ip_buff, "r");
if (ipfw == NULL)
{
puts("error");
}
fscanf(ipfw,"%s",ip_buff);
if(ip_buff != NULL)
{
                  sprintf(buff, "%s","ipfw table 1 delete 192.168.1.1");
                  ipfw = popen(buff, "r"); if (ipfw == NULL) puts("error");
                  pclose(ipfw);
 
}
так вот если ип совпадает и она уже есть в таблице, то все хорошо, в буфер записывается ип и по правилу далее делает делит. Если же ее там нет, то возвращает не пустую строку как бы хотелось, а в буфере остаеться ipfw table 1 list | grep 192.168.1.1

как исправить? не юзать grep? он не возвращает пустую строку и не зануляеться буфер?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.03.2011, 02:17
Ответы с готовыми решениями:

настройка ipfw на freebsd 8.0
Расскажу сначала о роутере (сервере): на нём стоят 3 сетевухи: 2 смотрят в 2 разные локалки и 1 смотрит в сторону провайдера, т.е. роутер...

Freebsd NATD IPFW
Подскажите, кто может, как настроить доступ в интернет LAN сети через роутер FreeBsd 8.0 Такой расклад: два сетевых адаптера, ниже...

Настройка прозрачного прокси (squid, ipfw) на FreeBSD 9.2
Всем доброго времени суток. Кеширующий прокси-сервера (squid) настроил, все работает нормально. Теперь хочу настроить его как прозрачный...

18
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
21.03.2011, 04:17
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

Bash
1
if inlist 192.168.1.1; then echo yes; else echo no; fi
Bash
1
2
3
inlist() {
    return ipfw table 1 list | grep $1 &>/dev/null
}
Добавлено через 5 минут
man popen
Code
1
2
       The pclose() function waits for the associated process to  terminate  and  returns
       the exit status of the command as returned by wait4(2).
это проверил, там возвращается что-то вроде 0x100

C
1
2
3
4
5
6
7
8
9
10
11
12
 
#include <stdio.h>
 
int main(void)
{
    FILE *ifp = popen("echo xy | grep y", "r");
    
    if (ifp)
        printf("%x\n", pclose(ifp));
    
    return 0;
}
Code
1
2
3
4
5
6
7
[guest@localhost tests]$ gcc -Wall t.c -o t
[guest@localhost tests]$ ./t
100
[guest@localhost tests]$ gcc -Wall t.c -o t
[guest@localhost tests]$ ./t
8d00
[guest@localhost tests]$
это для echo x | grep y и echo xy | grep y
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
21.03.2011, 09:07
Цитата Сообщение от accept Посмотреть сообщение
это для echo x | grep y и echo xy | grep y
Оба ваших теста показывают что все хорошо и pclose() вернул 0. т.к. статус 8битный...

to ТС:
как вариант, запускайте grep -q и проверяйте статус.

А что будет если в таблице есть 1.2.3.0/24 а проверить нужно 1.2.3.4?
С ipfw работать не приходилось, но по аналогии с pf там скорее всего есть свой развесистый API через get/set sockopt() для манипуляций правилами и таблицами.
1
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
21.03.2011, 09:53
Цитата Сообщение от g_u_e_s_t
Оба ваших теста показывают что все хорошо и pclose() вернул 0. т.к. статус 8битный...
C
1
2
3
4
5
6
7
8
9
10
11
12
 
#include <stdio.h>
 
int main(void)
{
    FILE *ifp = popen("echo x", "r");
    
    if (ifp)
        printf("%x\n", pclose(ifp));
    
    return 0;
}
Code
1
2
3
4
[guest@localhost tests]$ gcc -Wall t.c -o t
[guest@localhost tests]$ ./t
d
[guest@localhost tests]$
это что-то другое
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
21.03.2011, 10:29
В смысле другое?
Статус реально 8битный - что именно лежит в старшем байте я признаться не в курсе, да и врядли это как-то стандартизировано.

Последний пример не корректен.
Точнее корректен, но показывает именно ошибку. Нет времени копать доки или исходники, но готов держать пари: 0xd у sh наверняка not found. Попробуйте запустить /bin/echo или передать ключ -с шеллу
1
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
21.03.2011, 10:54
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

Цитата Сообщение от g_u_e_s_t
Точнее корректен, но показывает именно ошибку.
какую ошибку ?

C
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
int main(void)
{
    FILE *ifp = popen("/bin/echo x", "r");
    
    if (ifp)
        printf("%x\n", pclose(ifp));
    
    return 0;
}
Code
1
2
3
4
[guest@localhost tests]$ gcc -Wall t.c -o t
[guest@localhost tests]$ ./t
d
[guest@localhost tests]$
Цитата Сообщение от g_u_e_s_t
но готов держать пари
не, в системе-то всё работает

Добавлено через 2 минуты
Code
1
2
3
4
5
6
7
8
9
[guest@localhost ~]$ sh
sh-4.1$ echo $PATH
/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin/:/usr/games:/usr/lib/qt4/bin:/home/guest/bin:/bin:/sbin:/usr/bin:/usr/sbin
sh-4.1$ PATH=''
sh-4.1$ echo $PATH
 
sh-4.1$ echo x
x
sh-4.1$
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
21.03.2011, 10:55
Значит не угадал я)

А если по уму сделать через макросы?
#include <sys/wait.h>

status = pclose(ifp);
if (status != -1 && WIFEXITED(status))
printf("%x\n", WEXITSTATUS(status));
1
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
21.03.2011, 11:07
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <sys/wait.h>
 
int main(void)
{
    FILE *ifp = popen("echo x | grep y", "r");
        
    if (ifp) {
        printf("in\n");
        int status = pclose(ifp);
        if (status != -1 && WIFEXITED(status))
            printf("%x\n", WEXITSTATUS(status));
    }
    return 0;
}
Code
1
2
3
4
[guest@localhost tests]$ ./t
in
1
[guest@localhost tests]$
Добавлено через 5 минут
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <sys/wait.h>
 
int main(void)
{
    FILE *ifp = popen("echo x", "r");
        
    if (ifp) {
        printf("in\n");
        int status = pclose(ifp);
        if (status != -1 && WIFEXITED(status))
            printf("%x\n", WEXITSTATUS(status));
    }
    return 0;
}
Code
1
2
3
4
[guest@localhost tests]$ gcc -Wall t.c -o t
[guest@localhost tests]$ ./t
in
[guest@localhost tests]$
man wait3
Code
1
2
       WIFEXITED(status)
              не ноль, если потомок нормально завершился.
на /bin/echo то же самое

printf("status: %d\n", WIFEXITED(status)); даёт ноль на /bin/echo x
1
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
21.03.2011, 11:26
"Нормально завершился" это всего лишь выход через exit(3) или _exit(2). В смысле от кода возврата никак не зависит.
2
0 / 0 / 0
Регистрация: 20.12.2009
Сообщений: 15
21.03.2011, 15:10  [ТС]
спасибо за советы

следуя примеру, просто проверил статус, если grep находит ип, то статус равен нулю, если же нет, то статус равен чему-то другому, восновном там константа 0х100

вроде получился рабочий код, може добавить еще какие-то проверки?

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* тут цыкл который берет ип с базы, результат в row[1] */
/* ipfw_path - путь к ipfw */
 
sprintf(ip_buff, "%s%s%s", ipfw_path , " table 1 list | grep ", row[1]);
ipfw = popen(ip_buff, "r"); 
if (ipfw == NULL)
{
              puts("error");
}
fscanf(ipfw,"%s",ip_buff);
int status = pclose(ipfw);
if(status == 0)
{
              sprintf(buff, "%s%s%s", ipfw_path , " table 1 delete ", row[1]);
              ipfw = popen(buff, "r");
              if (ipfw == NULL) 
              {
                            puts("add rule to firewall table error");
              }
              pclose(ipfw);
}

п.с. может это варварство каждый раз дергать с таблицы грепом ип, но другого способа не придумал, может подкинет кто идею?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
21.03.2011, 15:45
Цитата Сообщение от oh.ua Посмотреть сообщение
C
1
if(status == 0)
Там выше по треду показан правильный код на макросах из sys/wait.h

Что касается идеи: если в процессе работы программы есть гарантия, что никто не изменит эту таблицу, то можно сделать popen("ipfw table 1 list",), прочитать и сохранить вывод, а дальше парсить ручками без грепа.
Но совсем правильно будет как-то так:
есть структура описывающая таблицу ipfw_table (netinet/ip_fw.h)
есть две "опции" для getsockopt() IP_FW_TABLE_GETSIZE - вернет количество записей в таблице и IP_FW_TABLE_LIST - вернет содержимое таблицы (память нужно выделить на всю таблицу целиком + размер самой структуры ipfw_table), а пробежаться по массиву адресов и сравнить с нужным уже не сложно. Код можно выдрать из самой ipfw
2
0 / 0 / 0
Регистрация: 20.12.2009
Сообщений: 15
22.03.2011, 12:30  [ТС]
спасибо, разобрался. Думаю пока буду использовать popen напрямую с ipfw, так как объем данных небольшой;
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
22.03.2011, 13:52
Может оно и правильно)
Держите, вдруг пригодиться...
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip_fw.h>
#include <arpa/inet.h>
#include <err.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
int
ipfw_table_lookup(uint32_t index, in_addr_t addr)
{
        ipfw_table      *tbl;
        int              ret, s;
        socklen_t        len;
        uint32_t         entries;
        unsigned int     i;
 
        ret = -1;
        s = -1;
        tbl = NULL;
 
        if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
                goto done;
 
        /* Get number of entries in table. */
        entries = index;
        len = sizeof(entries);
        if (getsockopt(s, IPPROTO_IP, IP_FW_TABLE_GETSIZE,
            &entries, &len) == -1)
                goto done;
        /* Empty table, assume not found. */
        if (entries == 0) {
                ret = 0;
                goto done;
        }
 
        /* Allocate buffer. */
        len = sizeof(*tbl) + entries * sizeof(ipfw_table_entry);
        if ((tbl = malloc(len)) == NULL)
                goto done;
        tbl->tbl = index;
 
        /* Get table content. */
        if (getsockopt(s, IPPROTO_IP, IP_FW_TABLE_LIST,
            tbl, &len) == -1)
                goto done;
 
        /* Assume not found. */
        ret = 0;
 
        for (i = 0; i < tbl->cnt; i++)
                if (tbl->ent[i].addr == addr) {
                        ret = 1;
                        break;
                }
 
done:
        if (tbl)
                free(tbl);
        if (s)
                close(s);
 
        return (ret);
}
 
int
main(int argc, char *argv[])
{
        in_addr_t                addr;
        extern char             *__progname;
        int                      ret;
 
        if (argc != 2) {
                fprintf(stderr, "usage: %s address\n", __progname);
                exit(1);
        }
 
        if ((addr = inet_addr(argv[1])) == INADDR_NONE)
                errx(1, "invalid address %s", argv[1]);
 
        ret = ipfw_table_lookup(1, addr);
        switch (ret) {
        case 0:
                printf("%s not in ipfw table\n",
                    inet_ntoa(*(struct in_addr *)&addr));
                break;
        case 1:
                printf("%s found in ipfw table\n",
                    inet_ntoa(*(struct in_addr *)&addr));
                break;
        default:
                err(-1, "ipfw_table_lookup()");
        }
 
        return (ret);
}
2
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
24.03.2011, 09:32
oh.ua, вчера посмотрел сырцы ipfw более внимательно.
Проверка "а есть ли такой адрес в таблице" там отсутствует - ipfw table n add/del x.x.x.x сразу пытается добавить/удалить адрес из таблицы, думаю вы можете сделать так же...
1
0 / 0 / 0
Регистрация: 20.12.2009
Сообщений: 15
29.03.2011, 20:08  [ТС]
g_u_e_s_t, только вот если удалять ип с таблицы, а ее там нет , то в ответ в консоль выкидывает сообщение что "ipfw: setsockopt(IP_FW_TABLE_DEL): No such process", да и смысл удалят то, чего нет, лутче как-то проверить. Думаю это надо делать на уровне выше, например ставить какието флажки, был ли добавлен адрес в такую-то таблицу, чтоб потом точно оттуда удалить его без проверки grep-ом и т.п.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
29.03.2011, 23:03
Так это именно по тому, что сам ipfw этого не проверяет, такая проверка происходит уже непосредственно в ядре. Соответственно ваш grep или код который я приводил для замены попросту избыточен.
В общем ваша задача сводится к одному вызову socket() на запуск и к одному setsockopt() на каждый удаляемый адрес или если больше нравиться плодить процессы (2 на каждый удаляемый адрес), то можно запускать ipfw с stderr перенаправленным в /dev/null.
1
0 / 0 / 0
Регистрация: 20.12.2009
Сообщений: 15
30.03.2011, 01:24  [ТС]
g_u_e_s_t, можно пример маленький? а то чтото пока не могу сообразить
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
30.03.2011, 04:07
https://www.cyberforum.ru/post1474375.html
C
1
2
        if (s)
                close(s);
запускает close() для -1


ошибка
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
#include <stdio.h>
#include <sys/wait.h>
 
int main(void)
{
    FILE *ifp = popen("echo x", "r");
        
    if (ifp) {
        printf("in\n");
        int status = pclose(ifp);
        if (status != -1 && WIFEXITED(status))
            printf("%x\n", WEXITSTATUS(status));
    }
    return 0;
}
Code
1
2
3
4
[guest@localhost tmp]$ gcc -Wall t.c -o t
[guest@localhost tmp]$ ./t
in
[guest@localhost tmp]$


эта правильная
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
#include <stdio.h>
#include <sys/wait.h>
 
int main(void)
{
    FILE *ifp = popen("echo x", "r");
        
    if (ifp) {
        printf("in\n");
        getc(ifp);
        int status = pclose(ifp);
        if (status != -1 && WIFEXITED(status))
            printf("%x\n", WEXITSTATUS(status));
    }
    return 0;
}
Code
1
2
3
4
5
[guest@localhost tmp]$ gcc -Wall t.c -o t
[guest@localhost tmp]$ ./t
in
0
[guest@localhost tmp]$


если не прочитать хотя бы один символ из открытого потока, то сбоит
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
30.03.2011, 10:30
Цитата Сообщение от oh.ua Посмотреть сообщение
g_u_e_s_t, можно пример маленький? а то чтото пока не могу сообразить
Держите.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip_fw.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#define IPFW_TABLE_INDEX        1       /* ipfw table index */
 
int ipfw;                               /* socket fd */
 
 
int
ipfw_table_del(uint32_t index, in_addr_t addr)
{
        ipfw_table_entry         ent;
 
        ent.tbl = index;
        ent.masklen = 32;
        ent.value = addr;
 
        if ((setsockopt(ipfw, IPPROTO_IP, IP_FW_TABLE_DEL,
            &ent, sizeof(ent))) == -1) {
                if (errno != ESRCH) {
                        warn("setsockopt");
                        return (-1);
                }
        }
 
        return (0);
}
 
int
main(int argc, char *argv[])
{
        in_addr_t                addr;
        extern char             *__progname;
 
        if (argc != 2) {
                fprintf(stderr, "usage: %s address\n", __progname);
                exit(1);
        }
 
        if ((addr = inet_addr(argv[1])) == INADDR_NONE)
                errx(1, "invalid address %s", argv[1]);
 
        if ((ipfw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
                err(1, "cannot create raw socket");
 
        ipfw_table_del(IPFW_TABLE_INDEX, addr);
 
        return (0);
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
30.03.2011, 10:30
Помогаю со студенческими работами здесь

ipfw в pfsense (freebsd с веб мордой) из командной строки
По информации из вебморды понял, что не все тонкости настроек отражены в графическом режиме. Хочу посмотреть настройки ipfw. Делаю #...

Команды в ipfw
Всем привет. Помогите плз с командами настройки ipfw Вот я например добавляю айпи в таблицу блокировки ipfw table 1 add...

FreeBSD, перенаправление вывода команды в файл
Пробую вывести результат команды в файл,выводит вместо файла в консоль,в чем проблема? tunefs -p da1s1&gt;&gt;myFile

После команды start батник прекращает выполнение. Как запустить 2 команды start?
Я хочу одним кликом на батник запускать сразу и BrowserSync, и Sublime Text. Однако, запускается лишь что-то одно так как после команд...

выполнение команды
Здравствуйте. Имеется такая проблема: выполняю команду вида if ( argc == 3 &amp;&amp; string( argv ) == &quot;check&quot;)...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru