On November 21, 2010 17:38, in comp.lang.c,
lid wrote:
> Lew Pitcher wrote:
>> On November 21, 2010 16:56, in comp.lang.c, lid
>> wrote:
>>
>>> Lew Pitcher wrote:
>>>
>>>> So, what is it you are trying to do?
>>>
>>> From RFC 1350...
>>>
>>> Sollins
>>> [Page 5]
>>>
>>> RFC 1350 TFTP Revision 2 July
>>> 1992
>>>
>>>
>>> 2 bytes string 1 byte string 1 byte
>>> ------------------------------------------------
>>> | Opcode | Filename | 0 | Mode | 0 |
>>> ------------------------------------------------
>>>
>>> ***
>>> See how the "Filename" and "Mode" areas in this packet are simply
>>> "string"? I'd be more comfortable with something like char
>>> filenam[20]; or the like.
>>> ***
>>
>> You may be more comfortable with a fixed-length Filename and Mode,
>> but that would violate the protocol.
>>
>> [snip]
>>> RRQ and WRQ packets (opcodes 1 and 2 respectively) have the format
>>> shown in Figure 5-1. The file name is a sequence of bytes in
>>> netascii terminated by a zero byte. The mode field contains the
>>> string "netascii", "octet", or "mail" (or any combination of upper
>>> and lower case, such as "NETASCII", NetAscii", etc.) in netascii
>>> indicating the three modes defined in the protocol.
>>
>> The above writeup indicates that both Filename and Mode are
>> variable-length components. You /might/ be able to do this with C99
>> VLAs (pedants? your opinion?), but otherwise, your structure cannot
>> /exactly/ represent this packet.
>>
>> If you use a structure to /organize/ this data (rather than as an
>> output or input buffer), you could
>> struct tftp {
>> short mode;
>> char *filename; /* points to the filename string */
>> char mode[9]; /* can contain any of the valid mode strings */
>> };
>
> That's what I intended was for storage.
>
>>
>> However, if you intend to use the structure as an I/O buffer, then
>> you'll have to define it fairly generically, and do some work in
>> logic...
>>
>> struct tftp {
>> unsigned char opcode[2]; /* 2 octets for mode, in network byte
>> order */
>
> Why unsigned?
So that, when you fill in opcode[] with a 16bit value in network byte order,
you don't get unintentional sign extension.
>
> char data[]; /* FIXME - need to specify exact
>> length of array */ };
>>
>> /* your logic....*/
>> FILE *connection;
>> struct tftp header;
>> int src, dst;
>> int length;
>>
>> /* set header opcode from opcodeValue */
>> header.opcode[1] = opcodeValue%256;
>> header.opcode[0] = opcodeValue/256;
>
> What's the above? % for modulo? and / for division by 256?
Take an integer value of unknown range, and squeeze it into a 16bit value in
network byte (aka "big endian") order, as two 8bit quantities.
I could have done it with logical operations (shifts and logical-ands), and
probably should have. But, I wanted to emphasize that we are dealing with
an integer value, shifted in format. So, I used integer arithmetical
operations, instead.
The modulo 256 results in a value between 0 and 255, and fits within 8 bits.
The division by 256 results in a value that is 8bits smaller than the
original value.
Thus, I compute the low-order octet of the 2-octet network-byte-order opcode
using the modulo 256, and I compute the high-order octet of the 2-octet
network-byte-order opcode using division.
Perhaps I /should/ have used logical operations....
header.opcode[1] = opcodeValue & 0xff;
header.opcode[0] = (opcodeValue>>

& 0xff;
>
>> /* set header filename from fileName string */
>> src = dst = 0;
>> do
>> header.data[dst++] = fileName[src];
>> while (fileName[src++] != 0);
>>
>> /* set header Mode from modeName string */
>> src = 0;
>> do
>> header.data[dst++] = modeName[src];
>> while (modeName[src++] != 0);
>
> The two do functions above I don't quite understand.
The TFTP protocol header wants two variable-length strings to be packed
together in one array, with each string terminated by a zero-value sentinal
byte.
So, that's what we do.
We first copy the filename string, including the zero-valued string
terminator, into the header's array. Following the zero-valued string
terminator of the filename in that array, we copy the mode string,
including the zero-valued string terminator.
The length of the entire TFTP header is variable, and is
the length of the two octet opcode
plus the length of the variable-length filename string (including the \0)
plus the length of the variable-length mode string (including the \0)
> VLAs? Do you mean variable length addresses?
No, I mean Variable Length Arrays. Arrays for which the compiler will
allocate space and compute the length dynamically.
> C99 or 89 whichever's best to implement this.
>
>> /* write out the header */
>> fwrite(header,sizeof(header.opcode) + dst, 1, connection);
>
> understood the fwrite.
>
> Bill
>
>
--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
Me:
http://pitcher.digitalfreehold.ca/ | Just Linux:
http://justlinux.ca/
---------- Slackware - Because I know what I'm doing. ------