Отправка запроса MDNS с использованием сокетов Objective C

У меня есть iPad, который не «видит» устройства Bonjour в сети. Итак, я хочу отправить пакет UDP MDNS, чтобы сеть предоставила IP-адрес новейшим устройствам в сети, чтобы я мог выполнять зеркалирование на iPad. Я могу создать сокет, но отправляю неверные данные. Любые идеи?

struct icmphdr
    {
        u_int16_t qr;       /* type sub-code */
        u_int16_t opcode;
        u_int16_t aa;
        u_int16_t tc;
        u_int16_t rd;
        u_int16_t ra;
        u_int16_t z;
        u_int16_t ad;
        u_int16_t cd;
        u_int16_t rcode;
        u_int16_t q_count;
}
// Create the socket connection
    int sd = socket(AF_INET, SOCK_DGRAM, 0);

// Configure the port and ip we want to send to
    struct sockaddr_in broadcastAddr; // Make an endpoint
    memset(&broadcastAddr, 0, sizeof (broadcastAddr));
    broadcastAddr.sin_family = AF_INET;
    broadcastAddr.sin_len = sizeof(broadcastAddr);
    broadcastAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    broadcastAddr.sin_addr.s_addr = inet_addr("224.0.0.251");
    broadcastAddr.sin_port = htons(5353); // Set port 5353

    bind (sd, (struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr));
    struct icmphdr req;
    req.qr=00;      // Reponse: Message is query
    req.opcode=00;  // Opcode: Standard Query (0)
    req.tc=00;      // Truncated: Message is not truncated
    req.rd=00;      // Recursion desired: Don't do query recursively
    req.z=00;       // Z: reserved (0)

    req.ad=00;      // Non-authenticated data: Unacceptable
    req.ra=02;      // Questions: 2
    req.cd = 00;
    req.rcode = 00;
    req.q_count = 00;
    req.aa = 00;

    if (sendto(sd, &req, sizeof(req), 00, (struct sockaddr*)&broadcastAddr, sizeof broadcastAddr)) {
        NSLog(@"%s",strerror(errno));
    }
    close(sd);

person Mariano Romano    schedule 07.07.2014    source источник


Ответы (1)


Во-первых, как узнать, что ваш iPad не видит устройства Bonjour? если только это не очень ранняя версия iOS, она должна быть в состоянии.

во-вторых, запросы Bonjour (обычно) выполняются с помощью DNS-запросов для записей PTR, а не ICMP. Насколько я знаю, нет способа получить список каждого устройства Bonjour в сети. поэтому вы можете либо запросить интересующие вас услуги, либо запросить _services._dns-sd._udp.local, чтобы получить список услуг, а затем запросить каждую из них.

в любом случае вашему пакету нужна некоторая информация о вопросе. Google для структуры пакетов DNS, вот краткое руководство по запросу PTR -

id - 2 байта, всегда нулевые флаги - 2 байта, ноль для количества вопросов запроса - 2 байта, в данном случае 1 счетчик ответов - 2 байта, нулевой счетчик полномочий - 2 байта, нулевой дополнительный счетчик - 2 байта, ноль

Далее следует ваш вопрос - имя (например, _airport._tcp.local) - в формате 3www6google3com0, тип - 2 байта, 12 для класса типа PTR - 2 байта, 1 для интернет-класса

это должно сделать это.

однако обратите внимание, что прежде чем приступить к этой проблеме, посмотрите, можете ли вы использовать bind () для порта 5353. Он не позволяет мне это сделать, говорит, что адрес уже используется. Я полагаю, ребята, которые портировали ответчик MDNS на iOS, забыли установить опцию «повторного использования адреса» на своем сокете. так что это конец. Спасибо ребята.

person Jason Proctor    schedule 12.08.2014
comment
Фактически, вы можете привязаться к порту 5353. Вот код для этого // Установите параметр сокета для повторного использования порта 5353 if (setsockopt (sd, SOL_SOCKET, SO_REUSEPORT, & on, sizeof (on)) ‹0) {NSLog (@setsockopt () не удалось:% s, strerror (errno)); } // Привязываем порт 5353 к iPad if (bind (sd, (struct sockaddr *) & client, sizeof (client)) ‹0) {NSLog (@Binding failed:% s, strerror (errno)); } - person Mariano Romano; 14.11.2014
comment
первое связывание порта должно установить опцию повторного использования порта, чтобы дальнейшие связывания работали. если нет первого связующего, то последующих привязок быть не может. скажите мне об этом, все мои приложения mDNS сломались с Yosemite, поскольку новая вещь обнаружения не устанавливает эту опцию. Однако я слышал, что El Capitan возвращается к mDNSResponder, который (если они сейчас тоже не сломали его) устанавливает параметр повторного использования. фу! Жизнь для нас с типами mDNS непроста. - person Jason Proctor; 27.10.2015