/********************************************************
* File: pkt.c
* Created at Sun Jan 28 22:10:32 MSK 2001 by raorn // raorn@binec.ru
* pkt processing
* $Id: pkt.c,v 1.16 2002/03/03 21:05:57 raorn Exp $
*******************************************************/
#include "crashecho.h"
/*
*
* Read Pkt
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define PKT_MINREADLEN 200
bool messageend;
bool shortread, longread;
ushort getuword(uchar * buf, ulong offset)
{
return (ushort) (buf[offset] + 256 * buf[offset + 1]);
}
void putuword(uchar * buf, ulong offset, ushort num)
{
buf[offset] = num % 256;
buf[offset + 1] = num / 256;
}
ulong ReadNull(uchar * buf, ulong maxlen, FILE *fh)
{
/* Reads from fh until buffer full or NULL */
int ch, c = 0;
if (shortread)
return (0);
ch = fgetc(fh);
while (ch != EOF && ch != 0 && c != maxlen - 1) {
buf[c++] = ch;
ch = fgetc(fh);
}
buf[c] = 0;
if (ch == EOF)
shortread = TRUE;
if (ch != 0 && c == maxlen - 1)
longread = TRUE;
return (c);
}
ulong ReadCR(uchar * buf, ulong maxlen, FILE *fh)
{
/* Reads from fh until buffer full or CR */
int ch, c = 0;
ch = fgetc(fh);
while (ch != EOF && ch != 0 && ch != 13 && c != maxlen - 2) {
if(ch != 10)
buf[c++] = ch;
if (c != maxlen - 2)
ch = fgetc(fh);
}
if (ch == 13)
buf[c++] = ch;
buf[c] = 0;
if (ch == 0)
messageend = TRUE;
if (ch == EOF)
shortread = TRUE;
return (c);
}
bool ReadPkt(uchar * pkt, struct FileEntry * fe, bool(*handlefunc) (struct MemMessage * mm, bool no_echomail), bool no_security, bool no_echomail)
{
FILE *fh, *pktofsh;
struct Aka *tmpaka;
struct ConfigNode *tmpcnode;
uchar pktofs[200];
ulong rlen, msgnum, msgoffset, c;
uchar buf[200];
uchar PktHeader[SIZE_PKTHEADER];
uchar PktMsgHeader[SIZE_PKTMSGHEADER];
struct Node4D PktOrig, PktDest;
uchar *monthnames[] =
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec", "???"
};
struct MemMessage *mm;
struct TextChunk *chunk;
bool pkt_pw, pkt_4d, pkt_5d;
shortread = FALSE;
longread = FALSE;
pkt_pw = FALSE;
pkt_4d = FALSE;
pkt_5d = FALSE;
PktOrig.Zone = 0;
PktOrig.Net = 0;
PktOrig.Node = 0;
PktOrig.Point = 0;
PktDest.Zone = 0;
PktDest.Net = 0;
PktDest.Node = 0;
PktDest.Point = 0;
if (!(mm = mmAlloc()))
return (FALSE);
if (!(fh = fopen(pkt, "rb"))) {
LogWrite(1, SYSTEMERR, "Unable to open %s", pkt);
LogWrite(1, SYSTEMERR, "Error: %s", strerror(errno));
mmFree(mm);
return (TRUE);
}
if (fread(PktHeader, 1, SIZE_PKTHEADER, fh) != SIZE_PKTHEADER) {
LogWrite(1, TOSSINGERR, "Packet header in %s is too short", pkt);
fclose(fh);
mmFree(mm);
BadFile(pkt);
return (TRUE);
}
if (getuword(PktHeader, PKTHEADER_PKTTYPE) != 0x0002) {
LogWrite(1, TOSSINGERR, "%s is not a Type-2 packet", pkt);
fclose(fh);
mmFree(mm);
BadFile(pkt);
return (TRUE);
}
if (getuword(PktHeader, PKTHEADER_BAUD) == 2) {
/* PktOrig och PktDest */
PktOrig.Zone = getuword(PktHeader, PKTHEADER_ORIGZONE);
PktOrig.Net = getuword(PktHeader, PKTHEADER_ORIGNET);
PktOrig.Node = getuword(PktHeader, PKTHEADER_ORIGNODE);
PktOrig.Point = getuword(PktHeader, PKTHEADER_ORIGPOINT);
PktDest.Zone = getuword(PktHeader, PKTHEADER_DESTZONE);
PktDest.Net = getuword(PktHeader, PKTHEADER_DESTNET);
PktDest.Node = getuword(PktHeader, PKTHEADER_DESTNODE);
PktDest.Point = getuword(PktHeader, PKTHEADER_DESTPOINT);
pkt_5d = TRUE;
} else {
/* PktOrig och PktDest */
if (getuword(PktHeader, PKTHEADER_ORIGZONE)) {
PktOrig.Zone = getuword(PktHeader, PKTHEADER_ORIGZONE);
PktDest.Zone = getuword(PktHeader, PKTHEADER_DESTZONE);
} else if (getuword(PktHeader, PKTHEADER_QORIGZONE)) {
PktOrig.Zone = getuword(PktHeader, PKTHEADER_QORIGZONE);
PktDest.Zone = getuword(PktHeader, PKTHEADER_QDESTZONE);
} else {
PktOrig.Zone = 0;
PktDest.Zone = 0;
}
PktOrig.Net = getuword(PktHeader, PKTHEADER_ORIGNET);
PktOrig.Node = getuword(PktHeader, PKTHEADER_ORIGNODE);
PktDest.Net = getuword(PktHeader, PKTHEADER_DESTNET);
PktDest.Node = getuword(PktHeader, PKTHEADER_DESTNODE);
if (PktHeader[PKTHEADER_CWVALIDCOPY] == PktHeader[PKTHEADER_CAPABILWORD + 1] &&
PktHeader[PKTHEADER_CWVALIDCOPY + 1] == PktHeader[PKTHEADER_CAPABILWORD]) {
pkt_4d = TRUE;
if (getuword(PktHeader, PKTHEADER_ORIGPOINT) != 0 &&
getuword(PktHeader, PKTHEADER_ORIGNET) == 0xffff)
PktOrig.Net = getuword(PktHeader, PKTHEADER_AUXNET);
PktOrig.Point = getuword(PktHeader, PKTHEADER_ORIGPOINT);
PktDest.Point = getuword(PktHeader, PKTHEADER_DESTPOINT);
}
}
/* Check packet destination */
if ((config.cfg_Flags & CFG_CHECKPKTDEST) && !no_security) {
for (tmpaka = (struct Aka *) config.AkaList.First; tmpaka; tmpaka = tmpaka->Next)
if (Compare4D(&tmpaka->Node, &PktDest) == 0)
break;
if (!tmpaka) {
LogWrite(1, TOSSINGERR, "Addressed to %u:%u/%u.%u, not to me",
PktDest.Zone, PktDest.Net, PktDest.Node, PktDest.Point);
fclose(fh);
mmFree(mm);
BadFile(pkt);
return (TRUE);
}
}
/* Fixa zone */
/* XXX I think this code does nothing, since Compare4D will always fail... */
if (PktOrig.Zone == 0)
for (tmpcnode = (struct ConfigNode *) config.CNodeList.First; tmpcnode; tmpcnode = tmpcnode->Next) {
if (Compare4D(&PktOrig, &tmpcnode->Node) == 0) {
PktOrig.Zone = tmpcnode->Node.Zone;
break;
}
}
if (PktDest.Zone == 0)
for (tmpaka = (struct Aka *) config.AkaList.First; tmpaka; tmpaka = tmpaka->Next) {
if (Compare4D(&PktDest, &tmpaka->Node) == 0) {
PktDest.Zone = tmpaka->Node.Zone;
break;
}
}
if (PktOrig.Zone == 0)
PktOrig.Zone = config.cfg_DefaultZone;
if (PktDest.Zone == 0)
PktDest.Zone = config.cfg_DefaultZone;
for (tmpcnode = (struct ConfigNode *) config.CNodeList.First; tmpcnode; tmpcnode = tmpcnode->Next)
if (Compare4D(&PktOrig, &tmpcnode->Node) == 0)
break;
if (tmpcnode) {
if (tmpcnode->PacketPW[0] != 0 && PktHeader[PKTHEADER_PASSWORD] != 0)
pkt_pw = TRUE;
}
buf[0] = 0;
if (pkt_pw)
strcat(buf, ", pw");
if (pkt_4d)
strcat(buf, ", 4d");
if (pkt_5d)
strcat(buf, ", 5d");
if (buf[0] != 0)
buf[0] = '/';
if (pkt_5d) {
uchar domain[10];
mystrncpy(domain, &PktHeader[PKTHEADER45_ORIGDOMAIN], 9);
LogWrite(1, ACTIONINFO, "Tossing %s (%luK) from %d:%d/%d.%d@%s %s", fe->Name, (fe->Size + 512) / 1024, PktOrig.Zone, PktOrig.Net, PktOrig.Node, PktOrig.Point, domain, buf);
} else {
int month;
month = getuword(PktHeader, PKTHEADER_MONTH);
if (month > 11)
month = 12;
LogWrite(1, ACTIONINFO, "Tossing %s (%luK) from %d:%d/%d.%d (%02ld-%s-%02ld %02ld:%02ld:%02ld) %s", fe->Name, (fe->Size + 512) / 1024, PktOrig.Zone, PktOrig.Net, PktOrig.Node, PktOrig.Point, getuword(PktHeader, PKTHEADER_DAY), monthnames[month], getuword(PktHeader, PKTHEADER_YEAR) % 100, getuword(PktHeader, PKTHEADER_HOUR), getuword(PktHeader, PKTHEADER_MINUTE), getuword(PktHeader, PKTHEADER_SECOND), buf);
}
if (tmpcnode) {
strncpy(buf, &PktHeader[PKTHEADER_PASSWORD], 8);
buf[8] = 0;
if (!no_security &&
(tmpcnode->PacketPW[0] != 0 && stricmp(buf, tmpcnode->PacketPW)) &&
(buf[0] != 0 || !(config.cfg_Flags & CFG_ALLOWNULLPASSWORDS))) {
LogWrite(1, TOSSINGERR, "Wrong password");
fclose(fh);
mmFree(mm);
BadFile(pkt);
return (TRUE);
}
}
snprintf(pktofs, 200, "%s.offset", pkt);
if ((pktofsh=fopen(pktofs, "rb")) != NULL) {
fread(&msgoffset, sizeof(msgoffset), 1, pktofsh);
fread(&msgnum, sizeof(msgnum), 1, pktofsh);
fseek(fh, msgoffset, SEEK_SET);
fclose(pktofsh);
LogWrite(1, ACTIONINFO, "Old packet with %ld processed messages found, continuing from offset %ld", msgnum, msgoffset);
} else {
msgoffset = ftell(fh);
msgnum = 0;
}
while (1) {
if ((pktofsh=fopen(pktofs, "wb")) != NULL) {
fwrite(&msgoffset, sizeof(msgoffset), 1, pktofsh);
fwrite(&msgnum, sizeof(msgnum), 1, pktofsh);
fclose(pktofsh);
}
msgnum++;
msgoffset = ftell(fh);
if (fread(PktMsgHeader, 1, SIZE_PKTMSGHEADER, fh) < 2) {
LogWrite(1, TOSSINGERR, "Packet header too short for msg #%lu (offset %ld)", msgnum + 1, msgoffset);
fclose(fh);
mmFree(mm);
BadFile(pkt); /* FIXME should we delete pktofs file here? */
return (TRUE);
}
if (getuword(PktMsgHeader, PKTMSGHEADER_PKTTYPE) != 2)
break;
printf("Message %lu \015", msgnum);
fflush(stdout);
/* Init variables */
mmClear(mm);
mm->OrigNode.Net = getuword(PktMsgHeader, PKTMSGHEADER_ORIGNET);
mm->OrigNode.Node = getuword(PktMsgHeader, PKTMSGHEADER_ORIGNODE);
mm->DestNode.Net = getuword(PktMsgHeader, PKTMSGHEADER_DESTNET);
mm->DestNode.Node = getuword(PktMsgHeader, PKTMSGHEADER_DESTNODE);
mm->DestNode.Zone = PktDest.Zone;
mm->DestNode.Zone = PktOrig.Zone;
mm->Attr = getuword(PktMsgHeader, PKTMSGHEADER_ATTR);
mm->Cost = getuword(PktMsgHeader, PKTMSGHEADER_COST);
Copy4D(&mm->PktOrig, &PktOrig);
Copy4D(&mm->PktDest, &PktDest);
if (no_security)
mm->no_security = TRUE;
/* Get header strings */
ReadNull(mm->DateTime, 20, fh);
ReadNull(mm->To, 36, fh);
ReadNull(mm->From, 36, fh);
ReadNull(mm->Subject, 72, fh);
/* Corrupt packet? */
if (shortread) {
LogWrite(1, TOSSINGERR, "Message header for msg #%lu (offset %ld) is short", msgnum, msgoffset);
fclose(fh);
mmFree(mm);
BadFile(pkt);
return (TRUE);
}
if (longread) {
LogWrite(1, TOSSINGERR, "Header strings too long in msg #%lu (offset %ld)", msgnum, msgoffset);
fclose(fh);
mmFree(mm);
BadFile(pkt);
return (TRUE);
}
/* Start reading message text */
messageend = FALSE;
rlen = ReadCR(buf, 200, fh);
/* Echomail or netmail? */
if (strncmp(buf, "AREA:", 5) == 0) {
mystrncpy(mm->Area, &buf[5], 80);
/* Strip spaces from area name */
stripleadtrail(mm->Area);
/* Uppercase areatag */
for (c = 0; mm->Area[c]; c++)
if (islower(mm->Area[c]))
mm->Area[c] = toupper(mm->Area[c]);
} else {
if (!mmAddLine(mm, buf, MM_ADD)) {
fclose(fh);
mmFree(mm);
return (FALSE);
}
}
/* Get rest of text */
while (!messageend) {
rlen = ReadCR(buf, 200, fh);
if (shortread) {
fclose(fh);
mmFree(mm);
LogWrite(1, TOSSINGERR, "Got unexpected EOF when reading msg #%lu (offset %ld)", msgnum, msgoffset);
BadFile(pkt);
return (TRUE);
}
if (buf[0]) {
if (!mmAddLine(mm, buf, MM_ADD)) {
fclose(fh);
mmFree(mm);
return (FALSE);
}
}
}
/* Stats */
for (tmpcnode = (struct ConfigNode *) config.CNodeList.First; tmpcnode; tmpcnode = tmpcnode->Next)
if (Compare4D(&tmpcnode->Node, &mm->PktOrig) == 0)
break;
if (tmpcnode) {
ulong size;
size = 0;
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next)
if (chunk->Data)
size += strlen(chunk->Data);
if (mm->Area[0]) {
tmpcnode->GotEchomails++;
tmpcnode->GotEchomailBytes += size;
} else {
tmpcnode->GotNetmails++;
tmpcnode->GotNetmailBytes += size;
}
}
if (ctrlc) {
fclose(fh);
mmFree(mm);
return (FALSE);
}
if (!(*handlefunc) (mm, no_echomail)) {
fclose(fh);
mmFree(mm);
return (FALSE);
}
}
if (getuword(PktMsgHeader, PKTMSGHEADER_PKTTYPE) != 0) {
fclose(fh);
mmFree(mm);
LogWrite(1, TOSSINGERR, "Unknown message type %lu for message #%lu (offset %ld)", getuword(PktMsgHeader, PKTMSGHEADER_PKTTYPE), msgnum + 1, msgoffset);
BadFile(pkt);
return (TRUE);
}
printf(" \015");
fflush(stdout);
unlink(pktofs);
fclose(fh);
mmFree(mm);
return (TRUE);
}
/*
*
* Write Pkt
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void pktWrite(struct Pkt *pkt, uchar * buf, ulong len)
{
if (fwrite(buf, 1, len, pkt->fh) != len) {
ioerror = TRUE;
ioerrornum = errno;
}
pkt->Len += len;
}
void WriteNull(struct Pkt *pkt, uchar * str)
{
pktWrite(pkt, str, (ulong) (strlen(str) + 1));
}
struct Pkt *FindPkt(struct Node4D *node, struct Node4D *mynode, ushort type)
{
struct Pkt *pkt;
for (pkt = (struct Pkt *) PktList.First; pkt; pkt = pkt->Next)
if (Compare4D(node, &pkt->Dest) == 0 && Compare4D(mynode, &pkt->Orig) == 0
&& type == pkt->Type)
return (pkt);
return (NULL);
}
static time_t lastt = 0;
static ulong serial = 0;
struct Pkt *CreatePkt(struct Node4D *dest, struct ConfigNode *node, struct Aka *aka, ushort type)
{
uchar buf[100], buf2[100];
struct Pkt *pkt;
ulong num, c;
time_t t;
struct tm *tp;
uchar PktHeader[SIZE_PKTHEADER];
do {
t = time(NULL);
if (t == lastt)
serial++;
else
serial = 0;
if (serial == 256)
serial = 0;
lastt = t;
num = (t << 8) + serial;
snprintf(buf2, 100, "%08lx.newpkt", num);
MakeFullPath(config.cfg_PacketCreate, buf2, buf, 100);
} while (Exists(buf));
if (!(pkt = (struct Pkt *) calloc(1, sizeof(struct Pkt)))) {
nomem = TRUE;
return (NULL);
}
if (!(pkt->fh = fopen(buf, "wb"))) {
LogWrite(1, SYSTEMERR, "Unable to create packet %s", buf);
LogWrite(1, SYSTEMERR, "Error: %s", strerror(errno));
free(pkt);
return (NULL);
}
pkt->hexnum = num;
pkt->Type = type;
Copy4D(&pkt->Dest, dest);
Copy4D(&pkt->Orig, &aka->Node);
putuword(PktHeader, PKTHEADER_ORIGNODE, aka->Node.Node);
putuword(PktHeader, PKTHEADER_DESTNODE, dest->Node);
time(&t);
tp = localtime(&t);
putuword(PktHeader, PKTHEADER_DAY, tp->tm_mday);
putuword(PktHeader, PKTHEADER_MONTH, tp->tm_mon);
putuword(PktHeader, PKTHEADER_YEAR, tp->tm_year + 1900);
putuword(PktHeader, PKTHEADER_HOUR, tp->tm_hour);
putuword(PktHeader, PKTHEADER_MINUTE, tp->tm_min);
putuword(PktHeader, PKTHEADER_SECOND, tp->tm_sec);
putuword(PktHeader, PKTHEADER_BAUD, 0);
putuword(PktHeader, PKTHEADER_PKTTYPE, 2);
putuword(PktHeader, PKTHEADER_ORIGNET, aka->Node.Net);
putuword(PktHeader, PKTHEADER_DESTNET, dest->Net);
PktHeader[PKTHEADER_PRODCODELOW] = 0xfe;
PktHeader[PKTHEADER_REVMAJOR] = VERSION_MAJOR;
putuword(PktHeader, PKTHEADER_QORIGZONE, aka->Node.Zone);
putuword(PktHeader, PKTHEADER_QDESTZONE, dest->Zone);
putuword(PktHeader, PKTHEADER_AUXNET, 0);
putuword(PktHeader, PKTHEADER_CWVALIDCOPY, 0x0100);
PktHeader[PKTHEADER_PRODCODEHIGH] = 0;
PktHeader[PKTHEADER_REVMINOR] = VERSION_MINOR;
putuword(PktHeader, PKTHEADER_CAPABILWORD, 0x0001);
putuword(PktHeader, PKTHEADER_ORIGZONE, aka->Node.Zone);
putuword(PktHeader, PKTHEADER_DESTZONE, dest->Zone);
putuword(PktHeader, PKTHEADER_ORIGPOINT, aka->Node.Point);
putuword(PktHeader, PKTHEADER_DESTPOINT, dest->Point);
PktHeader[PKTHEADER_PRODDATA] = 0;
PktHeader[PKTHEADER_PRODDATA + 1] = 0;
PktHeader[PKTHEADER_PRODDATA + 2] = 0;
PktHeader[PKTHEADER_PRODDATA + 3] = 0;
for (c = 0; c < 8; c++)
PktHeader[PKTHEADER_PASSWORD + c] = 0;
if (node)
strncpy(&PktHeader[PKTHEADER_PASSWORD], node->PacketPW, 8);
pktWrite(pkt, PktHeader, SIZE_PKTHEADER);
if (ioerror) {
fclose(pkt->fh);
free(pkt);
return (NULL);
}
return (pkt);
}
void FinishPacket(struct Pkt *pkt)
{
pktWrite(pkt, "", 1);
pktWrite(pkt, "", 1);
fclose(pkt->fh);
if (pkt->hexnum) {
uchar oldname[200], newname[200], buf1[100], buf2[100];
/* Create packet name */
snprintf(buf1, 100, "%08lx.newpkt", pkt->hexnum);
/* FIXME packet name may be too long */
snprintf(buf2, 100, "%08lx_%d_%d_%d_%d_%d_%d_%d_%d.newpkt", pkt->hexnum,
pkt->Orig.Zone, pkt->Orig.Net, pkt->Orig.Node, pkt->Orig.Point,
pkt->Dest.Zone, pkt->Dest.Net, pkt->Dest.Node, pkt->Dest.Point);
MakeFullPath(config.cfg_PacketCreate, buf1, oldname, 200);
MakeFullPath(config.cfg_PacketCreate, buf2, newname, 200);
if (rename(oldname, newname)) {
LogWrite(1, SYSTEMERR, "Failed to rename %s to %s", oldname, newname);
LogWrite(1, SYSTEMERR, "Error: %s", strerror(errno));
}
}
jbFreeNode(&PktList, (struct jbNode *) pkt);
}
void ClosePackets(void)
{
struct Pkt *pkt, *pkt2;
pkt = (struct Pkt *) PktList.First;
while (pkt) {
pkt2 = pkt->Next;
FinishPacket(pkt);
pkt = pkt2;
}
}
bool WriteMsgHeader(struct Pkt *pkt, struct MemMessage *mm)
{
uchar PktMsgHeader[SIZE_PKTMSGHEADER];
putuword(PktMsgHeader, PKTMSGHEADER_PKTTYPE, 0x0002);
putuword(PktMsgHeader, PKTMSGHEADER_ORIGNODE, mm->OrigNode.Node);
putuword(PktMsgHeader, PKTMSGHEADER_DESTNODE, mm->DestNode.Node);
putuword(PktMsgHeader, PKTMSGHEADER_ORIGNET, mm->OrigNode.Net);
putuword(PktMsgHeader, PKTMSGHEADER_DESTNET, mm->DestNode.Net);
putuword(PktMsgHeader, PKTMSGHEADER_ATTR, mm->Attr);
putuword(PktMsgHeader, PKTMSGHEADER_COST, mm->Cost);
pktWrite(pkt, PktMsgHeader, SIZE_PKTMSGHEADER);
WriteNull(pkt, mm->DateTime);
WriteNull(pkt, mm->To);
WriteNull(pkt, mm->From);
WriteNull(pkt, mm->Subject);
if (ioerror)
return (FALSE);
return (TRUE);
}
bool WritePath(struct Pkt * pkt, struct jbList * list)
{
ushort c;
struct Path *path;
for (path = (struct Path *) list->First; path; path = path->Next)
for (c = 0; c < path->Paths; c++)
if (path->Path[c][0] != 0) {
pktWrite(pkt, "\001PATH: ", 7);
pktWrite(pkt, path->Path[c], (ulong) strlen(path->Path[c]));
pktWrite(pkt, "\015", 1);
}
if (ioerror)
return (FALSE);
return (TRUE);
}
bool WriteSeenBy(struct Pkt * pkt, struct jbList * list)
{
uchar *buf;
if (!(buf = mmMakeSeenByBuf(list)))
return (FALSE);
pktWrite(pkt, buf, (ulong) strlen(buf));
free(buf);
return (TRUE);
}
bool WriteEchoMail(struct MemMessage * mm, struct ConfigNode * node, struct Aka * aka)
{
uchar buf[200];
struct Pkt *pkt;
struct TextChunk *chunk;
ulong size;
toss_written++;
mm->Type = PKTS_ECHOMAIL;
size = 0;
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next)
if (chunk->Data)
size += strlen(chunk->Data);
node->SentEchomails++;
node->SentEchomailBytes += size;
pkt = FindPkt(&node->Node, &aka->Node, mm->Type);
if (!pkt || (pkt && config.cfg_MaxPktSize != 0 && pkt->Len > config.cfg_MaxPktSize)) {
if (pkt)
FinishPacket(pkt);
if (!(pkt = CreatePkt(&node->Node, node, aka, mm->Type))) {
return FALSE;
}
jbAddNode(&PktList, (struct jbNode *) pkt);
}
Copy4D(&mm->DestNode, &node->Node);
Copy4D(&mm->OrigNode, &aka->Node);
if (!WriteMsgHeader(pkt, mm))
return FALSE;
snprintf(buf, 200, "AREA:%s\015", mm->Area);
pktWrite(pkt, buf, (ulong) strlen(buf));
if (ioerror)
return (FALSE);
if (mm->Rescanned) {
snprintf(buf, 200, "\001RESCANNED %u:%u/%u.%u\015", aka->Node.Zone, aka->Node.Net, aka->Node.Node, aka->Node.Point);
pktWrite(pkt, buf, (ulong) strlen(buf));
}
if (ioerror)
return (FALSE);
for (chunk = (struct TextChunk *) mm->TextChunks.First; chunk; chunk = chunk->Next) {
if (chunk->Data)
pktWrite(pkt, chunk->Data, strlen(chunk->Data));
if (ioerror)
return (FALSE);
}
if (node->Node.Zone != aka->Node.Zone || (node->Flags & NODE_TINYSEENBY)) {
struct jbList seenbylist;
struct Nodes2D *seenby;
if (!(seenby = (struct Nodes2D *) malloc(sizeof(struct Nodes2D)))) {
nomem = TRUE;
return (FALSE);
}
seenby->Nodes = 0;
seenby->Next = NULL;
jbNewList(&seenbylist);
jbAddNode(&seenbylist, (struct jbNode *) seenby);
if (node->Node.Point == 0)
if (!mmAddNodes2DList(&seenbylist, node->Node.Net, node->Node.Node)) {
jbFreeList(&seenbylist);
return (FALSE);
}
if (aka->Node.Point == 0)
if (!mmAddNodes2DList(&seenbylist, aka->Node.Net, aka->Node.Node)) {
jbFreeList(&seenbylist);
return (FALSE);
}
if (!mmSortNodes2D(&seenbylist)) {
jbFreeList(&seenbylist);
return (FALSE);
}
if (!WriteSeenBy(pkt, &seenbylist)) {
jbFreeList(&seenbylist);
return (FALSE);
}
jbFreeList(&seenbylist);
} else if (!(node->Flags & NODE_NOSEENBY)) {
if (!mmSortNodes2D(&mm->SeenBy))
return (FALSE);
if (!WriteSeenBy(pkt, &mm->SeenBy))
return (FALSE);
}
if (!WritePath(pkt, &mm->Path))
return (FALSE);
pktWrite(pkt, "", 1);
return (TRUE);
}
syntax highlighted by Code2HTML, v. 0.9.1