Exemplo n.º 1
0
Arquivo: dns.c Projeto: perryhg/terkos
/* Send the query to the server and read the response back. Return -1
   if it fails, otherwise put the response back in msg and return the
   length of the response. */
static int 
send_recv(char * msg, int len, int msglen)
{
    struct dns_header *dns_hdr;
    int finished = false;
    int read = 0;

    dns_hdr = (struct dns_header *) msg;

    do { 
        int len_togo = len;
        struct timeval timeout;
        struct sockaddr_in local_addr, from_addr;

        memset((char *)&local_addr, 0, sizeof(local_addr));
        local_addr.sin_family = AF_INET;
        local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        local_addr.sin_port = htons(get_port++);

        if (__udp_sendto(msg, len_togo, &server, &local_addr) < 0)
            return -1;

        memset((char *)&from_addr, 0, sizeof(from_addr));

        timeout.tv_sec = CYGNUM_REDBOOT_NETWORKING_DNS_TIMEOUT;
        timeout.tv_usec = 0;

        read = __udp_recvfrom(msg, len, &from_addr, &local_addr, &timeout);
        if (read < 0)
            return -1;

        /* Reply to an old query. Ignore it */
        if (ntohs(dns_hdr->id) != (id-1)) {
            continue;
        }
        finished = true;
    } while (!finished);

    return read;
}
Exemplo n.º 2
0
int
tftp_stream_read(char *buf,
                 int len,
                 int *err)
{
    int total_bytes = 0;
    int size, recv_len, data_len;
    struct timeval timeout;
    struct tftphdr *hdr = (struct tftphdr *)tftp_stream.data;

    while (total_bytes < len) {
        // Move any bytes which we've already read/buffered
        if (tftp_stream.avail > 0) {
            size = tftp_stream.avail;
            if (size > (len - total_bytes)) size = len - total_bytes;
            memcpy(buf, tftp_stream.bufp, size);
            buf += size;
            tftp_stream.bufp += size;
            tftp_stream.avail -= size;
            total_bytes += size;
        } else {
            if (tftp_ack(err) < 0) {
                return -1;
            }
            if ((tftp_stream.actual_len >= 0) && (tftp_stream.actual_len < SEGSIZE)) {
                // Out of data
                break;
            }
            timeout.tv_sec = (tftp_stream.last_good_block == 0) ? 10*TFTP_TIMEOUT_PERIOD : TFTP_TIMEOUT_PERIOD;
            timeout.tv_usec = 0;
            recv_len = sizeof(tftp_stream.data);
            if ((data_len = __udp_recvfrom(&tftp_stream.data[0], recv_len, &tftp_stream.from_addr, 
                                           &tftp_stream.local_addr,  &timeout)) < 0) {
                // No data, try again
                diag_printf("TFTP timed out %d/%d\n", tftp_stream.total_timeouts+1, TFTP_TIMEOUT_MAX);
                if ((++tftp_stream.total_timeouts > TFTP_TIMEOUT_MAX) || 
                    (tftp_stream.last_good_block == 0)) {
                    // Timeout - no data received
                    *err = TFTP_TIMEOUT;
                    return -1;
                }
                // Send out the ACK for the last block - maybe server will retry
                if (tftp_ack(err) < 0) {
                    return -1;
                }
            } else {
                tftp_stream.packets_received++;
                if (ntohs(hdr->th_opcode) == DATA) {
                    if (ntohs(hdr->th_block) == (cyg_uint16)((tftp_stream.last_good_block+1) & 0xFFFF)) {
                        // Consume this data
                        data_len -= 4;  /* Sizeof TFTP header */
                        tftp_stream.avail = tftp_stream.actual_len = data_len;
                        tftp_stream.bufp = hdr->th_data;
                        tftp_stream.last_good_block++;
                    }
                } else {
                    if (ntohs(hdr->th_opcode) == ERROR) {
                        *err = ntohs(hdr->th_code);
                        return -1;
                    } else {
                        // What kind of packet is this?
                        *err = TFTP_PROTOCOL;
                        return -1;
                    }
                }
            }
        }
    }
    return total_bytes;
}