Skip to content
Snippets Groups Projects
tftp.c 32.9 KiB
Newer Older
  • Learn to ignore specific revisions
  •                                         0,
                                            (struct sockaddr *)&fromaddr,
                                            &fromlen);
    
          if(state->remote_addrlen==0) {
            memcpy(&state->remote_addr, &fromaddr, fromlen);
            state->remote_addrlen = fromlen;
          }
    
    
          /* Sanity check packet length */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          if(state->rbytes < 4) {
    
            failf(data, "Received too short packet");
    
            /* Not a timeout, but how best to handle it? */
            event = TFTP_EVENT_TIMEOUT;
    
          }
          else {
    
            /* The event is given by the TFTP packet time */
            event = (tftp_event_t)getrpacketevent(&state->rpacket);
    
            switch(event) {
            case TFTP_EVENT_DATA:
              /* Don't pass to the client empty or retransmitted packets */
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
              if(state->rbytes > 4 &&
    
                  ((state->block+1) == getrpacketblock(&state->rpacket))) {
    
                code = Curl_client_write(conn, CLIENTWRITE_BODY,
    
                k->bytecount += state->rbytes-4;
                Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
    
              }
              break;
            case TFTP_EVENT_ERROR:
              state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
    
              infof(data, "%s\n", (const char *)state->rpacket.data+4);
    
            case TFTP_EVENT_OACK:
              code = tftp_parse_option_ack(state,
                                           (const char *)state->rpacket.data+2,
                                           state->rbytes-2);
              if(code)
                return code;
              break;
    
            case TFTP_EVENT_RRQ:
            case TFTP_EVENT_WRQ:
            default:
    
              failf(data, "%s", "Internal error: Unexpected packet");
    
            if(Curl_pgrsUpdate(conn))
              return CURLE_ABORTED_BY_CALLBACK;
    
        }
    
        /* Check for transfer timeout every 10 blocks, or after timeout */
        if(check_time%10==0) {
          time_t current;
          time(&current);
          if(current>state->max_time) {
    
            DEBUGF(infof(data, "timeout: %d > %d\n",
                         current, state->max_time));
    
            state->error = TFTP_ERR_TIMEOUT;
            state->state = TFTP_STATE_FIN;
          }
        }
    
      }
    
      if(code)
        return code;
    
      code = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
    
      if(state->error != TFTP_ERR_NONE) {
    
    
        /* Translate internal error codes to curl error codes */
        switch(state->error) {
        case TFTP_ERR_NOTFOUND:
          code = CURLE_TFTP_NOTFOUND;
          break;
        case TFTP_ERR_PERM:
          code = CURLE_TFTP_PERM;
          break;
        case TFTP_ERR_DISKFULL:
    
        case TFTP_ERR_ILLEGAL:
          code = CURLE_TFTP_ILLEGAL;
          break;
        case TFTP_ERR_UNKNOWNID:
          code = CURLE_TFTP_UNKNOWNID;
          break;
        case TFTP_ERR_EXISTS:
    
          break;
        case TFTP_ERR_NOSUCHUSER:
          code = CURLE_TFTP_NOSUCHUSER;
          break;
        case TFTP_ERR_TIMEOUT:
    
          break;
        case TFTP_ERR_NORESPONSE:
          code = CURLE_COULDNT_CONNECT;
          break;
        default:
          code= CURLE_ABORTED_BY_CALLBACK;
          break;
        }
      }
      else
        code = CURLE_OK;
      return code;
    }
    
    static CURLcode tftp_setup_connection(struct connectdata * conn)
    
    {
      struct SessionHandle *data = conn->data;
      char * type;
      char command;
    
      conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
    
      /* TFTP URLs support an extension like ";mode=<typecode>" that
       * we'll try to get now! */
    
      type = strstr(data->state.path, ";mode=");
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      if(!type)
    
        type = strstr(conn->host.rawalloc, ";mode=");
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      if(type) {
    
        *type = 0;                   /* it was in the middle of the hostname */
    
        command = Curl_raw_toupper(type[6]);
    
    
        switch (command) {
        case 'A': /* ASCII mode */
        case 'N': /* NETASCII mode */
          data->set.prefer_ascii = TRUE;
          break;
    
        case 'O': /* octet mode */
        case 'I': /* binary mode */
        default:
          /* switch off ASCII */
          data->set.prefer_ascii = FALSE;
          break;
        }
      }
    
      return CURLE_OK;
    }