/*****************************************************************************
 *
 * $Id$
 * Purpose ...............: Read fidonet .pkt header
 *
 *****************************************************************************
 * Copyright (C) 1997-2004
 *   
 * Michiel Broek		FIDO:	2:280/2802
 * Beekmansbos 10
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * MBSE BBS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with MBSE BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/


#include "../config.h"
#include "mbselib.h"


faddr	pktfrom;
char	pktpwd[9];


/*
 * Return codes:
 *  0 - All Seems Well
 *  1 - Invalid type (not 2 or 2+)
 *  2 - Read header error
 *  3 - Not for me
 *  4 - Password error
 *  5 - Unsecure session
 *
 *  If session is TRUE, the password is checked as being the session password,
 *  otherwise it is checked as the mail password.
 */
int getheader(faddr *f, faddr *t, FILE *pkt, char *pname, int session)
{
    unsigned char   buffer[0x3a];
    int		    i, capword, prodx, major, minor = 0, tome = FALSE;
    char	    *p, *prodn = NULL, *fa, *ta, buf[5];
    long	    year, month, day, hour, min, sec;

    f->domain = NULL;
    f->name   = NULL;
    t->domain = NULL;
    t->name   = NULL;

    /*
     * Read type 2+ packet header, see FSC-0039 version 4 and FTS-0001
     */
    if (fread(buffer, 1, 0x3a, pkt) != 0x3a) {
	WriteError("$Could not read header (%s)", pname);
	return 2;
    }
    if ((buffer[0x12] + (buffer[0x13] << 8)) != 2) {
	WriteError("Not a type 2 packet (%s)", pname);
	return 1;
    }

    f->node = (buffer[0x01] << 8) + buffer[0x00];
    t->node = (buffer[0x03] << 8) + buffer[0x02];
    f->net  = (buffer[0x15] << 8) + buffer[0x14];
    t->net  = (buffer[0x17] << 8) + buffer[0x16];
    f->zone = (buffer[0x23] << 8) + buffer[0x22];
    t->zone = (buffer[0x25] << 8) + buffer[0x24];

    year    = (buffer[0x05] << 8) + buffer[0x04];
    /*
     * Check for Y2K bugs, if there are any this is not important,
     * it is just for logging!
     */
    if (year < 50)
	year = year + 2000;
    else if (year < 1900)
	year = year + 1900;
    month   = (buffer[0x07] << 8) + buffer[0x06] + 1;
    day     = (buffer[0x09] << 8) + buffer[0x08];
    hour    = (buffer[0x0b] << 8) + buffer[0x0a];
    min     = (buffer[0x0d] << 8) + buffer[0x0c];
    sec     = (buffer[0x0f] << 8) + buffer[0x0e];
    prodx   =  buffer[0x18];
    major   =  buffer[0x19];

    capword = (buffer[0x2d] << 8) + buffer[0x2c];
    if (capword != ((buffer[0x28] << 8) + buffer[0x29]))
	capword = 0;

    if (capword & 0x0001) {
	/*
	 * FSC-0039 packet type 2+
	 */
	prodx     = prodx + (buffer[0x2a] << 8);
	minor     = buffer[0x2b];
	f->zone   = buffer[0x2e] + (buffer[0x2f] << 8);
	t->zone   = buffer[0x30] + (buffer[0x31] << 8);
	f->point  = buffer[0x32] + (buffer[0x33] << 8);
	t->point  = buffer[0x34] + (buffer[0x35] << 8);
    } else {
	/*
	 * Stone age @%#$@
	 */
	f->zone   = buffer[0x22] + (buffer[0x23] << 8);
	t->zone   = buffer[0x24] + (buffer[0x25] << 8);
	if ((f->zone == 0) && (t->zone == 0)) {
	    /*
	     * No zone info, since the packet should be for us, guess the zone
	     * against our aka's from the setup using a 2d test.
	     */
	    for (i = 0; i < 40; i++) {
		if ((CFG.akavalid[i]) && (t->net  == CFG.aka[i].net) && (t->node == CFG.aka[i].node)) {
		    t->zone = CFG.aka[i].zone;
		    f->zone = CFG.aka[i].zone;
		    Syslog('!', "Warning, zone %d assumed", CFG.aka[i].zone);
		    break;
		}
	    }
	}
    }
    
    for (i = 0; i < 8; i++) 
	pktpwd[i] = buffer[0x1a + i];
    pktpwd[8]='\0';
    for (p = pktpwd + 7; (p >= pktpwd) && (*p == ' '); p--) *p='\0';
    if (pktpwd[0]) 
	f->name = pktpwd;

    /*
     * Fill in a default product code in case it doesn't exist
     */
    sprintf(buf, "%04x", prodx);
    prodn = xstrcpy((char *)"Unknown 0x");
    prodn = xstrcat(prodn, buf);
    for (i = 0; ftscprod[i].name; i++)
	if (ftscprod[i].code == prodx) {
	    free(prodn);
	    prodn = xstrcpy(ftscprod[i].name);
	    break;
	}

    pktfrom.name   = NULL;
    pktfrom.domain = NULL;
    pktfrom.zone   = f->zone;
    pktfrom.net    = f->net;
    pktfrom.node   = f->node;
    if (capword & 0x0001) 
	pktfrom.point = f->point;
    else 
	pktfrom.point = 0;

    for (i = 0; i < 40; i++) {
	if ((CFG.akavalid[i]) && ((t->zone == 0) || (t->zone == CFG.aka[i].zone)) &&
	    (t->net  == CFG.aka[i].net) && (t->node == CFG.aka[i].node) &&
	    ((!(capword & 0x0001)) || (t->point == CFG.aka[i].point)))
	    tome = TRUE;
    }

    fa = xstrcpy(ascfnode(f, 0x1f));
    ta = xstrcpy(ascfnode(t, 0x1f));
    Syslog('+', "Packet   : %s type %s", pname, (capword & 0x0001) ? "2+":"stone-age");
    Syslog('+', "From     : %s to %s", fa, ta);
    Syslog('+', "Dated    : %02u-%02u-%u %02u:%02u:%02u", day, month, year, hour, min, sec);
    Syslog('+', "Program  : %s %d.%d", prodn, major, minor);
    free(ta);
    free(fa);

    if (capword & 0x0001) {
	buf[0] = buffer[0x36];
	buf[1] = buffer[0x37];
	buf[2] = buffer[0x38];
	buf[3] = buffer[0x39];
	buf[4] = '\0';
    }

    if (prodn)
	free(prodn);

    if (!tome)
	return 3;

    if (session) {
	/*
	 * FTS-0001 session setup mode.
	 */
	if (noderecord(f) && strlen(nodes.Spasswd)) {
	    if (strcasecmp(nodes.Spasswd, pktpwd) == 0) {
		return 0; /* Secure session */
	    } else {
		Syslog('!', "Password : got \"%s\", expected \"%s\"", pktpwd, nodes.Spasswd);
		return 4; /* Bad password */
	    }
	} else {
	    Syslog('+', "Node not in setup or no password set");
	    return 5; /* Unsecure session */
	}
    } else {
	/*
	 * Mail password check
	 */
	if (noderecord(f) && nodes.MailPwdCheck && strlen(nodes.Epasswd)) {
	    if (strcasecmp(nodes.Epasswd, pktpwd) == 0) {   
		return 0; /* Password Ok */
	    } else {
		Syslog('!', "Password : got \"%s\", expected \"%s\"", pktpwd, nodes.Epasswd);
		return 4; /* Bad password */
	    }
	} else {
	    return 0; /* Not checked, still Ok */
	}
    }

    return 0;
}