Intereting Posts
не может преобразовать строчные буквы в верхний регистр строки по директиве препроцессора Поддерживает ли стандартная библиотека c связанный список и т. Д. Структуры данных? Функция для проверки, является ли строка ввода целым числом или числом с плавающей запятой? Haskell: используйте последнюю ссылку на переменную, чтобы эффективно создать новую переменную как получить серийный номер тома (Game of Life) Как прокручивать внешний слой матрицы без проверки за ее пределами, одновременно проверяя наличие соседей? Установка gtk и компиляция с использованием gcc под windowsми? Инициализация массива после объявления C – литье int в char и добавление char для char Треугольник Паскаля в C Когда преобразование между неподписанным и подписанным символьным указателем становится небезопасным в C? Поделиться массивом между lua и C Программирование CUDA C на 2 видеокарты SIGCHLD отправляется на SIGCONT на Linux, но не на macOS Зачем мне передавать параметры функции по значению в C?

Получение шлюза для использования для данного ip в ANSI C

Я озирался, как сумасшедший, но не получил реального ответа. У меня есть один пример, но это зависело от личной библиотеки, поэтому не так хорошо.

Сначала мне захотелось получить шлюз по умолчанию для интерфейса, но поскольку разные IP-адреса могли быть маршрутизированы по-разному, я быстро понял, что я хочу, чтобы он получал шлюз для использования для данного IP-адреса назначения с использованием сокета AF_ROUTE и rtm_type RTM_GET . Есть ли у кого-нибудь пример, где я на самом деле заканчиваю строку, содержащую IP-адреса шлюзов (или MAC-адрес)? Запись шлюза кажется шестнадцатеричной, но также закодирована в / proc / net / route, где, я думаю, AF_ROUTE сокет получает информацию из (но через kernel, я думаю).

Заранее спасибо

и ps Я только начал использовать переполнение стека, и я должен сказать, что все вы, ребята, великолепны! Быстрые ответы и хорошие! Вы мои новые лучшие друзья;)

Это специфичная ОС, для этого нет единого (или ANSI C) API.

Предполагая Linux, лучший способ – просто разобрать / proc / net / route, искать запись, где Destination is 00000000, шлюз по умолчанию находится в столбце Gateway, где вы можете прочитать шестнадцатеричное представление IP-адреса шлюза (в больших endian, я считаю)

Если вы хотите сделать это с помощью более конкретных вызовов API, вам придется пройти через несколько обручей, вот пример программы:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define BUFSIZE 8192 char gateway[255]; struct route_info { struct in_addr dstAddr; struct in_addr srcAddr; struct in_addr gateWay; char ifName[IF_NAMESIZE]; }; int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId) { struct nlmsghdr *nlHdr; int readLen = 0, msgLen = 0; do { /* Recieve response from the kernel */ if ((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) { perror("SOCK READ: "); return -1; } nlHdr = (struct nlmsghdr *) bufPtr; /* Check if the header is valid */ if ((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) { perror("Error in recieved packet"); return -1; } /* Check if the its the last message */ if (nlHdr->nlmsg_type == NLMSG_DONE) { break; } else { /* Else move the pointer to buffer appropriately */ bufPtr += readLen; msgLen += readLen; } /* Check if its a multi part message */ if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) { /* return if its not */ break; } } while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); return msgLen; } /* For printing the routes. */ void printRoute(struct route_info *rtInfo) { char tempBuf[512]; /* Print Destination address */ if (rtInfo->dstAddr.s_addr != 0) strcpy(tempBuf, inet_ntoa(rtInfo->dstAddr)); else sprintf(tempBuf, "*.*.*.*\t"); fprintf(stdout, "%s\t", tempBuf); /* Print Gateway address */ if (rtInfo->gateWay.s_addr != 0) strcpy(tempBuf, (char *) inet_ntoa(rtInfo->gateWay)); else sprintf(tempBuf, "*.*.*.*\t"); fprintf(stdout, "%s\t", tempBuf); /* Print Interface Name*/ fprintf(stdout, "%s\t", rtInfo->ifName); /* Print Source address */ if (rtInfo->srcAddr.s_addr != 0) strcpy(tempBuf, inet_ntoa(rtInfo->srcAddr)); else sprintf(tempBuf, "*.*.*.*\t"); fprintf(stdout, "%s\n", tempBuf); } void printGateway() { printf("%s\n", gateway); } /* For parsing the route info returned */ void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo) { struct rtmsg *rtMsg; struct rtattr *rtAttr; int rtLen; rtMsg = (struct rtmsg *) NLMSG_DATA(nlHdr); /* If the route is not for AF_INET or does not belong to main routing table then return. */ if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) return; /* get the rtattr field */ rtAttr = (struct rtattr *) RTM_RTA(rtMsg); rtLen = RTM_PAYLOAD(nlHdr); for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) { switch (rtAttr->rta_type) { case RTA_OIF: if_indextoname(*(int *) RTA_DATA(rtAttr), rtInfo->ifName); break; case RTA_GATEWAY: rtInfo->gateWay.s_addr= *(u_int *) RTA_DATA(rtAttr); break; case RTA_PREFSRC: rtInfo->srcAddr.s_addr= *(u_int *) RTA_DATA(rtAttr); break; case RTA_DST: rtInfo->dstAddr .s_addr= *(u_int *) RTA_DATA(rtAttr); break; } } //printf("%s\n", inet_ntoa(rtInfo->dstAddr)); if (rtInfo->dstAddr.s_addr == 0) sprintf(gateway, (char *) inet_ntoa(rtInfo->gateWay)); //printRoute(rtInfo); return; } int main() { struct nlmsghdr *nlMsg; struct rtmsg *rtMsg; struct route_info *rtInfo; char msgBuf[BUFSIZE]; int sock, len, msgSeq = 0; /* Create Socket */ if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) perror("Socket Creation: "); memset(msgBuf, 0, BUFSIZE); /* point the header and the msg structure pointers into the buffer */ nlMsg = (struct nlmsghdr *) msgBuf; rtMsg = (struct rtmsg *) NLMSG_DATA(nlMsg); /* Fill in the nlmsg header*/ nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message. nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table . nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump. nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet. nlMsg->nlmsg_pid = getpid(); // PID of process sending the request. /* Send the request */ if (send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) { printf("Write To Socket Failed...\n"); return -1; } /* Read the response */ if ((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) { printf("Read From Socket Failed...\n"); return -1; } /* Parse and print the response */ rtInfo = (struct route_info *) malloc(sizeof(struct route_info)); //fprintf(stdout, "Destination\tGateway\tInterface\tSource\n"); for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) { memset(rtInfo, 0, sizeof(struct route_info)); parseRoutes(nlMsg, rtInfo); } free(rtInfo); close(sock); printGateway(); return 0; } 

Может быть, это очень старый вопрос, но у меня была такая же проблема, и я не могу найти лучшего результата. Наконец, я решил проблему с этим кодом, что он имеет несколько изменений. Поэтому я решил поделиться им.

 char* GetGatewayForInterface(const char* interface) { char* gateway = NULL; char cmd [1000] = {0x0}; sprintf(cmd,"route -n | grep %s | grep 'UG[ \t]' | awk '{print $2}'", interface); FILE* fp = popen(cmd, "r"); char line[256]={0x0}; if(fgets(line, sizeof(line), fp) != NULL) gateway = string(line); pclose(fp); } 

Я решил пойти «быстро и грязно», чтобы начать с и читать ip из /proc/net/route используя netstat -rm .

Я думал, что поделился бы своей функцией … Обратите внимание, что в ней есть некоторая ошибка, и, возможно, вы могли бы помочь мне найти ее, и я отредактирую ее без ошибок. Функция принимает имя iface как eth0 и возвращает ip шлюза, используемого этим iface.

 char* GetGatewayForInterface(const char* interface) { char* gateway = NULL; FILE* fp = popen("netstat -rn", "r"); char line[256]={0x0}; while(fgets(line, sizeof(line), fp) != NULL) { /* * Get destination. */ char* destination; destination = strndup(line, 15); /* * Extract iface to compare with the requested one * todo: fix for iface names longer than eth0, eth1 etc */ char* iface; iface = strndup(line + 73, 4); // Find line with the gateway if(strcmp("0.0.0.0 ", destination) == 0 && strcmp(iface, interface) == 0) { // Extract gateway gateway = strndup(line + 16, 15); } free(destination); free(iface); } pclose(fp); return gateway; } 

Проблема с этой функцией заключается в том, что когда я оставляю pclose там, это вызывает повреждение памяти chrash. Но он работает, если я удалю pclose-вызов (но это не будет хорошим решением, потому что stream останется открытым .. хе-хе). Поэтому, если кто-нибудь может заметить ошибку, я отредактирую функцию с правильной версией. Я не C гуру и немного запутался во всех играх памяти;)