And so many further code changes. DIFF between v4.17 and v5.00 is some 700kB
Hope I described the most important changes.
73 Joachim, DL8HBS@DB0GR.#BLN.DEU.EU
back to content page
B. System Identifiers (SID)
A system identifier for forwarding systems is created with the following syntax:
[<system_name>-<version_number>-<command_set>]
The most important field is the <command_set>. The existing characters indicate a protocol feature. They may be followed by a number, this indicates the protocol revision.
Lets investigate DP's SID:
[DP-4.17-AB1D1FHMR$]
A = ACK messages known
B = huffman compression, only in conjunction with F
B1 = extended compressed protocol, resume and CRC added.
D = extended board names (8 chars), improved CRC
D1 = block crc mode in compressed forward
F = message exchange in blocks of 5, syntax of F6FBB
H = hierarchical addresses accepted
M = Message ID's accepted (BID's of private mails)
R = extended reject messages as defined by AA4RE
$ = Bulletin ID's accepted (I am really a BBS)
back to content page
C. The Forward Protocols
DPBOX uses seven different forward protocols
1) W0RLI
2) TheBox
3) F6FBB version 1
4) DPBOX version 1
5) F6FBB version 2 (resume mode)
6) DPBOX version 2 (resume mode)
7) DPBOX version 3 (as 6, additional block CRCs)
The complete fbb style forward protocol will be described after this survey.
The differences between 3) and 4) are some extensions made for proper use in the German network.
The DPBOX forward protocol compared with F6FBB compressed protocol:
It is indicated by the presence of the letter 'D' in the SID.
Proposals are started with FD instead FA / FB.
The checksum of the proposals is a CRC-16 in hexadecimal notation, sent LSB -> MSB. For computation of the CRC, only the text content of the proposals without <CR> is regarded. The CRC is pre-loaded with 0.
Example:
FD P DL8HBS DB0EAM.#HES.DEU.EU DL3AAA 31310ADL8HBS 700
FD B DL8HBS DL SYSOP 32670BDL8HBS 1508 60
FD B DL8HBS EU STANDARD 32670CDL8HBS 6987 365
(... up to five ...)
F> A7CF
Boards may count 8 signs. Optionally, a lifetime is added (last parameter of proposals 2 and 3). A lifetime is the count of days after which a message shall be deleted.
The message exchange is using YAPP, as F6FBB does. The only difference is the end_of_transmission - block: Instead of a 1 byte checksum it contains a 2 byte CRC-16, LSB -> MSB. The CRC is computed over the content of all blocks transmitted before, including the title block. It is pre-loaded with 0.
The difference between 5) and 6) is the altered proposal protocol for 6) as in 4), additionally, the CRC of 6) is extended via the message title. 5) only CRCs the message body. Note that F6FBB uses a very special CRC calculation method.
The difference between 6) and 7) is the block CRC appended to each transmitted block, forcing the receiving bbs to disconnect immediately at detection of a transmission error.
back to content page
D. Presence of Letter D in SID
The presence of letter "D" in SID assumes (except of later on described extensions to the f6fbb forward protocols) the following:
1) Ability of understanding single line messages to boards "M" and "E"
2) Ability of processing full binary messages
3) Acceptation of board names with up to 8 signs
4) Acceptation of lifetimes in proposed forward
Description:
1) Ability of understanding single line messages to boards "M" and "E"
German net standard requires the exchange of home bbs information in board "M" and remote erase commands in board "E".
The format of both is simple:
MyBBS (respectively HomeBBS) information in board "M" are transmitted to M@THEBOX (where @THEBOX may be changed) with this syntax:
SB M@THEBOX < Sender $BID <HomeBBS> <UNIX Time> CTRL-Z
Sender is the users call entering a new home bbs, $BID is generically, <HomeBBS> is the new home bbs (may be hierarchical addressed too), <UNIX Time> is the update time in Unix time format plus 4 hours (dunno why).
Each field is separated by spaces.
This standard is NOT my choice, I prefer the WP standard. But for supporting the "D" extensions, you have to detect such mails.
Remote Erase messages in board "E" are transmitted to E@THEBOX (where @THEBOX may be changed) with this syntax:
SB E@THEBOX < originating_bbs $BID <eraseBID> CTRL-Z
originating_bbs is the bbs the remote erase was released, $BID is generically, <eraseBID> is the BID that shall be deleted in your bbs.
Each field is separated by spaces.
If you want to support the letter "D" in your SID but do not want to support the above features, simply answer to every received line with OK or NO and a ">" in the next line and trash the received line.
2) Ability of processing full binary messages
Supporting letter "D" in your SID means that your bbs system is aware of receiving full binary messages in forward. This happens the following way:
At any position of the forwarded message a binary header may be sent.
A binary header has at least the following format:
<CR>#BIN#<Size><CR>
but mostly has the format
<CR>#BIN#<Size>#|<CRC>#$<date>#<filename><CR>
Except BIN and <Size>, each field may be present or not. <filename> may even consist of a path and a name. The path may contain "/" and "\" and ":" .
The least your bbs has to do is storing the binary header to the receive file and then storing transparently <size> (decimal) bytes of data following the binary header and then prompting '>' or (if in batch fbb forward) being prepared for the next file.
As most other "D" - supporting BBS will send a <CRC>, you should check the CRC of the received binary with the sent one. Used CRC calculation is crcthp (see section "Calculating CRCs" in this document) In case of inequality, you should (if in ASCII forward mode, not in fbb batch forward mode) delete the received file and prompt a "|>" instead of ">" - this allows the sending bbs to take the file out of the forward after some erroneous transmissions. If in fbb batch forward mode, crc errors are corrected by the overlaying protocols, if in ascii fbb batch forward mode (who does so?) you have a problem and should disconnect and delete the received file.
The binary file transfer is an essential of the "D" mode, you cannot override it by any tricks. Compressed fbb forward by its nature has absolutely no problems transferring such files, but due to the fact that no local user nor local ASCII forward bbs of the receiving FBB bbs can read out such a file undistorted (it will be stripped of the eighth BIT), binary files are NEVER sent to bbs not having the "D" in the SID.
Refer to the description of the AutoBIN protocol later in this document. Note: other than described there (I didn't write it), a BBS never sends an acknowledgement ("#OK#") to a forwarding bbs nor waits for one nor sends a "#NO#". There is only one case your bbs will send an "#OK#" - when a local user starts a binary upload to the bbs sending a binary header after opening an input file with SB or SP.
Think about the implications of the full binary processing: You will no more need 7PLUS uploads, even not for splitting the message in parts, as FBB and DPBOX support resume mode (recovering crashed forward connects at the point the forward was interrupted, so, big files are no problem at all). You will never see any 7PERR messages, because beside the error protection of the FBB compressed forward, you also have an error protection on those weak ASCII forward links (binary protocol includes a CRC, read above).
3) Acceptation of board names with up to 8 signs
Well, this is a simple thing. If you do not want to support board names with 8 signs, simply cut them after the sixth sign in received forward. If you send a board with only 6 signs, lets say "KENWOO" that is known in DPBOX on the receiver side as "KENWOOD", it is expanded automatically while reception.
This means that for supporting letter "D" in SID, you only have to take care that your bbs does not crash when receiving a proposal with up to 8 signs in the board name.
4) Acceptation of lifetimes in proposed forward
Accepting lifetimes in forward means that in ASCII forward your BBS accepts or disregards lifetime settings in the proposal. Lifetimes are no essential for the net, if they are supported its fine, if they aren't, who cares.
A lifetime setting means that the received mail shall be deleted after the given count of days. This is a proposal by the originator of the message, not a must.
When forwarding a lifetime setting to another bbs, you have to deduct the days the message waited for forward in your bbs from the received lifetime setting.
Lifetimes are transmitted the following way:
SB BBS@EU < DL1XYZ $BID #10
but also:
SB BBS@EU < DL1XYZ $BID # 10
In this case, lifetime of the mail is set to 10 days in the receiving bbs.
If you want to support the letter "D" in SID, you may evaluate the lifetime setting in the proposal, but you won't have to.
On the other hand, you may send messages in forward without lifetime field and still presenting the "D" in your SID.
The lifetime setting is completely optional. It is nice if it is supported (as it helps sysops doing their job by deleting messages prematurely), but it is no must.
What's left: the minimum standard to support the "D" feature in SID reads as follows:
1) Accept incoming single line M and E messages, but trash them
2) Support full binary message exchange in forward and user interface
3) Accept board names with 8 signs but cut them to 6
4) Accept additional lifetime settings in proposals but trash them. Send without.
back to content page
E. Compressed Forward Protocol Description
Written January 1993, corrected August 1993, May 1994, extended April 1996.
Translated to English April 1996.
09.04.96:
This description tries to focus the main essentials of F6FBB type forward. Unfortunately, the requirements for the german bbs network (boards may count up to 8 signs, a lifetime may be added to each mail) lead to a confusing variety of different substandards of the protocol. I can't help it, the system grew in time, and from today's point of view, most standards are obsolete. But this is the whole story:
Up to today, F6FBB defined three evoluting steps of his protocol:
1) Mails are proposed and sent in batch forward, 5 at a time (but in ASCII).
2) as 1), additionally they are compressed with a simple LZH.
3) as 2), additional CRC and crash recovery (resume), allowing restart of forward transmission at the position the previous connect crashed (even within a mail).
In DPBOX there is an addition to step 3) of the protocol:
4) as 3), but includes block CRCs for every transmitted block.
Required by german bbs net standards, I had to add specific extensions to every protocol step. Each one was extended with the possibility to transfer so called "lifetimes" (a number of days after which the message shall be deleted) and extended board names with up to 8 signs, not only 6 as usual. Additionally, the transfer is locked against transmission errors by CRCs. In step 2), fbb forward had no CRC at all, in step 3) only over the message body, not over BID and subject field.
Further, I will refer on step 1) / 2) / 3) and the addition "D". "D" means DL or DL8HBS or whatever.
Step 1)
Extracts of f6fbb's original documentation:
APPENDIX -6- FBB Forward Protocol.
FBB software includes two forward protocols. The first one is standard with MBL/RLI protocol. The second one was developed to allow efficiency, particularly on long links where propagation time of data are long. The exchange of commands is reduced to a minimum, and not acknowledged to get time. The data transfer direction is changed every block of data, a block of data holding up to five messages. This uses the "pipeline" effect of long links (Nodes and digipeaters), and gain some time over short links (HF...).
FBB protocol is very simple in its principle. It is based on MID/BID usage. The identification is made by the F letter in the SID (system type identifier contained in square brackets). All command lines must start in first column with the 'F' character. All command lines are ended by a return (CR) character.
Suppose I call another BBS to forward some mail. When I connect another BBS using FBB protocol, I will receive the SID followed by a text and the prompt (">"). If the SID contains the F flag, I will send immediately my SID and the first proposal.
Proposals looks like :
FB P F6FBB FC1GHV FC1MVP 24657_F6FBB 1345
F> HH
FB : Identifies the type of the command (proposal)
P : Type of message (P = Private, B = Bulletin).
F6FBB : Sender (from field).
FC1GHV : BBS of recipient (@field).
FC1MVP : Recipient (to field).
24657_F6FBB : BID or MID.
1345 : Size of message in bytes.
F> : End of proposal.
HH is optional. It is the checksum of the whole proposal in hexadecimal.
ALL the fields are necessary. This kind of command must hold seven fields. If a field is missing upon receiving, an error message will be send immediately followed by a disconnection.
A proposal can handle up to five FB command lines. If the total size of messages seems to be too important, the proposal can handle less lines. In FBB software, a parameter is defined in INIT.SRV file to tell the maximum size of the message block. It is set by default to 10KB.
Example of proposal :
FB P F6FBB FC1GHV.FFPC.FRA.EU FC1MVP 24657_F6FBB 1345
FB P FC1CDC F6ABJ F6AXV 24643_F6FBB 5346
FB B F6FBB FRA FBB 22_456_F6FBB 8548
F> HH
This proposal is limited to three FB lines, as the amount of messages overran the 10KB limit.
When receiving the proposal, the other BBS will reject, accept or defer the message. This command is made by a FS line :
FS -+=
This means :
- I don't want the first message (-).
- I need the second message (+).
- I defer the third message, as I'm still receiving it (=).
It should interesting to defer a message if you are still receiving it on a other channel, or if you think that the size is to big, or for another reason. The message should be proposed again at the next connection.
FS line MUST have as many +,-,= signs as lines in the proposal.
When receiving the FS lines, I can send the block of messages. Each message is made with the title on the first line, the text, and a Ctrl Z in the last line. The is no blank line between the messages.
Title of 2nd message
Text of 2nd message
.....
^Z
When the other BBS has received all the asked messages, it acknowledges by sending its proposal, and the system is reversed.
If it has no message to send, it only sends a line :
FF
This line must not to be followed by a F>.
If the other hand has no message, it sends a line :
FQ
and asks for the disconnection.
Example :
F6FBB FC1GHV
----------------------------------------------------------------
Connects FC1GHV
Connected
[FBB-5.11-FHM$]
Bienvenue a Poitiers, Jean-Paul.
>
[FBB-5.11-FHM$] (F6FBB has the F flag in the SID)
FB P F6FBB FC1GHV.FFPC.FRA.EU FC1MVP 24657_F6FBB 1345
FB P FC1CDC F6ABJ F6AXV 24643_F6FBB 5346
FB B F6FBB FRA FBB 22_456_F6FBB 8548
F> HH
FS +-+ (accepts the 1st and the 3rd).
Title 1st message
Text 1st message
......
^Z
Title 3rd message
Text 3rd message
......
^Z
FB P FC1GHV F6FBB F6FBB 2734_FC1GHV 234
FB B FC1GHV F6FBB FC1CDC 2745_FC1GHV 3524
F> HH
FS -- (Don't need them, and send immediately the proposal).
FB P FC1CDC F6ABJ F6AXV 24754_F6FBB 345
F> HH
FS + (Accepts the message)
Title message
Text message
......
^Z
FF (no more message)
FB B F6FBB TEST FRA 24654_F6FBB 145
F> HH
FS + (Accepts the message)
Title message
Text message
......
^Z
FF (still no message)
FQ (No more message)
Disconnection of the link.
In this example, FBB protocol is used as the two BBS were identified by the F flag in the SID. If F6FBB had sent the SID [FBB-5.11-MH$] when answering FC1GHV, the protocol should be the standard MBL/RLI.
All callsigns are only examples !
End of F6FBB extract
Step 1D) is only slightly modified compared with step 1). The SID must contain a "D" (for example [DP-3.53-DFHM$]). Proposals then would be:
FD P DL8HBS DB0EAM DL3AAA 31310ADL8HBS 700
FD B DL8HBS DL SYSOP 32670BDL8HBS 1508 60
FD B DL8HBS EU STANDARD 32670CDL8HBS 6987 365
(... up to five ...)
F> A7CF
The "D" in "FD" signifies a transmission in the 1D) format. The 16-bit hexadecimal value after F> is a CRC over all bytes of the proposal lines except the line break (CR). It may be left out, but if it is present and unequal to the one calculated on the receiver side, the connection will be disconnected. CRC is of type crcthp (as for the autobin protocol, look at the end of this manual), preloaded with 0.
Obviously, board names may count up to 8 signs. A lifetime may be appended as last field to a proposal line (third proposal, lifetime 365 days).
A proposal is defined this way:
FD B DL8HBS ALL ATARI 564323DL8HBS 3456 60
^ ^ ^ ^ ^ ^ ^ ^
I I I I I I I Lifetime (optional)
I I I I I Bulletin-ID Size in Bytes of unpacked
I I I I I file
I I I I board (or callsign)
I I I I
I I I @mbx-field
I I Sender
I Type, [B]ulletin or [P]rivate or [A]cknowledge or N[T]S
I
Flag
Of course, depending on the "H" flag in SID, hierarchical addresses are valid, too.
Step 2)
Extracts of F6FBBs documentation
APPENDIX -7- Extension to the protocol. Compressed forward FBB.
The protocol utilised for the transfer of ASCII files compressed is an extension to the existing protocol. The compressed forward is validated by the presence of the letter B in the SID [FBB-5.12-BFHM$]. The transfer of compressed files can only take place under FBB protocol. The presence of the letter B in the SID without the F letter will remain without effect.
The only difference as regard to the standard protocol is the submit line. It can specify the type of data contained in the compressed message. FA means that the transfer will be an ASCII compressed message. FB means that the message will be a binary compressed file (this last possibility is not yet implemented in the version 5.12).
The submission of an ASCII message will be in the form :
FA P FC1CDC F6ABJ F6AXV 24754_F6FBB 345
The submission of a binary file will be in the form :
FB P FC1CDC F6ABJ F6AXV 24754_F6FBB 345
*** remarks by DL8HBS: type FB of transmission is not supported by DPBOX.
*** DPBOX supports full binary mail transfer in all modes.
The transferred data are of a specific format. The transfer will be done in binary mode. This last one is derived of the YAPP protocol which is very reliable. All transfer is made of a header, a block of data, an end of message and a checksum. Each transfer is equivalent to the transfer of one message of the standard protocol and shall not be followed by a control Z, the end of file specifier is defined in another way.
Format of header for an ASCII compressed message (submission FA) :
<SOH> 1 byte = 01 hex
Length of the header 1 byte = Length from the title,
including the two <NUL> characters.
Title of the message 1 to 80 bytes
<NUL> 1 byte = 00 hex
Offset 1 to 6 bytes
<NUL> 1 byte = 00 hex
Format of header for a binary compressed file (submission FB) :
<SOH> 1 byte = 01 hex
Length of the header 1 byte = Length from the filename,
including the two <NUL> characters.
Name of the file 1 to 80 bytes
<NUL> 1 byte = 00 hex
Offset 1 to 6 bytes
<NUL> 1 byte = 00 hex
As to follow the French regulation, the title of the message or the file name are transmitted in ASCII, not compressed.
The offset is also transmitted in ASCII and specifies the offset at which the data should be inserted in the file (in case of a fragmented file). In the version 5.12, this parameter is not utilised and is always equal to zero.
A data block contains from one to 256 bytes. It begins by two bytes which specify the format.
Data block format :
<STX> 1 byte = 02 hex
Number of data 1 byte = 00 to ff hex. (00 if length = 256 bytes).
Data bytes 1 to 256 bytes
The last data block is followed by the end of file specifier and the checksum.
End of file specifier format :
<EOT> 1 byte = 04 hex
Checksum 1 byte = 00 a ff hex
The checksum is equal to the sum of all the data bytes of the transmitted file, modulo 256 (8 bits) and then two's complemented.
The checking of the checksum is very simple :
The sum of the data's from the file and the checksum received modulo 256 (anded with FF) shall be equal to zero.
In case of a checksum error, the message or the file is not taken to account and the system issues a disconnect request after having sent the comment :
*** Checksum error
End of F6FBB extract
Step 2D)
"F", "D" and "B" must be present in the SID.
Only change compared with step 2) is the format of the proposals (see step 1D) ) and the locking of the transmitted compressed data's with a CRC. Again, the CRC is of type crcthp (see section "Calculating CRCs" at the end of this manual).
The CRC is transmitted in the EOT block (see step 2) ).
<EOT> 1 byte = 04 Hex
CRC 2 bytes, LSB first, then MSB.
The CRC counts over all data bytes of all preceding blocks, this includes the content of block 1), the subject with offset and the two zeroes. Only block identifiers and block length bytes are blanked out.
If the receiver calculates another CRC, it disconnects.
Step 3)
Preliminary: As far as I know, there is no released document from F6FBB explaining this protocol step. Use these information with caution, protocol may change.
Please honour the work of DG0FT. The assertion of the protocol took a complete weekend of work by him (in early 1993). He detected the used CRC algorithm, and this is not as simple as it seems. Thank you for your support, René.
The SID must contain "B1" and "F".
Example : [FBB-5.15c-AB1FHMR$]
Principally, transmission looks like in step 2). The YAPP-encoded file however is leaded by a CRC at the beginning. The CRC only counts over the body of the packed message, it does not cover the subject block.
The algorithm uses the CCITT CRC table, but a different calculation method:
CRC = (CRC << 8) ^ CRC_TABLE[(CRC >> 8) ^ DATA]; /* Credits to DG0FT! */
Except the CRC, no change yet compared with step 2).
But lets see what happens in case of a link failure while transmission:
The receiving BBS counts the amount of data's received with the penultimate YAPP block (this one was the last one completely received) and sends, if the interrupted file gets proposed once again, instead of
FS +
FS !1250
(for example). This means that file transmission shall be resumed at offset 1250.
Receiving a multi-proposal, the answer could look like:
FS +!1250-
The transmitting bbs now will send the interrupted file again, with a complete title block, but the OFFSET in this block is not set to 0 but to the demanded resume position (1250 in this example), followed by a short data block containing the first six bytes of the message (this is the CRC and the size of the uncompressed message, as LZH always puts that information in the first four bytes of a compressed file). After these two blocks, the remainder of the message follows in YAPP protocol, starting with the demanded OFFSET.
Step 3D)
"B1", "F" and "D" must be present in SID.
Example: [DP-3.53-AB1DFHMR$]
Step 3D) unites the advantages of step 2D) and 3).
It supports boards with a length of 8 signs and lifetimes (as generally with the "D" extension). The format of the proposals is as with 1D) or 2D). Note: CRC over the proposals still is in crcthp format!
The message itself will be transmitted exactly as with step 3), except for the CRC calculation. The CRC of step 3D) includes the subject, but, different to previous "D" - extensions, only all valid bytes of the subject, NOT the offset (it changes) and not the NULL bytes. The subject is CRCed prior to the message data's. NOTE: 3D) also uses the CRC algorithm of F6FBB, as does step 3). Step 2D) used another CRC algorithm, but that was at a time when fbb did not provide CRCs at all.
Step 4D)
As you will remark, this protocol is an extension to protocol 3D). There is no equivalent in F6FBB protocols.
"B1", "F" and "D1" must be present in SID.
Example: [DP-4.16-AB1D1FHMR$]
Uploading big messages, it often happens that the upload runs without interruption but after complete reception is disconnected with a "*** CRC error". This is annoying, at least if you managed to upload say 400k of a new bbs version via a remote HF channel.
What has happened?
Due to the unprotected data exchange in wa8ded hostmode, some bits of your upload got corrupted by a receiver overrun of the local bbs computers UART. This even happens with 16550 FIFOs running Linux (but very seldom).
The CRCing of the complete file avoided storage of the damaged file, but instead it would be better stopping the upload at the YAPP block where the error occurred instead of waiting till the end of file.
This lead to the implementation of step 4D). The difference compared with step 3D) is very simple: each transmitted YAPP block contains a CRC over its content (crcfbb, as the overall file CRC). The CRC is appended to the data field of the block. If the receiver detects a different result in computing the block CRC, it disconnects the connection and stores its resume offset to the end of the last completely received block.
No, no one promised that everything in this definition is logical and simple. As you easily can see, it is a protocol system grown by time. With the above information at your hands, it should be possible to implement the whole protocol suite in your own program.
Some further annotations:
Implementation problems of f6fbb's protocols usually have two reasons:
1) The compression method
2) The checksum of the proposals
1): The LZH as is used for f6fbb uses (different to the usual implementations of the LZH code) a string buffer size of 2048 bytes instead of 4096 bytes. Sending mails with a size bigger than 2048 bytes to a fbb bbs results in destroyed message contents if the sender used a 4096 bytes buffer for encoding. (DPBOX uses a buffer size of 4096 bytes for decoding, so, don't wonder if your program is able to send mails to a DPBOX but not to an FBB).
2): checksum computation in FBB proposals. Excerpt of a mail of F6FBB:
From version 5.14, there is an optional checksum at the end of the proposals. If the checksum exists, then the proposals will be checked.
It is simply computed :
Warning, there is no LF character and the CR is included in the checksum computation !
static char checksum(char *s)
{
char chck = 0;
while (*s)
{
chck += *s;
++s;
}
return(chck);
}
send_proposals(void)
{
char chck = 0;
int ...
for (p=0 ....
{
sprintf(s, "F%c %c %s %s %s %s %ld\r", ...
chck += checksum(s);
out_ascii(s);
}
sprintf(s, "F> %02X\r", (-chck) & 0xff) ;
out_ascii(s);
}
When receiving, the checksum of the proposals added the received checksum must be equal to zero.
73 Qro. Jean-Paul, F6FBB @ F6FBB.FMLR.FRA.EU
CRC computation for proposals in "D" protocol types does NOT include the CRs, as was noted in description of step 1D) !
Let me express my thanks to Jean-Paul, F6FBB, for the invention of the compressed AND batched forward protocols. I just aligned them for proper use in the german net. And, again, thank you René, DG0FT, for your work spent on these items helping me to implement it correctly.
back to content page
F. The Message Base Format
The DPBOX message base is held in the folders box/indexes/ and box/infofiles/ . Each existing board is represented by one index file (in box/indexes/) and one content file (in box/infofiles/).
The index file is an array of structures describing each file saved in the content file. The first array in the index represents message 1 in the board and so on. Deleted entries are only marked as deleted, the physical erase and reorganisation of the message base is performed while nightly garbage collection.
Indexes and contents are locked with checksums. Changing one bit in the files will make them invalid and the garbage collection will try to delete the changed entries.
In result, you only have read access on the information stored in the message base. You are not allowed to add or change information externally.
Each index file consists of an array[1..n] of indexstruct, where indexstruct is defined as follows:
typedef struct indexstruct {
uchar header_version; /* is 20 in this version */
Char bulletin_id[13]; /* BID */
Char destination[9]; /* board */
Char originator[7]; /* sender */
Char mbx[41]; /* @mbx */
Char subject[81]; /* subject */
long rxdate; /* locally received at */
long txdate; /* originally created at */
unsigned short lifetime; /* local liftetime */
unsigned short txlifetime; /* original lifetime */
Char msgtype; /* A/B/P/T */
uchar r0; /* not to be changed */
long start; /* start position in file */
long packsize; /* packed message size */
long size; /* unpacked message size */
long rxqrg; /* received on qrg (unused)*/
Char rxfrom[7]; /* received from bbs */
boolean deleted; /* logically deleted */
uchar content_type; /* content encoding */
uchar level; /* access level */
uchar fwdct; /* forward counter */
unsigned short msgflags; /* msgflags (see MSGFLAGS) */
long erasetime; /* erased at */
long lastread; /* last read at */
unsigned short readcount; /* readout counter */
Char read_by[141]; /* reader field */
uchar erased_by; /* erased by (see EBFLAGS) */
Char sendbbs[7]; /* originating bbs */
uchar reserved; /* zeroed in this version */
long msgnum; /* message number */
unsigned short r1, r2, r3; /* not to be changed */
} indexstruct;
/* MSGFLAGS */
#define MSG_SFWAIT 1
#define MSG_PROPOSED 2
#define MSG_SFRX 4
#define MSG_SFTX 8
#define MSG_SFERR 16
#define MSG_SFNOFOUND 32
#define MSG_CUT 64
#define MSG_MINE 128
#define MSG_REJECTED 256
#define MSG_DOUBLE 512
#define MSG_BROADCAST 1024
#define MSG_BROADCAST_RX 2048
#define MSG_OWNHOLD 4096
#define MSG_LOCALHOLD 8192
#define MSG_SFHOLD 16384
#define MSG_OUTDATED 32768
/* bit values for content_type */
#define PM_HUFF 4 /* LZH compression */
#define TTEXT 0 /* ASCII mail */
#define TBIN 32 /* binary mail */
#define T7PLUS 64 /* 7PLUS mail */
#define THTML 128 /* HTML mail */
/* EBFLAGS (erased_by in indexstruct) */
#define EB_NONE 0
#define EB_SENDER 1
#define EB_RECEIVER 2
#define EB_SYSOP 4
#define EB_RSYSOP 5
#define EB_DOUBLESYSOP 6
#define EB_LIFETIME 8
#define EB_SF 16
#define EB_REMOTE 32
#define EB_SFERR 64
#define EB_RETMAIL 66
#define EB_TRANSFER 128
Note that the gcc aligns the size of the structure to a size dividable by four.
back to content page
G. The Check List Format
DPBOX creates a "check list" while garbage collection: box/stat/msglist.box.
The file is used for the output of the CHECK command. The content is a subset of the content of the index files. Every relevant change in index files is projected on the check list too.
The check list is not locked with checksums, as invalid data herein causes no conflicts in forward. However, also the information represented in these files should not be changed, as it makes no sense at all.
Check lists are an array[1..n] of the following structure:
typedef struct boxlogstruct {
long msgnum; /* message number */
long rxdate; /* rxdate */
unsigned short idxnr; /* #nr in index/board */
unsigned short lifetime; /* local lifetime */
unsigned short msgflags; /* msgflags (see MSGFLAGS) */
long size; /* unpacked message size */
boolean deleted; /* logically deleted */
Char msgtype; /* A/B/P/T */
uchar content_type; /* content encoding */
uchar level; /* access level */
Char destination[9]; /* board */
Char obrett[9]; /* original board */
Char bulletin_id[13]; /* BID */
Char originator[7]; /* sender */
Char mbx[7]; /* @mbx (shortened) */
Char subject[41]; /* subject (shortened) */
} boxlogstruct;
/* MSGFLAGS */
#define MSG_SFWAIT 1
#define MSG_PROPOSED 2
#define MSG_SFRX 4
#define MSG_SFTX 8
#define MSG_SFERR 16
#define MSG_SFNOFOUND 32
#define MSG_CUT 64
#define MSG_MINE 128
#define MSG_REJECTED 256
#define MSG_DOUBLE 512
#define MSG_BROADCAST 1024
#define MSG_BROADCAST_RX 2048
#define MSG_OWNHOLD 4096
#define MSG_LOCALHOLD 8192
#define MSG_SFHOLD 16384
#define MSG_OUTDATED 32768
/* bit values for content_type */
#define PM_HUFF 4 /* LZH compression */
#define TTEXT 0 /* ASCII mail */
#define TBIN 32 /* binary mail */
#define T7PLUS 64 /* 7PLUS mail */
#define THTML 128 /* HTML mail */
back to content page
H. The Auto Router Data Base
The auto router database is fed with information by the header analysis of each incoming mail. It is used for smart routing capabilities of DPBOX and for automatic expansion of hierarchical bbs calls. You can check its content with the BBS command.
The database is stored in box/stat/hpath.box.
Its content is not locked with checksums, however, don't change its content while runtime of DPBOX as the data base is indexed by an automatic hashing algorithm.
There is one exception: you may delete one entry by overriding the call field of the structure with '******' to delete it, if you think a bbs should be deleted from the table. Normally, this is performed whilst garbage collection after 12 month of inactivity from that bbs.
Do not touch the other fields. Do not edit the content with text editors. Crashes are on your side.
The database in hpath.box is an array[1..n] of the following structure:
typedef struct hboxtyp {
Char call[7]; /* BBS-Call */
Char hpath[41]; /* hierarchical path */
Char bestvia[7]; /* best rx via */
Char rxfrom[7]; /* best path received from */
Char desc[41]; /* BBS info */
long lasttx; /* last TX date */
long msgct; /* count of messages */
long best; /* fastest runtime of msg */
long average; /* average runtime of msgs */
long bytect; /* count of received bytes */
long change_date; /* best path changed at */
} hboxtyp;
back to content page
I. The HomeBBS Data Base
The home bbs information of users is stored in the file box/stat/mybbs.box.
It is updated by local usage of the MYBBS command, by incoming M-Mails (german standard) and by incoming WP update messages of type /U (user set). Guessed entries of WP messages are not used for updating.
The file is not locked by checksums. However, don't change its content while DPBOX is running. DPBOX uses different caching mechanisms to speed lookup in this file, and any change whilst runtime will confuse the caching completely.
Additionally, home bbs information for local users (those one that connected your bbs at least once in the past year) is held in the box/indexes/M.IDX database, too. Information held therein overrides the setting in box/stat/mybbs.box (but is, if you didn't patch in mybbs.box, the same).
Better you open that file read only.
The database in mybbs.box is an array[1..n] of the following structure:
typedef struct mybbstyp {
Char call[7]; /* Call */
Char bbs[7]; /* MyBBS */
long updatetime; /* last updated at */
} mybbstyp;
back to content page
J. The DPBOX Socket Interface Specification
As is described more detailed in the TNT documentation, for connection to the outside world, DPBOX uses a Unix Socket Interface.
All communication with the DPBOX daemon is handled via this interface. Multiple interfaces may be opened at the same time. Except general file system access by DPBOX, no other input/output is done by the BBS. This is the vital interface.
You might be interested in the full layout of this interface if you want to write an own driver for DPBOX, e.g. a PACTOR driver or similar.
Erroneous implementation of the protocol WILL lead to crashes, there is no syntax check in the receiving code of DPBOX.
The interface was developed by Mark, DL4YBG. Its layout covers a general purpose of connecting terminal programs to data processing applications via socket interfaces. The use by DPBOX is only one possible implementation.
For this reason, data direction indicators in the below definition vary between the names "PR", "Program" and DPBox". In general, "PR" is the program DPBOX is connected to (usually supporting the access to the packet radio network), "Program" and "DPBox" siginify the part of DPBOX.
Definition of the protocol was made from the point of view of TNT. If in doubt what happens at specific actions, investigate the TNT source code and make your own program behave the way TNT does.
Description of Socket-Interface-Protocol Rev.2
Mark Wahl, DL4YBG
Created: 26.11.94
Last Update: 13.04.96
0. General Layout
Indicator (1 Byte)
Channel (2 Byte)
Usernr (2 Byte)
Length (2 Byte)
Data (Length Bytes)
1. Commands
1.1 Activate Program
(PR->Program)
On the specified channel the linked program (defined by used socket)
shall be activated (the interface will be opened).
If channel is 0, the activation is started from the operator console
instead of a packet channel.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE + (strlen(callsign) + 1)
Command (4 Byte)
CMD_ACTIVATE
Callsign ((strlen(callsign) + 1) Byte)
char callsign[]
1.2 Deactivate Program
(PR->Program)
On the specified channel the linked program (defined by used socket)
shall be deactivated (the interface will be closed).
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_DEACTIVATE
1.3 Connect
(Program->PR)
A free channel shall be used to build up a connection. QRG, Source call,
Destination call and a connection-build-up-time-out must be specified.
The connection will be build up using xconnect-feature, therefore no
digipeaterpath is allowed.
The user 'usernr' will be informed about the result of the connect,
successful or not.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_CONNECT + (strlen(sourcecall) + 1) + (strlen(destcall) + 1)
Command (4 Byte)
CMD_CONNECT
Timeout (4 Byte)
int timeout
Qrg (20 Byte)
char qrg[20]
Sourcecall (strlen(sourcecall) + 1)
char sourcecall[]
Destcall (strlen(destcall) + 1)
char destcall[]
1.4 Disconnect
(Program->PR)
The connection on the specified channel shall be disconnected.
Indicator (2 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_DISCONNECT
1.5 Finish Program
(Program->PR)
If the program was started directly (using special SSID), the connection
will be disconnected.
Otherwise a reconnection to the last used command processor will occur
(reconnect to terminal/node-software).
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_FINISH
1.6 Channel Status
(PR->Program)
If the number of frames in the TX-buffer (Program and TNC) has changed
on a channel linked to a program, a channel status message with the
new number of frames in TX-buffer will be sent.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_CSTATUS
Command (4 Byte)
CMD_CSTATUS
Number of frames in TX-buffer (4 Bytes)
int snd_frames
1.7 Blocking
(Program->PR, PR->Program)
If blocking is received, the sending side has reached maximum byte count
and is waiting for an unblocking message. Otherwise no data will be
transmitted.
This is a simple handshake to avoid an overrun of the socket.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_BLOCK
1.8 Unblocking
(Program->PR, PR->Program)
unblock restarts the transmitter on the other side of the interface.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE
Command (1 Byte)
CMD_UNBLOCK
1.9 Sort new mail
(PR->DPBox)
A mail was collected from monitor or during connect with a mailbox.
Pattern is the filename of the used file, Rcall is the callsign of
the mailbox where this file was fetched (or an empty string). Not
used for S&F connects, only for monitoring features.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(pattern_) + 1) + (strlen(rcall) + 1)
Command (4 Byte)
CMD_SORT_NEW_MAIL
Pattern ((strlen(pattern_) + 1) Bytes)
char pattern_[]
Rcall ((strlen(rcall) + 1) Bytes)
char rcall[]
1.10 SF Rx EMT
(PR->DPBox)
A mail for folder 'E', 'M' or 'T' was received. These mails consist only
of one line. This line will be sent directly in Eingabe. Not used for
S&F connects, only for monitoring features.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(eingabe_) + 1)
Command (4 Byte)
CMD_SF_RX_EMT
Eingabe ((strlen(eingabe_) + 1) Bytes)
char eingabe_[]
1.11 Connect for Store and Forward
(DPBox->PR)
A free channel shall be used to build up a connection for Store and
Forward. Sourcecall, Destinationcall and a connection-build-up-timeout
must be specified.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_BOXPBOXSF + (strlen(sourcecall) + 1) + (strlen(destcall) + 1)
Command (4 Byte)
CMD_BOXPBOXSF
Timeout (4 Byte)
int timeout
Sourcecall (strlen(sourcecall) + 1)
char sourcecall[]
Destcall (strlen(destcall) + 1)
char destcall[]
1.12 Disconnect
(DPBox->PR)
The connection on the specified channel shall be disconnected.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_BOXPRDISC
1.13 Abort Store and Forward
(DPBox->PR)
Store and Forward shall be cancelled. If Immediate is not 0, outstanding
TX-Packet must be cancelled, too.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (4 Byte)
LEN_BOXPABORTSF
Command (4 Byte)
CMD_BOXPABORTSF
Immediate (4 Byte)
int immediate
1.14 Abort Routing
(PR->DPBox)
A Connect command for Store and Forward sent by DPBox (CMD_BOXPBOXSF) was
not successful.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE + (strlen(callsign) + 1)
Command (4 Byte)
CMD_ABORT_ROUTING
Callsign ((strlen(callsign) + 1) Byte)
char callsign[]
1.15 Start Store and Forward
(PR->DPBox)
A Connect command for Store and Forward sent by DPBox (CMD_BOXPBOXSF) was
successful and S&F can begin.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE + (strlen(callsign) + 1)
Command (4 Byte)
CMD_START_SF
Callsign ((strlen(callsign) + 1) Byte)
char callsign[]
1.16 Finish Program
(PR->Program)
The Program connected to the socket shall terminate the execution.
This is used to kill daemon-processes.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_FINISH_PRG
1.17 Activation Response
(Program->PR)
If a program was activated via CMD_ACTIVATE or CMD_START_SF, the resulting
usernr will be returned in this message. If the usernumber is equal 0,
then the activation was not successful.
In the response string additional information about the activation can
be transferred.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(response) + 1)
Command (4 Byte)
CMD_FINISH_PRG
Response ((strlen(response) + 1) Byte)
char response[]
1.18 AutoBIN-File to Box
(PR->Program)
On the current channel a file was received with AutoBIN-protocol.
Erase defines if the file shall be deleted afterwards, error indicates
a wrong CRC-checksum and buffer contains the filename of the file.
No more supported by DPBOX, DPBOX handles AutoBIN itself.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_ABINFILETOBOX + (strlen(buffer) + 1)
Command (4 Byte)
CMD_ABINFILETOBOX
Erase (4 Byte)
int erase
Error (4 Byte)
int error
Buffer ((strlen(buffer) + 1) Byte)
char buffer[]
1.19 Huffman Status
(PR->Program) (Program->PR)
If huffman coding is enabled or disabled this message will inform the other
side about the new status. 1 means huffman coding is active, 0 means
inactive. Huffman encoding/decoding has to be done by PR.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_HUFFSTAT
Command (4 Byte)
CMD_HUFFSTAT
Huffstat (4 Byte)
int huffstat
1.20 Frequency Information
(PR->Program)
With this message all frequencies handled by the PR-program are sent to
the program. This information is used to find the right interface for
S&F by DPBox.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_QRGINFO
Command (4 Byte)
CMD_QRGINFO
Frequency (220 Byte)
char qrg[MAXQRGS+1][20] (MAXQRGS = 10)
1.21 Bulletin-ID query and answer
(PR->DPBox)(DPBox->PR)
With this message the program can query if a mail is already available
in the DPBox by checking the bulletin ID. DPBox will answer in 'Found'
(0: not found, 1: found) and will return the bullid, too. Not used for
S&F connects, only for monitoring features and similar.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_BULLID
Command (4 Byte)
CMD_BULLID
Found (4 Byte)
int found
Bullid (13 Byte)
char bullid[BULLIDLEN+1] (BULLIDLEN = 12)
1.22 Start AutoBIN-receive
(DPBox->PR)
This message instructs TNT to prepare AutoBIN reception on the current
channel. The filename of the file to open will be given as parameter
(null-terminated string in buffer).
No more supported by DPBOX, DPBOX handles AutoBIN itself.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(buffer) + 1)
Command (4 Byte)
CMD_STARTABIN
Buffer ((strlen(buffer) + 1) Byte)
char buffer[]
1.23 Update Box-timeout
(PR->DPBox)
During AutoBIN-receive TNT informs DPBox by this message that the user is
still active.
No more supported by DPBOX.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_BOXTOUCH
1.24 Set Read/write Mode
(DPBox->PR)
This message informs TNT if during a boxconnect the AutoBIN-header shall be
analysed (rwmode = 0) or not (rwmode = 1).
No more supported by DPBOX, DPBOX handles AutoBIN itself.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SETRWMODE
Command (4 Byte)
CMD_SETRWMODE
Rwmode (4 Byte)
int rwmode
1.25 Box Is Busy
(DPBox->PR)
This message informs TNT if DPBox is busy and connects shall be rejected.
(boxisbusy = 0, connects allowed; boxisbusy = 1, no connects allowed)
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_BOXISBUSY
Command (4 Byte)
CMD_BOXISBUSY
Boxisbusy (4 Byte)
int boxisbusy
1.26 Start Box Broadcast
(DPBox->PR)
This message instructs TNT to start a broadcast transmission of a file.
The broadcast-header is contained in a file, the filename of this file is
stored in buffer.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SIMPLE + (strlen(buffer) + 1)
Command (4 Byte)
CMD_STARTBOXBC
Buffer ((strlen(buffer) + 1) Byte)
char buffer[]
1.27 Broadcast Callback
(PR->DPBox)
If the broadcast transmission of a file is finished, DPBox will be informed
by this message. The file is identified by the file_id contained in the
message.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_BCCALLBACK
Command (4 Byte)
CMD_BCCALLBACK
File_id (4 Byte)
long file_id
1.28 Set Unproto Destination
(DPBox->PR)
This message sets the unproto destination for the following unproto data.
The destination is stored independently for every interface.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
LEN_SETUNPROTO + (strlen(buffer) + 1)
Command (4 Byte)
CMD_SETUNPROTO
Qrg (20 Byte)
char qrg[20]
Address ((strlen(address) + 1) Byte)
char address[]
1.29 Connect Not Successful
(PR->Program)
A connect, initiated by user 'usernr' was not successful.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_NOSUCCESSCON
1.30 Connect Successful
(PR->Program)
A connect, initiated by user 'usernr' was successful and the link between
the two connects shall be established. The channel of the new connection is
contained in channel.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(callsign) + 1)
Command (4 Byte)
CMD_SUCCESSCON
Callsign ((strlen(callsign) + 1) Byte)
char callsign[]
1.31 TNT-Command
(Program->PR)
This command contains a command string, which shall be parsed and executed
by the TNT command processor. 'channel' is used as channel used for the
command. 'usernr' is the user, which must be informed about the result.
Only used in DPBOX for the TNTCOMM command.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(buffer) + 1)
Command (4 Byte)
CMD_TNTCOMMAND
Buffer ((strlen(buffer) + 1) Byte)
char buffer[]
1.32 TNT-Response
(PR->Program)
This message contains the response to the command given by CMD_TNTCOMMAND
(1.31 TNT-Command). 'follows' indicates, if other responses to the command
will follow, 'follows' == 0 indicates the last response.
'channel' is the given channel for the command and 'usernr' is the user,
who requested the command.
Only used in DPBOX for the TNTCOMM command.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE + (strlen(buffer) + 1)
Command (4 Byte)
CMD_TNTRESPONSE
Follows (4 Byte)
follows
Buffer ((strlen(buffer) + 1) Byte)
char buffer[]
1.33 Abort Connect
(Program->PR)
A connect request started by 'usernr' shall be aborted.
Indicator (1 Byte)
IF_COMMAND
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
usernr
Length (2 Byte)
LEN_SIMPLE
Command (4 Byte)
CMD_ABORTCON
2. Data
Indicator (1 Byte)
IF_DATA
Channel (2 Byte)
channel
Usernr (2 Byte)
usernr
Length (2 Byte)
1 - 256
Data (Length Bytes)
char data[]
3. Unproto
The data will be sent to the destination last defined by CMD_SETUNPROTO.
Indicator (1 Byte)
IF_UNPROTO
Channel (2 Byte)
NO_CHANNEL
Usernr (2 Byte)
NO_USERNR
Length (2 Byte)
1 - 256
Data (Length Bytes)
char data[]
Following are the const definitions for the interface:
#define MAXQRGS 10
#define BULLIDLEN 12
#define LEN_SIMPLE sizeof(int)
#define LEN_CSTATUS (LEN_SIMPLE + sizeof(int))
#define LEN_BOXPBOXSF (LEN_SIMPLE + sizeof(int))
#define LEN_BOXPABORTSF (LEN_SIMPLE + sizeof(int))
#define LEN_HUFFSTAT (LEN_SIMPLE + sizeof(int))
#define LEN_ABINFILETOBOX (LEN_SIMPLE + sizeof(int) + sizeof(int))
#define DAT_QRGINFO (20 * (MAXQRGS + 1))
#define LEN_QRGINFO (LEN_SIMPLE + DAT_QRGINFO)
#define LEN_BULLID (LEN_SIMPLE + sizeof(int) + BULLIDLEN + 1)
#define LEN_SETRWMODE (LEN_SIMPLE + sizeof(int))
#define LEN_BOXISBUSY (LEN_SIMPLE + sizeof(int))
#define LEN_BCCALLBACK (LEN_SIMPLE + sizeof(long))
#define LEN_SETUNPROTO (LEN_SIMPLE + 20)
#define LEN_CONNECT (LEN_SIMPLE + sizeof(int) + 20)
#define LEN_TNTRESPONSE (LEN_SIMPLE + sizeof(int))
/* special definitions */
#define NO_CHANNEL -1
#define NO_USERNR -1
/* states for iface_list.active (0 = inactive) */
#define IF_NOTACTIVE 0
#define IF_ACTIVE 1
#define IF_TRYING 2
/* states of iface_list.indicator and first byte of iface-packet */
#define IF_COMMAND 1
#define IF_DATA 2
#define IF_UNPROTO 3
/* commands if IF_COMMAND */
#define CMD_ACTIVATE 1
#define CMD_DEACTIVATE 2
#define CMD_CONNECT 3
#define CMD_DISCONNECT 4
#define CMD_FINISH 5
#define CMD_CSTATUS 6
#define CMD_BLOCK 7
#define CMD_UNBLOCK 8
#define CMD_SORT_NEW_MAIL 9
#define CMD_SF_RX_EMT 10
#define CMD_BOXPBOXSF 11
#define CMD_BOXPRDISC 12
#define CMD_BOXPABORTSF 13
#define CMD_ABORT_ROUTING 14
#define CMD_START_SF 15
#define CMD_FINISH_PRG 16
#define CMD_ACT_RESP 17
#define CMD_ABINFILETOBOX 18
#define CMD_HUFFSTAT 19
#define CMD_QRGINFO 20
#define CMD_BULLID 21
#define CMD_STARTABIN 22
#define CMD_BOXTOUCH 23
#define CMD_SETRWMODE 24
#define CMD_BOXISBUSY 25
#define CMD_STARTBOXBC 26
#define CMD_BCCALLBACK 27
#define CMD_SETUNPROTO 28
#define CMD_NOSUCCESSCON 29
#define CMD_SUCCESSCON 30
#define CMD_TNTCOMMAND 31
#define CMD_TNTRESPONSE 32
#define CMD_ABORTCON 33
back to content page
K. The AutoBIN Protocol
DPBOX uses a binary mode for receiving and transmitting binary messages called the "AutoBIN protocol". It first was defined in the mid-80s by DL1BHO and is broadly used in german packet programs.
The below text is a packet message of DK4NB explaining the implementation of the protocol. Please note that I disagree in some minor points with the author, so for the importance of the YAPP protocol.
### Start of copied text ###
From: DK4NB @ DB0AAB.#BAY.DEU.EU
To : SOFTWARE @ WW
This is the documentation for the so-called #BIN# protocol, a procedure
for transferring binary and other data files without undue overhead.
0) REVISION LOG
31 May 94 First published.
1) HISTORY
The original #BIN# protocol was probably devised by DL1BHO for use with his TurboPacket program. The protocol underwent a number of changes and improvements at the hands of ex-DL1MEN who is now DK4NB. The #BIN# protocol is implemented in most packet terminal programs utilizing the WA8DED host mode, such as TurboPacket, TOP, GP, SP and others, as well as the F6FBB and TheBox BBS software.
As of today (June 1994), the most recent version of the #BIN# protocol is only available in SP version 9. It is hoped that this version is adopted by other packet terminal programs. Due to its very low overhead, it is a natural for replacing the obsolete YAPP protocol.
2) PROTOCOL DESCRIPTION
2.1) BASIC
The basic #BIN# protocol consists of three elements:
The station transmitting the file (from now on called STATION A) transmits
#BIN#nnnnn\r
and the station receiving the file (from now on called STATION B) transmits
#OK#\r
in positive response, or
#NO#...\r
in negative response.
"nnnnn" = the length of the file in decimal bytes
"\r" = a RETURN character
"..." = any explanatory text as to why the file transfer is rejected.
STATION B is to ignore any data not beginning with #OK# or #NO#.
All Elements are to start at the beginning of a frame and be contained entirely within one frame. The frame immediately preceding an element is to end with a return ("\r").
A transfer is aborted in midstream by one of the stations transmitting
\r#ABORT#\r
2.2) EXTENDED
The extended #BIN# protocol has last been changed in January 1994 and is described as follows:
STATION A transmits:
#BIN#nnnnn#|ccccc#$dddddddd?#ssss\r
----- ----- -------- ----
! ! ! file name without path
! ! file date and time in 'struct ftime' format (BCC 3.x)
! ! in hexadecimal notation (32 bits)
! The CRC of the whole file in decimal. Standard CCITT
! polynomial.
file length in decimal bytes.
The negative response by STATION B is defined as above. The positive response may be
#OK#\r (1)
or
#OK#ssss\r (2)
or
#OK#ssss#$nnnnn#ccccc\r (3)
---- ----- -----
! ! CRC of received file fragment
! number of bytes in received fragment
file name without path
Case (1) and case (2) are treated identically. Currently, the #OK# file name is transmitted for information to the operator only, since the receiving side is free to choose any file name.
Case (3) is the response used if it had previously been attempted to transfer the file, and the transfer has failed due to a manual abort or a broken link, or a disconnect. Note that when aborting, it is the responsibility of the receiving station not to allow any extraneous information, such as digipeater status messages or the #ABORT# command or TNC status messages or any other data not belonging to the received file to be stored. If the receiving station cannot guarantee this, it should delete the file fragment.
When STATION A re-transmits the same file, STATION B should check for existence of a previously stored file fragment. If there is a fragment, then the data according to (3) should be determined and the appropriate #OK# message should be transmitted.
The method of identifying a file fragment is up to the protocol implementation. In the case of SP, the file extension contains a "$" in place of the first character, e.g. "TEST.LZH" generates a fragment called "TEST.$ZH". Better operating systems than MS-DOS allow long file names which could be used to better denote a fragment.
STATION A, upon receiving the #OK# according to (1) or (2), should commence transmission of the file. The logical conclusion of the file transfer is achieved with the transmission of the last byte of the file. Upon receiving #OK# according to (3), STATION A should determine the CRC of the fragment and compare it with the CRC reported. Appropriate measures must be taken if the CRCs do not match.
2.3) OPERATOR CHAT
While STATION A is in binary transfer mode (i.e. not all bytes of the file have been committed to the TNC yet), the user is allowed to transmit textual data not related to the binary transfer. All frames of such data must be preceded by the string
SP\- and STATION B must not regard frames starting with this string as parts of the binary file transfer. This allows the operators to chat while transferring the file. STATION B, when transmitting data, need not take any precautions. STATION A must not cause an abort when receiving any data from STATION B that does not consist of the special abort element described above.
2.4) INABILITY TO RESUME
If STATION A is unable to resume an aborted binary transfer, it should signal this to STATION B at the start of the transfer by not transmitting the question mark ("?") shown in the #BIN# element above. If this question mark is missing, STATION B is to take whatever measures required to either reject the transfer or to quietly overwrite the fragment.
If STATION B is unable to resume an aborted binary transfer, it should delete aborted file fragments or take whatever steps necessary to not cause an error message should STATION A repeat the transfer attempt.
2.5) CRC ERRORS
If, at the end of a transfer, STATION B detects a CRC error, it should report this to STATION A and take whatever steps required (e.g. delete the damaged file). The format of this report may be of any kind, since it is not used by the protocol.
2.6) SUCCESS
STATION B should, at the end of a successful transfer, transmit a success message to STATION A. It is recommended that STATION A send one to STATION B as well. Neither message will be part of the protocol specification. Provisions should be made to transmit success messages on a per CALL SIGN basis, so as to not send such messages to BBS systems, which might be confused and report invalid commands. Success messages only make sense when transmitted to a human operator.
3) AUTOMATIC #BIN#
ld react to the #BIN# element even if it has not been placed in binary mode. An example would be the reception of a binary file from a TheBox BBS, which simply sends the #BIN# element immediately followed by data. Normal procedure, however, calls for some other means of initiation.
A second use for automatic #BIN# would be consecutive transmission of multiple files. The list of files is to be controlled by STATION A, and STATION B must be in a mode which allows automatic responses to #BIN#. The protocol does not allow auto resume with automatic #BIN#.
4) INITIATION OF A BINARY TRANSFER
A binary transfer may be initiated at the programmer's discretion. Usually, this will be a command issued by one of the two stations involved.
A typical constellation is a packet user controlling an unattended station. That unattended station should place the appropriate commands at the remote user's disposal. Implementation of such remote commands depends on factors such as the programmer's fancy or the general purpose of the station to be controlled and their description is beyond the scope of this document.
5) FURTHER INFORMATION, CHANGE PROPOSALS
All communication regarding the Extended #BIN# Protocol is to be directed to the author, DK4NB @ DB0AAB.DEU.EU or Compuserve 100346,2236 (Internet 100346.2236@composerve.com).
This specification is subject to change without prior notice. Any changes will be published. Anyone making changes to this protocol specification does so at their own risk.
6) CRC ROUTINE
The following C code consists of the standard CRC table and a macro used to access the table.
/*
* crctab calculated by Mark G. Mendel, Network Systems Corporation
*/
unsigned short crctab[256] = {
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
};
/*
* updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
* NOTE: First argument must be in range 0 to 255.
* Second argument is referenced twice.
*
* Programmers may incorporate any or all code into their programs,
* giving proper credit within the source. Publication of the
* source routines is permitted so long as proper credit is given
* to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
* Omen Technology.
*/
#define updcrc(cp,crc) (crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
### End of copied text ###
back to content page
L. Calculating CRCs
This is no theoretic explication on how CRCs are computed. I just give you the CRC calculation routines as used by DPBOX. Credits belong to DG0FT for spending two days (and a night hi) hunting for the CRCing of FBB in compressed forward.
### File crc.h ###
/* four different methods of CRCing:
crc_16 is the CRC16 as used for SMACK KISS (init crc with 0),
crcfcs is the FCS of AX.25 (init crc with 0xFFFF),
crcthp is the AutoBIN-CRC (init crc with 0),
(thp represents TurboHostPacket, the forefather of all german hostmode
programs, written by DL1BHO in mid-80s)
crcfbb is the f6fbb-forward-CRC (init crc with 0).
*/
extern void crc_16(uchar Data, unsigned short *crc);
extern void crcfcs(uchar Data, unsigned short *crc);
extern void crcthp(uchar Data, unsigned short *crc);
extern void crcfbb(uchar Data, unsigned short *crc);
### End of file crc.h ###
### File crc.c ###
#include "crc.h"
typedef unsigned short crctabtype[256];
Static crctabtype crc16_table = {
0, 0xc0c1, 0xc181, 0x140, 0xc301, 0x3c0, 0x280, 0xc241, 0xc601, 0x6c0,
0x780, 0xc741, 0x500, 0xc5c1, 0xc481, 0x440, 0xcc01, 0xcc0, 0xd80,
0xcd41, 0xf00, 0xcfc1, 0xce81, 0xe40, 0xa00, 0xcac1, 0xcb81, 0xb40,
0xc901, 0x9c0, 0x880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00,
0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0,
0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680,
0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600,
0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1,
0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80,
0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 0x2940,
0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00,
0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1,
0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080,
0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00,
0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0,
0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981,
0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41,
0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700,
0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0,
0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280,
0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00,
0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0,
0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81,
0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540,
0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100,
0x81c1, 0x8081, 0x4040
};
Static crctabtype ccitt_table = {
0, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129,
0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x210, 0x3273,
0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a,
0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x420, 0x1401, 0x64e6,
0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee,
0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x630, 0x76d7, 0x66f6,
0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe,
0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x840, 0x1861, 0x2802,
0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a,
0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0xa50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0xc60, 0x1c41, 0xedae,
0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97,
0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0xe70, 0xff9f, 0xefbe,
0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9,
0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0xa1, 0x30c2,
0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da,
0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x2b1, 0x1290, 0x22f3, 0x32d2, 0x4235,
0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e,
0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x481, 0x7466, 0x6447,
0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e,
0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x691, 0x16b0, 0x6657, 0x7676, 0x4615,
0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a,
0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x8e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0xaf1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e,
0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26,
0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0xcc1, 0xef1f, 0xff3e,
0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36,
0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0xed1, 0x1ef0
};
void crc_16(uchar Data, unsigned short *crc)
{
*crc = ((*crc) >> 8) ^ crc16_table[((*crc) ^ Data) & 0xff];
}
void crcfcs(uchar Data, unsigned short *crc)
{
*crc = ((*crc) >> 8) ^ ccitt_table[((*crc) ^ Data) & 0xff];
}
void crcthp(uchar Data, unsigned short *crc)
{
*crc = ((*crc) << 8) ^ Data ^ ccitt_table[(*crc) >> 8];
}
void crcfbb(uchar Data, unsigned short *crc)
{
*crc = ((*crc) << 8) ^ ccitt_table[((*crc) >> 8) ^ Data];
}
### End of file crc.c ###
back to content page
M. LZHuf Compression
This is the LZHuf compression algorithm as used in DPBOX and F6FBB.
/**************************************************************
lzhuf.c
written by Haruyasu Yoshizaki 11/20/1988
some minor changes 4/6/1989
comments translated by Haruhiko Okumura 4/7/1989
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
FILE *infile, *outfile;
unsigned long int textsize = 0, codesize = 0, printcount = 0;
char wterr[] = "Can't write.";
void Error(char *message)
{
printf("\n%s\n", message);
exit(EXIT_FAILURE);
}
/********** LZSS compression **********/
#define N 4096 /* buffer size */
/* Attention: When using this file for f6fbb-type compressed data exchange,
set N to 2048 ! (DL8HBS) */
#define F 60 /* lookahead buffer size */
#define THRESHOLD 2
#define NIL N /* leaf of tree */
unsigned char
text_buf[N + F - 1];
int match_position, match_length,
lson[N + 1], rson[N + 257], dad[N + 1];
void InitTree(void) /* initialize trees */
{
int i;
for (i = N + 1; i <= N + 256; i++)
rson[i] = NIL; /* root */
for (i = 0; i < N; i++)
dad[i] = NIL; /* node */
}
void InsertNode(int r) /* insert to tree */
{
int i, p, cmp;
unsigned char *key;
unsigned c;
cmp = 1;
key = &text_buf[r];
p = N + 1 + key[0];
rson[r] = lson[r] = NIL;
match_length = 0;
for ( ; ; ) {
if (cmp >= 0) {
if (rson[p] != NIL)
p = rson[p];
else {
rson[p] = r;
dad[r] = p;
return;
}
} else {
if (lson[p] != NIL)
p = lson[p];
else {
lson[p] = r;
dad[r] = p;
return;
}
}
for (i = 1; i < F; i++)
if ((cmp = key[i] - text_buf[p + i]) != 0)
break;
if (i > THRESHOLD) {
if (i > match_length) {
match_position = ((r - p) & (N - 1)) - 1;
if ((match_length = i) >= F)
break;
}
if (i == match_length) {
if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
match_position = c;
}
}
}
}
dad[r] = dad[p];
lson[r] = lson[p];
rson[r] = rson[p];
dad[lson[p]] = r;
dad[rson[p]] = r;
if (rson[dad[p]] == p)
rson[dad[p]] = r;
else
lson[dad[p]] = r;
dad[p] = NIL; /* remove p */
}
void DeleteNode(int p) /* remove from tree */
{
int q;
if (dad[p] == NIL)
return; /* not registered */
if (rson[p] == NIL)
q = lson[p];
else
if (lson[p] == NIL)
q = rson[p];
else {
q = lson[p];
if (rson[q] != NIL) {
do {
q = rson[q];
} while (rson[q] != NIL);
rson[dad[q]] = lson[q];
dad[lson[q]] = dad[q];
lson[q] = lson[p];
dad[lson[p]] = q;
}
rson[q] = rson[p];
dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p)
rson[dad[p]] = q;
else
lson[dad[p]] = q;
dad[p] = NIL;
}
/* Huffman coding */
#define N_CHAR (256 - THRESHOLD + F)
/* kinds of characters (character code = 0..N_CHAR-1) */
#define T (N_CHAR * 2 - 1) /* size of table */
#define R (T - 1) /* position of root */
#define MAX_FREQ 0x8000 /* updates tree when the */
/* root frequency comes to this value. */
typedef unsigned char uchar;
/* table for encoding and decoding the upper 6 bits of position */
/* for encoding */
uchar p_len[64] = {
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
uchar p_code[64] = {
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
/* for decoding */
uchar d_code[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};
uchar d_len[256] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};
unsigned freq[T + 1]; /* frequency table */
int prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
/* elements [T..T + N_CHAR - 1] which are used to get */
/* the positions of leaves corresponding to the codes. */
int son[T]; /* pointers to child nodes (son[], son[] + 1) */
unsigned getbuf = 0;
uchar getlen = 0;
int GetBit(void) /* get one bit */
{
int i;
while (getlen <= 8) {
if ((i = getc(infile)) < 0) i = 0;
getbuf |= i << (8 - getlen);
getlen += 8;
}
i = getbuf;
getbuf <<= 1;
getlen--;
return (i < 0);
}
int GetByte(void) /* get one byte */
{
unsigned i;
while (getlen <= 8) {
if ((i = getc(infile)) < 0) i = 0;
getbuf |= i << (8 - getlen);
getlen += 8;
}
i = getbuf;
getbuf <<= 8;
getlen -= 8;
return i >> 8;
}
unsigned putbuf = 0;
uchar putlen = 0;
void Putcode(int l, unsigned c) /* output c bits of code */
{
putbuf |= c >> putlen;
if ((putlen += l) >= 8) {
if (putc(putbuf >> 8, outfile) == EOF) {
Error(wterr);
}
if ((putlen -= 8) >= 8) {
if (putc(putbuf, outfile) == EOF) {
Error(wterr);
}
codesize += 2;
putlen -= 8;
putbuf = c << (l - putlen);
} else {
putbuf <<= 8;
codesize++;
}
}
}
/* initialization of tree */
void StartHuff(void)
{
int i, j;
for (i = 0; i < N_CHAR; i++) {
freq[i] = 1;
son[i] = i + T;
prnt[i + T] = i;
}
i = 0; j = N_CHAR;
while (j <= R) {
freq[j] = freq[i] + freq[i + 1];
son[j] = i;
prnt[i] = prnt[i + 1] = j;
i += 2; j++;
}
freq[T] = 0xffff;
prnt[R] = 0;
}
/* reconstruction of tree */
void reconst(void)
{
int i, j, k;
unsigned f, l;
/* collect leaf nodes in the first half of the table */
/* and replace the freq by (freq + 1) / 2. */
j = 0;
for (i = 0; i < T; i++) {
if (son[i] >= T) {
freq[j] = (freq[i] + 1) / 2;
son[j] = son[i];
j++;
}
}
/* begin constructing tree by connecting sons */
for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
k = i + 1;
f = freq[j] = freq[i] + freq[k];
for (k = j - 1; f < freq[k]; k--);
k++;
l = (j - k) * 2;
memmove(&freq[k + 1], &freq[k], l);
freq[k] = f;
memmove(&son[k + 1], &son[k], l);
son[k] = i;
}
/* connect prnt */
for (i = 0; i < T; i++) {
if ((k = son[i]) >= T) {
prnt[k] = i;
} else {
prnt[k] = prnt[k + 1] = i;
}
}
}
/* increment frequency of given code by one, and update tree */
void update(int c)
{
int i, j, k, l;
if (freq[R] == MAX_FREQ) {
reconst();
}
c = prnt[c + T];
do {
k = ++freq[c];
/* if the order is disturbed, exchange nodes */
if (k > freq[l = c + 1]) {
while (k > freq[++l]);
l--;
freq[c] = freq[l];
freq[l] = k;
i = son[c];
prnt[i] = l;
if (i < T) prnt[i + 1] = l;
j = son[l];
son[l] = i;
prnt[j] = c;
if (j < T) prnt[j + 1] = c;
son[c] = j;
c = l;
}
} while ((c = prnt[c]) != 0); /* repeat up to root */
}
unsigned code, len;
void EncodeChar(unsigned c)
{
unsigned i;
int j, k;
i = 0;
j = 0;
k = prnt[c + T];
/* travel from leaf to root */
do {
i >>= 1;
/* if node's address is odd-numbered, choose bigger brother node */
if (k & 1) i += 0x8000;
j++;
} while ((k = prnt[k]) != R);
Putcode(j, i);
code = i;
len = j;
update(c);
}
void EncodePosition(unsigned c)
{
unsigned i;
/* output upper 6 bits by table lookup */
i = c >> 6;
Putcode(p_len[i], (unsigned)p_code[i] << 8);
/* output lower 6 bits verbatim */
Putcode(6, (c & 0x3f) << 10);
}
void EncodeEnd(void)
{
if (putlen) {
if (putc(putbuf >> 8, outfile) == EOF) {
Error(wterr);
}
codesize++;
}
}
int DecodeChar(void)
{
unsigned c;
c = son[R];
/* travel from root to leaf, */
/* choosing the smaller child node (son[]) if the read bit is 0, */
/* the bigger (son[]+1} if 1 */
while (c < T) {
c += GetBit();
c = son[c];
}
c -= T;
update(c);
return c;
}
int DecodePosition(void)
{
unsigned i, j, c;
/* recover upper 6 bits from table */
i = GetByte();
c = (unsigned)d_code[i] << 6;
j = d_len[i];
/* read lower 6 bits verbatim */
j -= 2;
while (j--) {
i = (i << 1) + GetBit();
}
return c | (i & 0x3f);
}
/* compression */
void Encode(void) /* compression */
{
int i, c, len, r, s, last_match_length;
fseek(infile, 0L, 2);
textsize = ftell(infile);
if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1)
Error(wterr); /* output size of text */
if (textsize == 0)
return;
rewind(infile);
textsize = 0; /* rewind and re-read */
StartHuff();
InitTree();
s = 0;
r = N - F;
for (i = s; i < r; i++)
text_buf[i] = ' ';
for (len = 0; len < F && (c = getc(infile)) != EOF; len++)
text_buf[r + len] = c;
textsize = len;
for (i = 1; i <= F; i++)
InsertNode(r - i);
InsertNode(r);
do {
if (match_length > len)
match_length = len;
if (match_length <= THRESHOLD) {
match_length = 1;
EncodeChar(text_buf[r]);
} else {
EncodeChar(255 - THRESHOLD + match_length);
EncodePosition(match_position);
}
last_match_length = match_length;
for (i = 0; i < last_match_length &&
(c = getc(infile)) != EOF; i++) {
DeleteNode(s);
text_buf[s] = c;
if (s < F - 1)
text_buf[s + N] = c;
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode(r);
}
if ((textsize += i) > printcount) {
printf("%12ld\r", textsize);
printcount += 1024;
}
while (i++ < last_match_length) {
DeleteNode(s);
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
if (--len) InsertNode(r);
}
} while (len > 0);
EncodeEnd();
printf("In : %ld bytes\n", textsize);
printf("Out: %ld bytes\n", codesize);
printf("Out/In: %.3f\n", (double)codesize / textsize);
}
void Decode(void) /* recover */
{
int i, j, k, r, c;
unsigned long int count;
if (fread(&textsize, sizeof textsize, 1, infile) < 1)
Error("Can't read"); /* read size of text */
if (textsize == 0)
return;
StartHuff();
for (i = 0; i < N - F; i++)
text_buf[i] = ' ';
r = N - F;
for (count = 0; count < textsize; ) {
c = DecodeChar();
if (c < 256) {
if (putc(c, outfile) == EOF) {
Error(wterr);
}
text_buf[r++] = c;
r &= (N - 1);
count++;
} else {
i = (r - DecodePosition() - 1) & (N - 1);
j = c - 255 + THRESHOLD;
for (k = 0; k < j; k++) {
c = text_buf[(i + k) & (N - 1)];
if (putc(c, outfile) == EOF) {
Error(wterr);
}
text_buf[r++] = c;
r &= (N - 1);
count++;
}
}
if (count > printcount) {
printf("%12ld\r", count);
printcount += 1024;
}
}
printf("%12ld\n", count);
}
int main(int argc, char *argv[])
{
char *s;
if (argc != 4) {
printf("'lzhuf e file1 file2' encodes file1 into file2.\n"
"'lzhuf d file2 file1' decodes file2 into file1.\n");
return EXIT_FAILURE;
}
if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
|| (s = argv[2], (infile = fopen(s, "rb")) == NULL)
|| (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
printf("??? %s\n", s);
return EXIT_FAILURE;
}
if (toupper(*argv[1]) == 'E')
Encode();
else
Decode();
fclose(infile);
fclose(outfile);
return EXIT_SUCCESS;
}
back to content page
N. RSA Data Security, Inc. MD2 Message Digest Algorithm
This is the RSA Data Security, Inc. MD2 Message Digest Algorithm
/* ------- start of RSA copyrighted code --------- */
/* some changes were made by Joachim Schurig 28/04/96 to encapsulate
the code in PASCAL */
/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
License to copy and use this software is granted for
non-commercial Internet Privacy-Enhanced Mail provided that it is
identified as the "RSA Data Security, Inc. MD2 Message Digest
Algorithm" in all material mentioning or referencing this software
or this function.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
typedef uchar MD2barr16[16];
typedef struct MD2_CTX {
MD2barr16 state, checksum;
long count;
MD2barr16 buffer;
} MD2_CTX;
/*
* Permutation of 0..255 constructed from the digits of pi. It gives a
* "random" nonlinear byte substitution operation.
*/
typedef uchar PI_SUBSTTYPE[256];
typedef MD2barr16 PADDINGTYPE[17];
Static PI_SUBSTTYPE PI_SUBST = {
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98,
167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30,
155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78,
196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169,
104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127,
93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48,
179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56,
210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112,
89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173,
174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221,
81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40,
132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193,
171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99,
232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88,
208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
};
Static PADDINGTYPE PADDING;
Static boolean PADDINGOK;
/* must be initialized with FALSE at program startup (Joachim Schurig) */
/*
* initializes the padding tab, cannot be assigned directly in PASCAL code
* added by Joachim Schurig
*/
Static void init_padding(void)
{
short x, y;
PADDING[0][0] = 0;
for (x = 1; x <= 16; x++) {
for (y = 0; y < x; y++)
PADDING[x][y] = x;
}
PADDINGOK = true;
}
/* MD2 initialization. Begins an MD2 operation, writing a new context. */
Static void MD2Init(MD2_CTX *context)
{
if (!PADDINGOK) /* added for PASCAL */
init_padding();
context->count = 0;
memset(context->state, 0, sizeof(MD2barr16));
memset(context->checksum, 0, sizeof(MD2barr16));
}
/* MD2 basic transformation. Transforms state and updates checksum based on block. */
Static void MD2Transform(uchar *state, uchar *checksum, uchar *block)
{
long i, j, t;
uchar x[48];
/* Form encryption block from state, block, state ^ block. */
memcpy(x, state, 16);
memcpy(&x[16], block, 16);
for (i = 0; i <= 15; i++)
x[i + 32] = state[i] ^ block[i];
/* Encrypt block (18 rounds). */
t = 0;
for (i = 0; i <= 17; i++) {
for (j = 0; j <= 47; j++) {
t = x[j] ^ PI_SUBST[t];
x[j] = t;
}
t = (t + i) & 0xff;
}
/* Save new state */
memcpy(state, x, 16);
/* Update checksum. */
t = checksum[15];
for (i = 0; i <= 15; i++) {
t = checksum[i] ^ PI_SUBST[block[i] ^ t];
checksum[i] = t;
}
/* Zeroize sensitive information. */
memset(x, 0, sizeof(uchar) * 48);
}
/*
* MD2 block update operation. Continues an MD2 message-digest
* operation, processing another message block, and updating the
* context.
*/
Static void MD2Update(MD2_CTX *context, uchar *input, long inputLen)
{
long i, index, partLen;
/* Update number of bytes mod 16 */
index = context->count;
context->count = (index + inputLen) & 0xf;
partLen = 16 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
memcpy(&context->buffer[index], input, partLen);
MD2Transform(context->state, context->checksum, context->buffer);
i = partLen;
while (i + 15 < inputLen) {
MD2Transform(context->state, context->checksum, (uchar *)(&input[i]));
i += 16;
}
index = 0;
} else
i = 0;
/* Buffer remaining input */
memcpy(&context->buffer[index], (uchar *)(&input[i]), inputLen - i);
}
/*
* MD2 finalization. Ends an MD2 message-digest operation, writing the
* message digest and zeroizing the context.
*/
Static void MD2Final(uchar *digest, MD2_CTX *context)
{
long index, padLen;
/* Pad out to multiple of 16 */
index = context->count;
padLen = 16 - index;
MD2Update(context, PADDING[padLen], padLen);
/* Extend with checksum */
MD2Update(context, context->checksum, 16);
/* Store state in digest */
memcpy(digest, context->state, 16);
/* Zeroize sensitive information */
memset((uchar *)context, 0, sizeof(MD2_CTX));
}
/* ------- end of RSA copyrighted code ------- */
void calc_MD2_pw(Char *MD2prompt, Char *MD2pw, Char *MD2result)
{
MD2_CTX context;
MD2barr16 digest;
short i, n, len;
long bc;
Char c1, c2;
uchar *buffp;
Char buff[256];
short FORLIM;
buffp = buff;
bc = 0;
FORLIM = strlen(MD2prompt);
for (i = 0; i < FORLIM; i++) {
buffp[bc] = MD2prompt[i];
bc++;
}
FORLIM = strlen(MD2pw);
for (i = 0; i < FORLIM; i++) {
buffp[bc] = MD2pw[i];
bc++;
}
buffp[bc] = 0;
MD2Init(&context);
len = bc;
i = 0;
while (i < len) {
if (len - i > 16)
n = 16;
else
n = len - i;
MD2Update(&context, (uchar *)(&buffp[i]), n);
i += 16;
}
MD2Final(digest, &context);
MD2result[0] = '\0';
for (i = 0; i <= 15; i++) {
int2hchar(digest[i], &c1, &c2);
sprintf(MD2result + strlen(MD2result), "%c%c", c1, c2);
}
lower(MD2result);
}
void calc_MD2_prompt(Char *MD2prompt)
{
short x;
Char c;
MD2prompt[0] = '\0';
for (x = 1; x <= 10; x++) {
do {
c = dp_randomize(48, 122);
} while (!isalnum(c));
sprintf(MD2prompt + strlen(MD2prompt), "%c", c);
}
}