TFTP.BAD
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:6k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * Copyright (c) 1990, 1999 Erick Engelke
  3.  */
  4. #include <rtos.h>
  5. #include <net.h>
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <time.h>
  11. #include <syslog.h>
  12. #include <tftp.h>
  13. #include <sysstat.h>
  14. #define TFTP_LOCAL_PORT 10069
  15. #define TFTP_PACKET_LEN 512 + 8
  16. /*
  17.  * get_tftp_response
  18.  *      - if TIMEOUT return -1
  19.  *      - sends multiple retries as needed in case data lost
  20.  */
  21. static int get_tftp_response( udp_Socket *out, udp_Socket *in, char *buffer, int *buflen )
  22. {
  23. #define TFTP_TIMEOUT 5 /* seconds */
  24. #define TFTP_SLEEP 20  /* milliseconds */
  25. #define TFTP_RETRIES 5
  26.     int timecount;
  27.     int retrycount = TFTP_RETRIES;
  28.     DWORD nextxmit;
  29.     int templen;
  30.     if ( out == NULL )
  31.         out = in;           /* handle post-setup sockets */
  32.     sock_fastwrite( out, buffer, *buflen );
  33.     nextxmit = ktime + TFTP_TIMEOUT;
  34.     while  ((templen = sock_dataready( in )) == 0 ) {
  35.         tcp_tick( NULL );
  36.         rt_sleep( 0 );
  37.         if ( nextxmit <= ktime) {
  38.             nextxmit = ktime + TFTP_TIMEOUT;
  39.             if ( retrycount -- < 1 )
  40.                 return( -1 );
  41.             sock_fastwrite( out, buffer, *buflen );
  42.         }
  43.     }
  44.     sock_fastread( in, buffer, templen );
  45.     *buflen = templen;
  46.     return( 0 );
  47. }
  48. // getblock - returns received length
  49. static int getblock( char *filename, int blocknum, void *buffer )
  50. {
  51.     FILE *f;
  52.     int result = 0;
  53.     kblock();
  54.     f = fopen( filename, "rb");
  55.     if ( f != NULL ) {
  56.         if ( 0 == fseek( f, (blocknum - 1) * 512L, SEEK_SET ))
  57.             result = fread( buffer, 1, 512, f );
  58.         fclose( f );
  59.     }
  60.     kunblock();
  61.     return( result );
  62. }
  63. // putblock - returns 0 on success
  64. static int putblock( char *filename, int blocknum, void *buffer, int length )
  65. {
  66.     FILE *f;
  67.     int result = 0;
  68.     kblock();
  69.     f = fopen( filename, "a+b");
  70.     if ( f != NULL ) {
  71.         if ( 0 == fseek( f, (blocknum - 1) * 512L, SEEK_SET ))
  72.             fwrite( buffer, 1, length, f );
  73.         else result = 3;    // disk full or alloc exceeded
  74.         fclose( f );
  75.     } else result = 3;
  76.     kunblock();
  77.     return( result ? 3 : 0 );
  78. }
  79. int tftp( DWORD host, int op, char * file )
  80. {
  81.     udp_Socket *s, *s2;
  82.     char *buf;
  83.     int datalen;
  84.     RRQ_Packet*t;
  85.     DATA_Packet *d;
  86.     ERROR_Packet *e;
  87.     char *p;
  88.     int result;
  89.     int ongoing = 1;        /* means we are still doing stuff */
  90.     int block;
  91.     DWORD filesize;
  92.     long bytesleft;
  93.     struct stat statbuf;
  94.     int i;
  95.     s = kcalloc( sizeof( udp_Socket ), 1 );
  96.     if ( s == NULL ) return( -1 );
  97.     s2 = kcalloc( sizeof( udp_Socket ), 1 );
  98.     if ( s2 == NULL ) {
  99.         kfree(s);
  100.         return( -1 );
  101.     }
  102.     buf = kcalloc( TFTP_PACKET_LEN , 1 );
  103.     if ( buf == NULL ) {
  104.         kfree( s );
  105.         kfree( s2 );
  106.         return( -1 );
  107.     }
  108.     d = t = e = buf;
  109.     if ( op == TFTP_GET )
  110.         unlink( file );
  111.     else {
  112.         kblock();
  113.         i = stat( file , &statbuf );
  114.         kunblock();
  115.         if ( i != 0 ) return -1 ;   /* file not found */
  116.         filesize = statbuf.st_size;
  117.         block = 0;
  118.     }
  119.     if (!udp_open( s, TFTP_LOCAL_PORT, host, TFTP_PORT, NULL )) {
  120.         kfree( s );
  121.         kfree( s2 );
  122.         kfree( buf );
  123.         return( -1 );
  124.     }
  125.     udp_open( s2, TFTP_LOCAL_PORT, 0, 0, NULL );
  126.     // build the file request packet
  127.     memset( buf, 0, TFTP_PACKET_LEN );
  128.     t->op2 = ( op == TFTP_PUT ) ? TFTP_WRQ : TFTP_RRQ;
  129.     strcpy( t->filename, file );
  130.     p = strchr( t->filename, 0 );
  131.     strcpy( ++p, "octet");
  132.     p = strchr( p, 0 );
  133.     datalen = p - t + 1;
  134. // sock_write( s, buf, datalen );
  135.     result = 0;
  136.     while ( 1 ) {
  137.         if ( get_tftp_response( s, s2, buf, &datalen) == -1 ) {
  138.             result = -1;
  139.             break;
  140.         }
  141.         /* we don't need original socket any more */
  142.         if ( s != NULL ) {
  143.             sock_close( s );
  144.             kfree( s );
  145.             s = NULL;
  146.         }
  147.         if ( !ongoing ) break;      /* after we have acked last packet, we quit */
  148.         if ( d->op2 == TFTP_ERROR ) {
  149.             result = -1;
  150.             break;
  151.         } else if (d->op2 == TFTP_DATA ) {
  152.             /* TFTP_GET */
  153.             datalen = datalen - sizeof( ACK_Packet );
  154.             d->op2 = TFTP_ACK;
  155.             block = intel16( d->block) ;
  156.             putblock( file, block, d->data, datalen );
  157.             /* 512 bytes means there is more to read */
  158.             if ( datalen != 512 ) {
  159.                 sock_write( s2, buf, sizeof( ACK_Packet ));
  160.                 break;
  161.             }
  162.             datalen = sizeof( ACK_Packet );
  163.         } else if ( d->op2 == TFTP_ACK ) {
  164.             /* TFTP_PUT */
  165.             if ( intel16( d->block) == block )
  166.                 block++;                /* advance, else repeat */
  167.             bytesleft = filesize - (( block - 1) * 512L);
  168.             if ( bytesleft <= 0 )   /* hit end of file */
  169.                 break;
  170.             d->op2 = TFTP_DATA;
  171.             d->block = intel16( block );
  172.             /* try to read block from disk */
  173.             i = getblock( file, block, d->data );
  174.             if ( i == 0 ) {
  175.                 result = -1;
  176.                 break;
  177.             }
  178.             datalen = sizeof( ACK_Packet ) + i;
  179.         } else {
  180.             /* error */
  181.             result = -1;
  182.             ongoing = 0;
  183.             e->op2 = TFTP_ERROR;
  184.             e->err1 = e->err2 = 0;
  185.             *e->errmsg = 0;
  186.             datalen = sizeof( ERROR_Packet );
  187.         }
  188.     } 
  189.     if ( s != NULL ) {
  190.         sock_close( s );
  191.         kfree( s );
  192.     }
  193.     sock_close( s2 );
  194.     kfree( buf );
  195.     kfree( s2 );
  196.     return( result );
  197. }