~ubuntu-branches/ubuntu/quantal/curl/quantal-updates

« back to all changes in this revision

Viewing changes to tests/server/tftpd.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Schuldei
  • Date: 2009-04-02 23:35:45 UTC
  • mto: (1.2.1 upstream) (3.2.3 sid)
  • mto: This revision was merged to the branch mainline in revision 38.
  • Revision ID: james.westby@ubuntu.com-20090402233545-geixkwhe3izccjt7
Tags: upstream-7.19.4
ImportĀ upstreamĀ versionĀ 7.19.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * $Id: tftpd.c,v 1.35 2008-04-23 23:55:34 yangtse Exp $
 
8
 * $Id: tftpd.c,v 1.48 2008-10-23 14:34:09 yangtse Exp $
9
9
 *
10
10
 * Trivial file transfer protocol server.
11
11
 *
96
96
/* include memdebug.h last */
97
97
#include "memdebug.h"
98
98
 
 
99
#ifdef ENABLE_IPV6
 
100
static bool use_ipv6 = FALSE;
 
101
#endif
 
102
static const char *ipv_inuse = "IPv4";
 
103
 
99
104
struct testcase {
100
105
  char *buffer;   /* holds the file data to send to the client */
101
106
  size_t bufsize; /* size of the data in buffer */
113
118
                   int convert);
114
119
static void mysignal(int, void (*func)(int));
115
120
 
 
121
#define opcode_RRQ   1
 
122
#define opcode_WRQ   2
 
123
#define opcode_DATA  3
 
124
#define opcode_ACK   4
 
125
#define opcode_ERROR 5
116
126
 
117
127
#define TIMEOUT         5
118
128
 
119
129
#define PKTSIZE SEGSIZE+4
120
130
 
121
 
struct formats;
122
 
static int tftp(struct testcase *test, struct tftphdr *tp, int size);
 
131
struct formats {
 
132
  const char *f_mode;
 
133
  int f_convert;
 
134
};
 
135
static struct formats formata[] = {
 
136
  { "netascii",   1 },
 
137
  { "octet",      0 },
 
138
  { NULL,         0 }
 
139
};
 
140
 
 
141
static int tftp(struct testcase *test, struct tftphdr *tp, ssize_t size);
123
142
static void nak(int error);
124
143
static void sendtftp(struct testcase *test, struct formats *pf);
125
144
static void recvtftp(struct testcase *test, struct formats *pf);
137
156
struct bf {
138
157
  int counter;            /* size of data in buffer, or flag */
139
158
  char buf[PKTSIZE];      /* room for data packet */
140
 
} bfs[2];
 
159
};
 
160
static struct bf bfs[2];
141
161
 
142
162
                                /* Values for bf.counter  */
143
163
#define BF_ALLOC -3             /* alloc'd but not yet filled */
147
167
static int nextone;     /* index of next buffer to use */
148
168
static int current;     /* index of buffer in use */
149
169
 
150
 
                        /* control flags for crlf conversions */
151
 
int newline = 0;        /* fillbuf: in middle of newline expansion */
152
 
int prevchar = -1;      /* putbuf: previous char (cr check) */
 
170
                           /* control flags for crlf conversions */
 
171
static int newline = 0;    /* fillbuf: in middle of newline expansion */
 
172
static int prevchar = -1;  /* putbuf: previous char (cr check) */
153
173
 
154
174
static void read_ahead(struct testcase *test,
155
175
                       int convert /* if true, convert to ascii */);
365
385
#endif
366
386
    if (i) {
367
387
      j++;
368
 
      fromaddrlen = sizeof fromaddr;
369
 
      (void) recvfrom(f, rbuf, sizeof (rbuf), 0,
370
 
                      (struct sockaddr *)&fromaddr, &fromaddrlen);
 
388
      fromaddrlen = sizeof(fromaddr);
 
389
      (void)recvfrom(f, rbuf, sizeof(rbuf), 0,
 
390
                     (struct sockaddr *)&fromaddr, &fromaddrlen);
371
391
    }
372
392
    else
373
393
      break;
397
417
 
398
418
#define REQUEST_DUMP  "log/server.input"
399
419
 
400
 
char use_ipv6=FALSE;
401
420
 
402
421
int main(int argc, char **argv)
403
422
{
407
426
#endif /* ENABLE_IPV6 */
408
427
 
409
428
  struct tftphdr *tp;
410
 
  int n = 0;
 
429
  ssize_t n = 0;
411
430
  int arg = 1;
412
431
  char *pidname= (char *)".tftpd.pid";
413
432
  unsigned short port = DEFAULT_PORT;
435
454
    }
436
455
    else if(!strcmp("--ipv6", argv[arg])) {
437
456
#ifdef ENABLE_IPV6
438
 
      use_ipv6=TRUE;
 
457
      ipv_inuse = "IPv6";
 
458
      use_ipv6 = TRUE;
439
459
#endif
440
460
      arg++;
441
461
    }
505
525
    return 1;
506
526
  }
507
527
 
508
 
  logmsg("Running IPv%d version on port UDP/%d",
509
 
#ifdef ENABLE_IPV6
510
 
         (use_ipv6?6:4)
511
 
#else
512
 
         4
513
 
#endif
514
 
         , port );
 
528
  logmsg("Running %s version on port UDP/%d", ipv_inuse, (int)port);
515
529
 
516
530
  do {
517
531
    fromlen = sizeof(from);
518
 
    n = recvfrom(sock, buf, sizeof (buf), 0,
519
 
                 (struct sockaddr *)&from, &fromlen);
 
532
    n = (ssize_t)recvfrom(sock, buf, sizeof(buf), 0,
 
533
                          (struct sockaddr *)&from, &fromlen);
520
534
    if (n < 0) {
521
535
      logmsg("recvfrom:\n");
522
536
      result = 3;
543
557
 
544
558
    tp = (struct tftphdr *)buf;
545
559
    tp->th_opcode = ntohs(tp->th_opcode);
546
 
    if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) {
 
560
    if (tp->th_opcode == opcode_RRQ || tp->th_opcode == opcode_WRQ) {
547
561
      memset(&test, 0, sizeof(test));
548
562
      if (tftp(&test, tp, n) < 0)
549
563
        break;
561
575
  return result;
562
576
}
563
577
 
564
 
struct formats {
565
 
  const char *f_mode;
566
 
  int f_convert;
567
 
} formats[] = {
568
 
  { "netascii",   1 },
569
 
  { "octet",      0 },
570
 
  { NULL,         0 }
571
 
};
572
 
 
573
578
/*
574
579
 * Handle initial connection protocol.
575
580
 */
576
 
static int tftp(struct testcase *test, struct tftphdr *tp, int size)
 
581
static int tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
577
582
{
578
583
  char *cp;
579
584
  int first = 1, ecode;
623
628
  fprintf(server, "mode: %s\n", mode);
624
629
  fclose(server);
625
630
 
626
 
  for (pf = formats; pf->f_mode; pf++)
 
631
  for (pf = formata; pf->f_mode; pf++)
627
632
    if (strcmp(pf->f_mode, mode) == 0)
628
633
      break;
629
634
  if (!pf->f_mode) {
635
640
    nak(ecode);
636
641
    return 1;
637
642
  }
638
 
  if (tp->th_opcode == WRQ)
 
643
  if (tp->th_opcode == opcode_WRQ)
639
644
    recvtftp(test, pf);
640
645
  else
641
646
    sendtftp(test, pf);
734
739
  return 0;
735
740
}
736
741
 
737
 
int timeout;
 
742
static int timeout;
738
743
#ifdef HAVE_SIGSETJMP
739
 
sigjmp_buf timeoutbuf;
 
744
static sigjmp_buf timeoutbuf;
740
745
#endif
741
746
 
742
747
static void timer(int signum)
755
760
#endif
756
761
}
757
762
 
 
763
static unsigned short sendblock;
 
764
static struct tftphdr *sdp;
 
765
static struct tftphdr *sap; /* ack packet */
758
766
/*
759
767
 * Send the requested file.
760
768
 */
761
769
static void sendtftp(struct testcase *test, struct formats *pf)
762
770
{
763
 
  struct tftphdr *dp;
764
 
  struct tftphdr *ap;    /* ack packet */
765
 
  unsigned short block = 1;
766
771
  int size;
767
772
  ssize_t n;
 
773
  sendblock = 1;
768
774
#if defined(HAVE_ALARM) && defined(SIGALRM)
769
775
  mysignal(SIGALRM, timer);
770
776
#endif
771
 
  dp = r_init();
772
 
  ap = (struct tftphdr *)ackbuf;
 
777
  sdp = r_init();
 
778
  sap = (struct tftphdr *)ackbuf;
773
779
  do {
774
 
    size = readit(test, &dp, pf->f_convert);
 
780
    size = readit(test, &sdp, pf->f_convert);
775
781
    if (size < 0) {
776
782
      nak(ERRNO + 100);
777
783
      return;
778
784
    }
779
 
    dp->th_opcode = htons((u_short)DATA);
780
 
    dp->th_block = htons((u_short)block);
 
785
    sdp->th_opcode = htons((u_short)opcode_DATA);
 
786
    sdp->th_block = htons((u_short)sendblock);
781
787
    timeout = 0;
782
788
#ifdef HAVE_SIGSETJMP
783
789
    (void) sigsetjmp(timeoutbuf, 1);
784
790
#endif
785
791
    send_data:
786
 
    if (swrite(peer, dp, size + 4) != size + 4) {
 
792
    if (swrite(peer, sdp, size + 4) != size + 4) {
787
793
      logmsg("write\n");
788
794
      return;
789
795
    }
800
806
        logmsg("read: fail\n");
801
807
        return;
802
808
      }
803
 
      ap->th_opcode = ntohs((u_short)ap->th_opcode);
804
 
      ap->th_block = ntohs((u_short)ap->th_block);
 
809
      sap->th_opcode = ntohs((u_short)sap->th_opcode);
 
810
      sap->th_block = ntohs((u_short)sap->th_block);
805
811
 
806
 
      if (ap->th_opcode == ERROR) {
 
812
      if (sap->th_opcode == opcode_ERROR) {
807
813
        logmsg("got ERROR");
808
814
        return;
809
815
      }
810
816
 
811
 
      if (ap->th_opcode == ACK) {
812
 
        if (ap->th_block == block) {
 
817
      if (sap->th_opcode == opcode_ACK) {
 
818
        if (sap->th_block == sendblock) {
813
819
          break;
814
820
        }
815
821
        /* Re-synchronize with the other side */
816
822
        (void) synchnet(peer);
817
 
        if (ap->th_block == (block -1)) {
 
823
        if (sap->th_block == (sendblock-1)) {
818
824
          goto send_data;
819
825
        }
820
826
      }
821
827
 
822
828
    }
823
 
    block++;
 
829
    sendblock++;
824
830
  } while (size == SEGSIZE);
825
831
}
826
832
 
830
836
}
831
837
 
832
838
 
 
839
static unsigned short recvblock;
 
840
static struct tftphdr *rdp;
 
841
static struct tftphdr *rap; /* ack buffer */
833
842
/*
834
843
 * Receive a file.
835
844
 */
836
845
static void recvtftp(struct testcase *test, struct formats *pf)
837
846
{
838
 
  struct tftphdr *dp;
839
 
  struct tftphdr *ap;    /* ack buffer */
840
 
  unsigned short block = 0;
841
847
  ssize_t n, size;
 
848
  recvblock = 0;
842
849
#if defined(HAVE_ALARM) && defined(SIGALRM)
843
850
  mysignal(SIGALRM, timer);
844
851
#endif
845
 
  dp = w_init();
846
 
  ap = (struct tftphdr *)ackbuf;
 
852
  rdp = w_init();
 
853
  rap = (struct tftphdr *)ackbuf;
847
854
  do {
848
855
    timeout = 0;
849
 
    ap->th_opcode = htons((u_short)ACK);
850
 
    ap->th_block = htons((u_short)block);
851
 
    block++;
 
856
    rap->th_opcode = htons((u_short)opcode_ACK);
 
857
    rap->th_block = htons((u_short)recvblock);
 
858
    recvblock++;
852
859
#ifdef HAVE_SIGSETJMP
853
860
    (void) sigsetjmp(timeoutbuf, 1);
854
861
#endif
862
869
#ifdef HAVE_ALARM
863
870
      alarm(rexmtval);
864
871
#endif
865
 
      n = sread(peer, dp, PKTSIZE);
 
872
      n = sread(peer, rdp, PKTSIZE);
866
873
#ifdef HAVE_ALARM
867
874
      alarm(0);
868
875
#endif
870
877
        logmsg("read: fail\n");
871
878
        goto abort;
872
879
      }
873
 
      dp->th_opcode = ntohs((u_short)dp->th_opcode);
874
 
      dp->th_block = ntohs((u_short)dp->th_block);
875
 
      if (dp->th_opcode == ERROR)
 
880
      rdp->th_opcode = ntohs((u_short)rdp->th_opcode);
 
881
      rdp->th_block = ntohs((u_short)rdp->th_block);
 
882
      if (rdp->th_opcode == opcode_ERROR)
876
883
        goto abort;
877
 
      if (dp->th_opcode == DATA) {
878
 
        if (dp->th_block == block) {
 
884
      if (rdp->th_opcode == opcode_DATA) {
 
885
        if (rdp->th_block == recvblock) {
879
886
          break;                         /* normal */
880
887
        }
881
888
        /* Re-synchronize with the other side */
882
889
        (void) synchnet(peer);
883
 
        if (dp->th_block == (block-1))
 
890
        if (rdp->th_block == (recvblock-1))
884
891
          goto send_ack;                 /* rexmit */
885
892
      }
886
893
    }
887
894
 
888
 
    size = writeit(test, &dp, (int)(n - 4), pf->f_convert);
 
895
    size = writeit(test, &rdp, (int)(n - 4), pf->f_convert);
889
896
    if (size != (n-4)) {                 /* ahem */
890
897
      if (size < 0)
891
898
        nak(ERRNO + 100);
896
903
  } while (size == SEGSIZE);
897
904
  write_behind(test, pf->f_convert);
898
905
 
899
 
  ap->th_opcode = htons((u_short)ACK);   /* send the "final" ack */
900
 
  ap->th_block = htons((u_short)(block));
 
906
  rap->th_opcode = htons((u_short)opcode_ACK);  /* send the "final" ack */
 
907
  rap->th_block = htons((u_short)recvblock);
901
908
  (void) swrite(peer, ackbuf, 4);
902
909
#if defined(HAVE_ALARM) && defined(SIGALRM)
903
910
  mysignal(SIGALRM, justtimeout);        /* just abort read on timeout */
908
915
  alarm(0);
909
916
#endif
910
917
  if (n >= 4 &&                          /* if read some data */
911
 
      dp->th_opcode == DATA &&           /* and got a data block */
912
 
      block == dp->th_block) {           /* then my last ack was lost */
 
918
      rdp->th_opcode == opcode_DATA &&   /* and got a data block */
 
919
      recvblock == rdp->th_block) {      /* then my last ack was lost */
913
920
    (void) swrite(peer, ackbuf, 4);      /* resend final ack */
914
921
  }
915
922
abort:
919
926
struct errmsg {
920
927
  int e_code;
921
928
  const char *e_msg;
922
 
} errmsgs[] = {
 
929
};
 
930
static struct errmsg errmsgs[] = {
923
931
  { EUNDEF,       "Undefined error code" },
924
932
  { ENOTFOUND,    "File not found" },
925
933
  { EACCESS,      "Access violation" },
942
950
  struct errmsg *pe;
943
951
 
944
952
  tp = (struct tftphdr *)buf;
945
 
  tp->th_opcode = htons((u_short)ERROR);
 
953
  tp->th_opcode = htons((u_short)opcode_ERROR);
946
954
  tp->th_code = htons((u_short)error);
947
955
  for (pe = errmsgs; pe->e_code >= 0; pe++)
948
956
    if (pe->e_code == error)