отправка необработанного пакета в C не появляется на проводе - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь закодировать обходной путь в моей среде. Я не контролирую функционирование оборудования назначения, просто общаюсь с ним. С учетом вышесказанного мне нужно разработать пакет UDP для отправки на другой конец и отправить через необработанный сокет, чтобы избежать стека сетевого уровня, поскольку конечная точка может не совпадать с su bnet. Эта проблема должна быть взята из предположения, что не будет консоли для работы, поэтому, пожалуйста, не предлагайте решения с консоли. Поэтому я написал приложение для отправки пакета, однако при запуске пакет не появляется на проводе и не видит, что я сделал неправильно. Я смотрю Wireshark, чтобы захватить, но просто не там. Так что Wireshark не просматривает необработанные пакеты, отправленные так, как при прохождении через сетевой стек, или так написан мой код. Он возвращает количество отправленных байтов.

Код запущен в Debian.


unsigned char   pktdata[2048];
struct ip     * iph     = NULL;
struct udphdr * udph    = NULL;
unsigned char * data    = NULL;
int             sock    = 0;
unsigned char   m_src_mac[6];

void openSocket()
{
    struct ifreq    ifr;
    int             ifindex     = 0;    /*Ethernet Interface index*/
    char            src_mac[20];
    char            device[8];

    bzero(device, sizeof(device));
    memcpy(device, "eth3", 5);
    std::vector<std::string> src = split(srcaddr, '.');
    if (src.size() == 4)
    {
        if (src[2].compare("62") == 0)
        {
            memcpy(device, "eth5", 5);
        }
    }

    printf("Server started, entering initialization phase...\n");

    /*open socket*/
    if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
        perror("socket():");
        exit(1);
    }
    printf("Successfully opened socket: %i\n", sock);

    /*retrieve Ethernet interface index*/
    strncpy(ifr.ifr_name, device, IFNAMSIZ);
    printf("set device to %s\n", ifr.ifr_name);
    if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1) {
        perror("SIOCGIFINDEX");
        exit(1);
    }
    ifindex = ifr.ifr_ifindex;
    printf("Successfully got interface index: %i\n", ifindex);

    /*retrieve corresponding MAC*/
    if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
        perror("SIOCGIFINDEX");
        exit(1);
    }
    for (int i = 0; i < 6; i++) {
        m_src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
    }
    snprintf(src_mac, sizeof(src_mac), "%02X:%02X:%02X:%02X:%02X:%02X",
            m_src_mac[0], m_src_mac[1], m_src_mac[2], m_src_mac[3], m_src_mac[4], m_src_mac[5]);

    printf("Successfully got our MAC address: %s\n", src_mac);

    // Create the structure for the socket to bind too
    struct sockaddr_ll sll;
    bzero(&sll , sizeof(sll));

    int one = 1;
    const int *val = &one;

    if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
    {
        perror("setsockopt: error");
        exit(1);
    }
    else
        printf("setsockopt is OK\n");
}

void PackData()
{
    iph     = (struct ip *)pktdata;
    udph    = (struct udphdr *)(pktdata + sizeof(struct ip));
    data    = pktdata + sizeof(struct ip) + sizeof(struct udphdr);

    iph->ip_hl  = 5;            /* header length            */
    iph->ip_v   = 4;            /* version                  */
    iph->ip_tos = 0;            /* type of service          */
    iph->ip_len = 154;          /* total length             */
    iph->ip_id  = 25802;        /* identification           */
    iph->ip_off = 16384;        /* fragment offset field    */
    iph->ip_ttl = 64;           /* time to live             */
    iph->ip_p   = 17;           /* protocol                 */
    iph->ip_sum = 0;            /* checksum                 */
    iph->ip_src = 0x0a3ca8c0;   /* source  address          */
    iph->ip_dst = 0x0b3ca8c0;   /* dest address             */

    iph->ip_sum = calc_ip_sum();

    udph->uh_sport  = 5000;     /* source port      */
    udph->uh_dport  = 10161;    /* destination port */
    udph->uh_ulen   = 134;      /* udp length       */
    udph->uh_sum    = 0;        /* udp checksum     */

    // Add payload here

    udph->uh_sum    = calc_udp_sum();
}

void SendPacket()
{
    openSocket();

    struct sockaddr_in sin;

    bzero((void*)&sin, sizeof(struct sockaddr_in));
    sin.sin_family      = AF_INET;
    sin.sin_port        = udph->uh_dport;
    sin.sin_addr.s_addr = iph->ip_dst;

    printf("Sockadd info family %d, port %hu, addr : %08x\n", sin.sin_family, sin.sin_port, sin.sin_addr.s_addr);

    if (sendto(sock, pktdata, iph->ip_len, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0)
    {
        perror("sendto failed");
    }
    else
    {
        printf("Packet Send. Length : %lu\n", iph->ip_len);
    }

}

int main(int argc, char ** argv)
{
    PackData();
    openSocket();
    SendPacket();
}

Основы мой локальный eth3 будет 60.10, eth5 будет 62.10, конечное устройство должно быть либо 60.11 или 62.11, в зависимости от того, к какому NI C он непосредственно подключен. Маска подсети будет 255.255.255.0. Приложение ДОЛЖНО иметь возможность отправлять пакет на любой адрес конечной точки с любого локального NI C. Конфигурация локальной сети не может быть изменена, поэтому это не решение проблемы. Конфигурация сети конечной точки является той, которая была последней успешной конфигурацией. Таким образом, если устройство, которое было подключено к eth5 и настроено на 62.11, выходит из строя, оно будет заменено другим блоком HW, который мог быть настроен как 60.11. Я не могу просто поменять IP локально, потому что, возможно, уже работает устройство eth3 с версией 60.11. Обходные предложения будут приняты, просто ничего не связано с консолью. Возможно, мне удастся программно изменить локальный IP-адрес, отправить пакет и изменить IP-адрес обратно, но мне все равно придется разговаривать только с правильным устройством 60.11, не путая работающую систему с другими.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...