示例#1
0
文件: socket.c 项目: JDsolution/ipnc
int avahi_send_dns_packet_ipv6(
        int fd,
        AvahiIfIndex interface,
        AvahiDnsPacket *p,
        const AvahiIPv6Address *src_address,
        const AvahiIPv6Address *dst_address,
        uint16_t dst_port) {

    struct sockaddr_in6 sa;
    struct msghdr msg;
    struct iovec io;
    struct cmsghdr *cmsg;
    size_t cmsg_data[(CMSG_SPACE(sizeof(struct in6_pktinfo))/sizeof(size_t)) + 1];

    assert(fd >= 0);
    assert(p);
    assert(avahi_dns_packet_check_valid(p) >= 0);
    assert(!dst_address || dst_port > 0);

    if (!dst_address)
        mdns_mcast_group_ipv6(&sa);
    else
        ipv6_address_to_sockaddr(&sa, dst_address, dst_port);

    memset(&io, 0, sizeof(io));
    io.iov_base = AVAHI_DNS_PACKET_DATA(p);
    io.iov_len = p->size;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = &sa;
    msg.msg_namelen = sizeof(sa);
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_flags = 0;

    if (interface > 0 || src_address) {
        struct in6_pktinfo *pkti;

        memset(cmsg_data, 0, sizeof(cmsg_data));
        msg.msg_control = cmsg_data;
        msg.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = msg.msg_controllen;
        cmsg->cmsg_level = IPPROTO_IPV6;
        cmsg->cmsg_type = IPV6_PKTINFO;

        pkti = (struct in6_pktinfo*) CMSG_DATA(cmsg);

        if (interface > 0)
            pkti->ipi6_ifindex = interface;

        if (src_address)
            memcpy(&pkti->ipi6_addr, src_address->address, sizeof(src_address->address));
    } else {
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
    }

    return sendmsg_loop(fd, &msg, 0);
}
示例#2
0
static void handle_packet(AvahiWideAreaLookupEngine *e, AvahiDnsPacket *p) {
    AvahiWideAreaLookup *l = NULL;
    int i, r;

    AvahiBrowserEvent final_event = AVAHI_BROWSER_ALL_FOR_NOW;
    
    assert(e);
    assert(p);

    /* Some superficial validity tests */
    if (avahi_dns_packet_check_valid(p) < 0 || avahi_dns_packet_is_query(p)) {
        avahi_log_warn(__FILE__": Ignoring invalid response for wide area datagram.");
        goto finish;
    }

    /* Look for the lookup that issued this query */
    if (!(l = find_lookup(e, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID))) || l->dead)
        goto finish;

    /* Check whether this a packet indicating a failure */
    if ((r = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & 15) != 0 ||
        avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ANCOUNT) == 0) {

        avahi_server_set_errno(e->server, r == 0 ? AVAHI_ERR_NOT_FOUND : map_dns_error(r));
        /* Tell the user about the failure */
        final_event = AVAHI_BROWSER_FAILURE;

        /* We go on here, since some of the records contained in the
           reply might be interesting in some way */
    }

    /* Skip over the question */
    for (i = (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); i > 0; i--) {
        AvahiKey *k;
        
        if (!(k = avahi_dns_packet_consume_key(p, NULL))) {
            avahi_log_warn(__FILE__": Wide area response packet too short or invalid while reading question key. (Maybe a UTF-8 problem?)");
            avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET);
            final_event = AVAHI_BROWSER_FAILURE;
            goto finish;
        }

        avahi_key_unref(k);
    }

    /* Process responses */
    for (i = (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ANCOUNT) +
             (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_NSCOUNT) +
             (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ARCOUNT); i > 0; i--) {

        AvahiRecord *rr;

        if (!(rr = avahi_dns_packet_consume_record(p, NULL))) {
            avahi_log_warn(__FILE__": Wide area response packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)");
            avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET);
            final_event = AVAHI_BROWSER_FAILURE;
            goto finish;
        }

        add_to_cache(e, rr);
        avahi_record_unref(rr);
    }

finish:
    
    if (l && !l->dead) {
        if (l->callback)
            l->callback(e, final_event, AVAHI_LOOKUP_RESULT_WIDE_AREA, NULL, l->userdata);

        lookup_stop(l);
    }
}
示例#3
0
文件: socket.c 项目: JDsolution/ipnc
int avahi_send_dns_packet_ipv4(
        int fd,
        AvahiIfIndex interface,
        AvahiDnsPacket *p,
        const AvahiIPv4Address *src_address,
        const AvahiIPv4Address *dst_address,
        uint16_t dst_port) {

    struct sockaddr_in sa;
    struct msghdr msg;
    struct iovec io;
#ifdef IP_PKTINFO
    struct cmsghdr *cmsg;
    size_t cmsg_data[( CMSG_SPACE(sizeof(struct in_pktinfo)) / sizeof(size_t)) + 1];
#elif !defined(IP_MULTICAST_IF) && defined(IP_SENDSRCADDR)
    struct cmsghdr *cmsg;
    size_t cmsg_data[( CMSG_SPACE(sizeof(struct in_addr)) / sizeof(size_t)) + 1];
#endif

    assert(fd >= 0);
    assert(p);
    assert(avahi_dns_packet_check_valid(p) >= 0);
    assert(!dst_address || dst_port > 0);

    if (!dst_address)
        mdns_mcast_group_ipv4(&sa);
    else
        ipv4_address_to_sockaddr(&sa, dst_address, dst_port);

    memset(&io, 0, sizeof(io));
    io.iov_base = AVAHI_DNS_PACKET_DATA(p);
    io.iov_len = p->size;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = &sa;
    msg.msg_namelen = sizeof(sa);
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_flags = 0;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;

#ifdef IP_PKTINFO
    if (interface > 0 || src_address) {
        struct in_pktinfo *pkti;

        memset(cmsg_data, 0, sizeof(cmsg_data));
        msg.msg_control = cmsg_data;
        msg.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = msg.msg_controllen;
        cmsg->cmsg_level = IPPROTO_IP;
        cmsg->cmsg_type = IP_PKTINFO;

        pkti = (struct in_pktinfo*) CMSG_DATA(cmsg);

        if (interface > 0)
            pkti->ipi_ifindex = interface;

        if (src_address)
            pkti->ipi_spec_dst.s_addr = src_address->address;
    }
#elif defined(IP_MULTICAST_IF)
    if (src_address) {
        struct in_addr any = { INADDR_ANY };
        if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, src_address ? &src_address->address : &any, sizeof(struct in_addr)) < 0) {
            avahi_log_warn("IP_MULTICAST_IF failed: %s", strerror(errno));
            return -1;
        }
    }
#elif defined(IP_SENDSRCADDR)
    if (src_address) {
        struct in_addr *addr;

        memset(cmsg_data, 0, sizeof(cmsg_data));
        msg.msg_control = cmsg_data;
        msg.msg_controllen = CMSG_LEN(sizeof(struct in_addr));

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = msg.msg_controllen;
        cmsg->cmsg_level = IPPROTO_IP;
        cmsg->cmsg_type = IP_SENDSRCADDR;

        addr = (struct in_addr *)CMSG_DATA(cmsg);
        addr->s_addr =  src_address->address;
    }
#elif defined(__GNUC__)
#warning "FIXME: We need some code to set the outgoing interface/local address here if IP_PKTINFO/IP_MULTICAST_IF is not available"
#endif

    return sendmsg_loop(fd, &msg, 0);
}