~ubuntu-branches/ubuntu/lucid/curl/lucid-security

« back to all changes in this revision

Viewing changes to lib/tftp.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2009-04-29 11:10:29 UTC
  • mfrom: (3.2.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090429111029-2j5eiyokfw2bw049
Tags: 7.19.4-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Drop build dependencies: stunnel, libdb4.6-dev, libssh2-1-dev
  - Add build-dependency on openssh-server
  - Drop libssh2-1-dev from libcurl4-openssl-dev's Depends.
  - Call automake-1.9 with --add-missing --copy --force
* drop debian/patches/security_CVE-2009-0037.patch 
  - this patch is part of 7.19.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: tftp.c,v 1.68 2008-02-11 22:03:31 bagder Exp $
 
21
 * $Id: tftp.c,v 1.81 2009-02-14 13:43:18 giva Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
26
26
#ifndef CURL_DISABLE_TFTP
27
27
/* -- WIN32 approved -- */
28
28
#include <stdio.h>
29
 
#include <string.h>
30
29
#include <stdarg.h>
31
30
#include <stdlib.h>
32
31
#include <ctype.h>
52
51
#ifdef HAVE_NET_IF_H
53
52
#include <net/if.h>
54
53
#endif
 
54
#ifdef HAVE_SYS_IOCTL_H
55
55
#include <sys/ioctl.h>
56
 
#include <signal.h>
 
56
#endif
57
57
 
58
58
#ifdef HAVE_SYS_PARAM_H
59
59
#include <sys/param.h>
71
71
#include "strerror.h"
72
72
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
73
73
#include "url.h"
 
74
#include "rawstr.h"
74
75
 
75
76
#define _MPRINTF_REPLACE /* use our functions only */
76
77
#include <curl/mprintf.h>
81
82
/* The last #include file should be: */
82
83
#include "memdebug.h"
83
84
 
84
 
/* RFC2348 allows the block size to be negotiated, but we don't support that */
85
 
#define TFTP_BLOCKSIZE 512
 
85
/* RFC2348 allows the block size to be negotiated */
 
86
#define TFTP_BLKSIZE_DEFAULT 512
 
87
#define TFTP_BLKSIZE_MIN 8
 
88
#define TFTP_BLKSIZE_MAX 65464
 
89
#define TFTP_OPTION_BLKSIZE "blksize"
 
90
#define TFTP_OPTION_TSIZE "tsize"
 
91
#define TFTP_OPTION_INTERVAL "interval"
86
92
 
87
93
typedef enum {
88
94
  TFTP_MODE_NETASCII=0,
103
109
  TFTP_EVENT_DATA = 3,
104
110
  TFTP_EVENT_ACK = 4,
105
111
  TFTP_EVENT_ERROR = 5,
 
112
  TFTP_EVENT_OACK = 6,
106
113
  TFTP_EVENT_TIMEOUT
107
114
} tftp_event_t;
108
115
 
123
130
} tftp_error_t;
124
131
 
125
132
typedef struct tftp_packet {
126
 
  unsigned char data[2 + 2 + TFTP_BLOCKSIZE];
 
133
  unsigned char *data;
127
134
} tftp_packet_t;
128
135
 
129
136
typedef struct tftp_state_data {
133
140
  struct connectdata      *conn;
134
141
  curl_socket_t   sockfd;
135
142
  int             retries;
136
 
  int             retry_time;
137
 
  int             retry_max;
 
143
  time_t          retry_time;
 
144
  time_t          retry_max;
138
145
  time_t          start_time;
139
146
  time_t          max_time;
140
147
  unsigned short  block;
141
148
  struct Curl_sockaddr_storage   local_addr;
142
149
  struct Curl_sockaddr_storage   remote_addr;
143
150
  socklen_t       remote_addrlen;
144
 
  int             rbytes;
145
 
  int             sbytes;
 
151
  ssize_t         rbytes;
 
152
  size_t          sbytes;
 
153
  size_t          blksize;
 
154
  int             requested_blksize;
146
155
  tftp_packet_t   rpacket;
147
156
  tftp_packet_t   spacket;
148
157
} tftp_state_data_t;
152
161
static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
153
162
static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
154
163
static CURLcode tftp_connect(struct connectdata *conn, bool *done);
 
164
static CURLcode tftp_disconnect(struct connectdata *conn);
155
165
static CURLcode tftp_do(struct connectdata *conn, bool *done);
156
166
static CURLcode tftp_done(struct connectdata *conn,
157
167
                               CURLcode, bool premature);
173
183
  ZERO_NULL,                            /* doing */
174
184
  ZERO_NULL,                            /* proto_getsock */
175
185
  ZERO_NULL,                            /* doing_getsock */
176
 
  ZERO_NULL,                            /* disconnect */
 
186
  ZERO_NULL,                            /* perform_getsock */
 
187
  tftp_disconnect,                      /* disconnect */
177
188
  PORT_TFTP,                            /* defport */
178
189
  PROT_TFTP                             /* protocol */
179
190
};
193
204
{
194
205
  time_t maxtime, timeout;
195
206
  long timeout_ms;
 
207
  bool start = (bool)(state->state == TFTP_STATE_START);
196
208
 
197
209
  time(&state->start_time);
198
210
 
199
211
  /* Compute drop-dead time */
200
 
  timeout_ms = Curl_timeleft(state->conn, NULL, TRUE);
 
212
  timeout_ms = Curl_timeleft(state->conn, NULL, start);
201
213
 
202
214
  if(timeout_ms < 0) {
203
215
    /* time-out, bail out, go home */
205
217
    return CURLE_OPERATION_TIMEDOUT;
206
218
  }
207
219
 
208
 
  if(state->state == TFTP_STATE_START) {
 
220
  if(start) {
209
221
 
210
222
    maxtime = (time_t)(timeout_ms + 500) / 1000;
211
223
    state->max_time = state->start_time+maxtime;
253
265
    state->retry_time=1;
254
266
 
255
267
  infof(state->conn->data,
256
 
        "set timeouts for state %d; Total %d, retry %d maxtry %d\n",
 
268
        "set timeouts for state %d; Total %d, retry %d maxtry %d\n",
257
269
        state->state, (state->max_time-state->start_time),
258
270
        state->retry_time, state->retry_max);
259
271
 
291
303
  return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
292
304
}
293
305
 
 
306
static size_t Curl_strnlen(const char *string, size_t maxlen)
 
307
{
 
308
  const char *end = memchr (string, '\0', maxlen);
 
309
  return end ? (size_t) (end - string) : maxlen;
 
310
}
 
311
 
 
312
static const char *tftp_option_get(const char *buf, size_t len,
 
313
                                   const char **option, const char **value)
 
314
{
 
315
  size_t loc;
 
316
 
 
317
  loc = Curl_strnlen( buf, len );
 
318
  loc++; /* NULL term */
 
319
 
 
320
  if (loc >= len)
 
321
    return NULL;
 
322
  *option = buf;
 
323
 
 
324
  loc += Curl_strnlen( buf+loc, len-loc );
 
325
  loc++; /* NULL term */
 
326
 
 
327
  if (loc > len)
 
328
    return NULL;
 
329
  *value = &buf[strlen(*option) + 1];
 
330
 
 
331
  return &buf[loc];
 
332
}
 
333
 
 
334
static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
 
335
                                      const char *ptr, int len)
 
336
{
 
337
  const char *tmp = ptr;
 
338
  struct SessionHandle *data = state->conn->data;
 
339
 
 
340
  /* if OACK doesn't contain blksize option, the default (512) must be used */
 
341
  state->blksize = TFTP_BLKSIZE_DEFAULT;
 
342
 
 
343
  while (tmp < ptr + len) {
 
344
    const char *option, *value;
 
345
 
 
346
    tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
 
347
    if(tmp == NULL) {
 
348
      failf(data, "Malformed ACK packet, rejecting");
 
349
      return CURLE_TFTP_ILLEGAL;
 
350
    }
 
351
 
 
352
    infof(data, "got option=(%s) value=(%s)\n", option, value);
 
353
 
 
354
    if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
 
355
      int blksize;
 
356
 
 
357
      blksize = strtol( value, NULL, 10 );
 
358
 
 
359
      if(!blksize) {
 
360
        failf(data, "invalid blocksize value in OACK packet");
 
361
        return CURLE_TFTP_ILLEGAL;
 
362
      }
 
363
      else if(blksize > TFTP_BLKSIZE_MAX) {
 
364
        failf(data, "%s (%d)", "blksize is larger than max supported",
 
365
                TFTP_BLKSIZE_MAX);
 
366
        return CURLE_TFTP_ILLEGAL;
 
367
      }
 
368
      else if(blksize < TFTP_BLKSIZE_MIN) {
 
369
        failf(data, "%s (%d)", "blksize is smaller than min supported",
 
370
                TFTP_BLKSIZE_MIN);
 
371
        return CURLE_TFTP_ILLEGAL;
 
372
      }
 
373
      else if (blksize > state->requested_blksize) {
 
374
        /* could realloc pkt buffers here, but the spec doesn't call out
 
375
         * support for the server requesting a bigger blksize than the client
 
376
         * requests */
 
377
        failf(data, "%s (%d)",
 
378
                "server requested blksize larger than allocated", blksize);
 
379
        return CURLE_TFTP_ILLEGAL;
 
380
      }
 
381
 
 
382
      state->blksize = blksize;
 
383
      infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK",
 
384
        state->blksize, "requested", state->requested_blksize);
 
385
    }
 
386
    else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
 
387
      long tsize = 0;
 
388
 
 
389
      tsize = strtol( value, NULL, 10 );
 
390
      if(!tsize) {
 
391
        failf(data, "invalid tsize value in OACK packet");
 
392
        return CURLE_TFTP_ILLEGAL;
 
393
      }
 
394
      Curl_pgrsSetDownloadSize(data, tsize);
 
395
      infof(data, "%s (%d)\n", "tsize parsed from OACK", tsize);
 
396
    }
 
397
  }
 
398
 
 
399
  return CURLE_OK;
 
400
}
 
401
 
 
402
static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
 
403
                              char *buf, const char *option)
 
404
{
 
405
  if( ( strlen(option) + csize + 1U ) > state->blksize )
 
406
        return 0;
 
407
  strcpy(buf, option);
 
408
  return( strlen(option) + 1 );
 
409
}
 
410
 
 
411
static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, tftp_event_t event)
 
412
{
 
413
  CURLcode res;
 
414
  struct SessionHandle *data = state->conn->data;
 
415
 
 
416
  infof(data, "%s\n", "Connected for transmit");
 
417
  state->state = TFTP_STATE_TX;
 
418
  res = tftp_set_timeouts(state);
 
419
  if(res != CURLE_OK)
 
420
    return(res);
 
421
  return tftp_tx(state, event);
 
422
}
 
423
 
 
424
static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, tftp_event_t event)
 
425
{
 
426
  CURLcode res;
 
427
  struct SessionHandle *data = state->conn->data;
 
428
 
 
429
  infof(data, "%s\n", "Connected for receive");
 
430
  state->state = TFTP_STATE_RX;
 
431
  res = tftp_set_timeouts(state);
 
432
  if(res != CURLE_OK)
 
433
    return(res);
 
434
  return tftp_rx(state, event);
 
435
}
 
436
 
294
437
static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
295
438
{
296
439
  int sbytes;
297
440
  const char *mode = "octet";
298
441
  char *filename;
 
442
  char buf[8];
299
443
  struct SessionHandle *data = state->conn->data;
300
444
  CURLcode res = CURLE_OK;
301
445
 
319
463
      /* If we are uploading, send an WRQ */
320
464
      setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
321
465
      state->conn->data->req.upload_fromhere =
322
 
        (char *)&state->spacket.data[4];
 
466
        (char *)state->spacket.data+4;
323
467
      if(data->set.infilesize != -1)
324
468
        Curl_pgrsSetUploadSize(data, data->set.infilesize);
325
469
    }
328
472
      setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
329
473
    }
330
474
    /* As RFC3617 describes the separator slash is not actually part of the
331
 
    file name so we skip the always-present first letter of the path string. */
 
475
       file name so we skip the always-present first letter of the path
 
476
       string. */
332
477
    filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
333
478
                                  NULL);
334
479
    if(!filename)
335
480
      return CURLE_OUT_OF_MEMORY;
336
481
 
337
 
    snprintf((char *)&state->spacket.data[2],
338
 
             TFTP_BLOCKSIZE,
 
482
    snprintf((char *)state->spacket.data+2,
 
483
             state->blksize,
339
484
             "%s%c%s%c", filename, '\0',  mode, '\0');
340
 
    sbytes = 4 + (int)strlen(filename) + (int)strlen(mode);
341
 
    sbytes = sendto(state->sockfd, (void *)&state->spacket,
 
485
    sbytes = 4 + strlen(filename) + strlen(mode);
 
486
 
 
487
    /* add tsize option */
 
488
    sbytes += tftp_option_add(state, sbytes,
 
489
                              (char *)state->spacket.data+sbytes,
 
490
                              TFTP_OPTION_TSIZE);
 
491
    sbytes += tftp_option_add(state, sbytes,
 
492
                              (char *)state->spacket.data+sbytes, "0");
 
493
    /* add blksize option */
 
494
    snprintf( buf, sizeof(buf), "%d", state->requested_blksize );
 
495
    sbytes += tftp_option_add(state, sbytes,
 
496
                              (char *)state->spacket.data+sbytes,
 
497
                              TFTP_OPTION_BLKSIZE);
 
498
    sbytes += tftp_option_add(state, sbytes,
 
499
                              (char *)state->spacket.data+sbytes, buf );
 
500
    /* add timeout option */
 
501
    snprintf( buf, sizeof(buf), "%d", state->retry_time );
 
502
    sbytes += tftp_option_add(state, sbytes,
 
503
                              (char *)state->spacket.data+sbytes,
 
504
                              TFTP_OPTION_INTERVAL);
 
505
    sbytes += tftp_option_add(state, sbytes,
 
506
                              (char *)state->spacket.data+sbytes, buf );
 
507
 
 
508
    sbytes = sendto(state->sockfd, (void *)state->spacket.data,
342
509
                    sbytes, 0,
343
510
                    state->conn->ip_addr->ai_addr,
344
511
                    state->conn->ip_addr->ai_addrlen);
348
515
    Curl_safefree(filename);
349
516
    break;
350
517
 
 
518
  case TFTP_EVENT_OACK:
 
519
    if(data->set.upload) {
 
520
      res = tftp_connect_for_tx(state, event);
 
521
    }
 
522
    else {
 
523
      res = tftp_connect_for_rx(state, event);
 
524
    }
 
525
    break;
 
526
 
351
527
  case TFTP_EVENT_ACK: /* Connected for transmit */
352
 
    infof(data, "%s\n", "Connected for transmit");
353
 
    state->state = TFTP_STATE_TX;
354
 
    res = tftp_set_timeouts(state);
355
 
    if(res)
356
 
      break;
357
 
    return tftp_tx(state, event);
 
528
    res = tftp_connect_for_tx(state, event);
 
529
    break;
358
530
 
359
 
  case TFTP_EVENT_DATA: /* connected for receive */
360
 
    infof(data, "%s\n", "Connected for receive");
361
 
    state->state = TFTP_STATE_RX;
362
 
    res = tftp_set_timeouts(state);
363
 
    if(res)
364
 
      break;
365
 
    return tftp_rx(state, event);
 
531
  case TFTP_EVENT_DATA: /* Connected for receive */
 
532
    res = tftp_connect_for_rx(state, event);
 
533
    break;
366
534
 
367
535
  case TFTP_EVENT_ERROR:
368
536
    state->state = TFTP_STATE_FIN;
391
559
  switch(event) {
392
560
 
393
561
  case TFTP_EVENT_DATA:
394
 
 
395
562
    /* Is this the block we expect? */
396
563
    rblock = getrpacketblock(&state->rpacket);
397
564
    if((state->block+1) != rblock) {
420
587
    }
421
588
 
422
589
    /* Check if completed (That is, a less than full packet is received) */
423
 
    if(state->rbytes < (int)sizeof(state->spacket)){
 
590
    if(state->rbytes < (ssize_t)state->blksize+4){
424
591
      state->state = TFTP_STATE_FIN;
425
592
    }
426
593
    else {
428
595
    }
429
596
    break;
430
597
 
 
598
  case TFTP_EVENT_OACK:
 
599
    /* ACK option acknowledgement so we can move on to data */
 
600
    state->block = 0;
 
601
    state->retries = 0;
 
602
    setpacketevent(&state->spacket, TFTP_EVENT_ACK);
 
603
    setpacketblock(&state->spacket, state->block);
 
604
    sbytes = sendto(state->sockfd, (void *)state->spacket.data,
 
605
                    4, SEND_4TH_ARG,
 
606
                    (struct sockaddr *)&state->remote_addr,
 
607
                    state->remote_addrlen);
 
608
    if(sbytes < 0) {
 
609
      failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
 
610
      return CURLE_SEND_ERROR;
 
611
    }
 
612
 
 
613
    /* we're ready to RX data */
 
614
    state->state = TFTP_STATE_RX;
 
615
    break;
 
616
 
431
617
  case TFTP_EVENT_TIMEOUT:
432
618
    /* Increment the retry count and fail if over the limit */
433
619
    state->retries++;
439
625
    }
440
626
    else {
441
627
      /* Resend the previous ACK */
442
 
      sbytes = sendto(state->sockfd, (void *)&state->spacket,
 
628
      sbytes = sendto(state->sockfd, (void *)state->spacket.data,
443
629
                      4, SEND_4TH_ARG,
444
630
                      (struct sockaddr *)&state->remote_addr,
445
631
                      state->remote_addrlen);
515
701
    state->retries = 0;
516
702
    setpacketevent(&state->spacket, TFTP_EVENT_DATA);
517
703
    setpacketblock(&state->spacket, state->block);
518
 
    if(state->block > 1 && state->sbytes < TFTP_BLOCKSIZE) {
 
704
    if(state->block > 1 && state->sbytes < state->blksize) {
519
705
      state->state = TFTP_STATE_FIN;
520
706
      return CURLE_OK;
521
707
    }
522
 
    res = Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes);
 
708
    res = Curl_fillreadbuffer(state->conn, state->blksize,
 
709
                              (int *)&state->sbytes);
523
710
    if(res)
524
711
      return res;
525
712
    sbytes = sendto(state->sockfd, (void *)state->spacket.data,
548
735
    }
549
736
    else {
550
737
      /* Re-send the data packet */
551
 
      sbytes = sendto(state->sockfd, (void *)&state->spacket,
 
738
      sbytes = sendto(state->sockfd, (void *)state->spacket.data,
552
739
                      4+state->sbytes, SEND_4TH_ARG,
553
740
                      (struct sockaddr *)&state->remote_addr,
554
741
                      state->remote_addrlen);
611
798
  return res;
612
799
}
613
800
 
 
801
/**********************************************************
 
802
 *
 
803
 * tftp_disconnect
 
804
 *
 
805
 * The disconnect callback
 
806
 *
 
807
 **********************************************************/
 
808
static CURLcode tftp_disconnect(struct connectdata *conn)
 
809
{
 
810
  tftp_state_data_t *state = conn->proto.tftpc;
 
811
 
 
812
  /* done, free dynamically allocated pkt buffers */
 
813
  if(state) {
 
814
    Curl_safefree(state->rpacket.data);
 
815
    Curl_safefree(state->spacket.data);
 
816
    free(state);
 
817
  }
 
818
 
 
819
  return CURLE_OK;
 
820
}
614
821
 
615
822
/**********************************************************
616
823
 *
623
830
{
624
831
  CURLcode code;
625
832
  tftp_state_data_t *state;
626
 
  int rc;
 
833
  int blksize, rc;
 
834
 
 
835
  blksize = TFTP_BLKSIZE_DEFAULT;
627
836
 
628
837
  /* If there already is a protocol-specific struct allocated for this
629
838
     sessionhandle, deal with it */
630
839
  Curl_reset_reqproto(conn);
631
840
 
632
 
  state = conn->data->state.proto.tftp;
633
 
  if(!state) {
634
 
    state = conn->data->state.proto.tftp = calloc(sizeof(tftp_state_data_t),
635
 
                                                  1);
636
 
    if(!state)
 
841
  state = conn->proto.tftpc = calloc(sizeof(tftp_state_data_t), 1);
 
842
  if(!state)
 
843
    return CURLE_OUT_OF_MEMORY;
 
844
 
 
845
  /* alloc pkt buffers based on specified blksize */
 
846
  if(conn->data->set.tftp_blksize) {
 
847
    blksize = conn->data->set.tftp_blksize;
 
848
    if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN )
 
849
      return CURLE_TFTP_ILLEGAL;
 
850
  }
 
851
 
 
852
  if(!state->rpacket.data) {
 
853
    state->rpacket.data = calloc(1, blksize + 2 + 2);
 
854
 
 
855
    if(!state->rpacket.data)
 
856
      return CURLE_OUT_OF_MEMORY;
 
857
  }
 
858
 
 
859
  if(!state->spacket.data) {
 
860
    state->spacket.data = calloc(1, blksize + 2 + 2);
 
861
 
 
862
    if(!state->spacket.data)
637
863
      return CURLE_OUT_OF_MEMORY;
638
864
  }
639
865
 
643
869
  state->sockfd = state->conn->sock[FIRSTSOCKET];
644
870
  state->state = TFTP_STATE_START;
645
871
  state->error = TFTP_ERR_NONE;
 
872
  state->blksize = TFTP_BLKSIZE_DEFAULT;
 
873
  state->requested_blksize = blksize;
646
874
 
647
875
  ((struct sockaddr *)&state->local_addr)->sa_family =
648
876
    (unsigned short)(conn->ip_addr->ai_family);
731
959
  */
732
960
  Curl_reset_reqproto(conn);
733
961
 
734
 
  if(!data->state.proto.tftp) {
 
962
  if(!conn->proto.tftpc) {
735
963
    code = tftp_connect(conn, done);
736
964
    if(code)
737
965
      return code;
738
966
  }
739
 
  state = (tftp_state_data_t *)data->state.proto.tftp;
 
967
  state = (tftp_state_data_t *)conn->proto.tftpc;
740
968
 
741
969
  /* Run the TFTP State Machine */
742
970
  for(code=tftp_state_machine(state, TFTP_EVENT_INIT);
745
973
 
746
974
    /* Wait until ready to read or timeout occurs */
747
975
    rc=Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD,
748
 
                         state->retry_time * 1000);
 
976
                         (int)(state->retry_time * 1000));
749
977
 
750
978
    if(rc == -1) {
751
979
      /* bail out */
764
992
    else {
765
993
 
766
994
      /* Receive the packet */
767
 
      fromlen=sizeof(fromaddr);
768
 
      state->rbytes = recvfrom(state->sockfd,
769
 
                               (void *)&state->rpacket, sizeof(state->rpacket),
770
 
                               0, (struct sockaddr *)&fromaddr, &fromlen);
 
995
      fromlen = sizeof(fromaddr);
 
996
      state->rbytes = (ssize_t)recvfrom(state->sockfd,
 
997
                                        (void *)state->rpacket.data,
 
998
                                        state->blksize+4,
 
999
                                        0,
 
1000
                                        (struct sockaddr *)&fromaddr,
 
1001
                                        &fromlen);
771
1002
      if(state->remote_addrlen==0) {
772
1003
        memcpy(&state->remote_addr, &fromaddr, fromlen);
773
1004
        state->remote_addrlen = fromlen;
790
1021
          if(state->rbytes > 4 &&
791
1022
              ((state->block+1) == getrpacketblock(&state->rpacket))) {
792
1023
            code = Curl_client_write(conn, CLIENTWRITE_BODY,
793
 
                                     (char *)&state->rpacket.data[4],
 
1024
                                     (char *)state->rpacket.data+4,
794
1025
                                     state->rbytes-4);
795
1026
            if(code)
796
1027
              return code;
800
1031
          break;
801
1032
        case TFTP_EVENT_ERROR:
802
1033
          state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
803
 
          infof(data, "%s\n", (char *)&state->rpacket.data[4]);
 
1034
          infof(data, "%s\n", (const char *)state->rpacket.data+4);
804
1035
          break;
805
1036
        case TFTP_EVENT_ACK:
806
1037
          break;
 
1038
        case TFTP_EVENT_OACK:
 
1039
          code = tftp_parse_option_ack(state,
 
1040
                                       (const char *)state->rpacket.data+2,
 
1041
                                       state->rbytes-2);
 
1042
          if(code)
 
1043
            return code;
 
1044
          break;
807
1045
        case TFTP_EVENT_RRQ:
808
1046
        case TFTP_EVENT_WRQ:
809
1047
        default:
898
1136
 
899
1137
  if(type) {
900
1138
    *type = 0;                   /* it was in the middle of the hostname */
901
 
    command = (char) toupper((int) type[6]);
 
1139
    command = Curl_raw_toupper(type[6]);
902
1140
 
903
1141
    switch (command) {
904
1142
    case 'A': /* ASCII mode */