/*******************************************************************************/
/*                                                                             */
/*  Copyright 2004 Pascal Gloor                                                */
/*                                                                             */
/*  Licensed under the Apache License, Version 2.0 (the "License");            */
/*  you may not use this file except in compliance with the License.           */
/*  You may obtain a copy of the License at                                    */
/*                                                                             */
/*     http://www.apache.org/licenses/LICENSE-2.0                              */
/*                                                                             */
/*  Unless required by applicable law or agreed to in writing, software        */
/*  distributed under the License is distributed on an "AS IS" BASIS,          */
/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/*  See the License for the specific language governing permissions and        */
/*  limitations under the License.                                             */
/*                                                                             */
/*******************************************************************************/


#include <inttypes.h>
#include <pwd.h>

#define P_VER_MA "1"
#define P_VER_MI "0"
#define P_VER_PL "3"

#define MAX_PEERS 1024
#define DUMPINTERVAL 10

#ifndef PATH
#define PATH "./"
#endif

#define LOGFILE    PATH "/var/piranha.log"
#define STATUSFILE PATH "/var/piranha.status"
#define PIDFILE    PATH "/var/piranha.pid"
#define DUMPDIR    PATH "/dump"

#define INPUT_BUFFER  1048576
#define OUTPUT_BUFFER 65536
#define TEMP_BUFFER   65536

#define BGP_HEADER_LEN  19
#define BGP_OPEN_LEN    10
#define BGP_ERROR_LEN   8

#define BGP_DEFAULT_HOLD 180

#define DUMP_HEADER      0
#define DUMP_OPEN        1
#define DUMP_CLOSE       2
#define DUMP_KEEPALIVE   3
#define DUMP_ANNOUNCE    4
#define DUMP_WITHDRAWN   5
#define DUMP_FOOTER    255

#define DUMP_OPT_ASPATH      1
#define DUMP_OPT_COMMUNITY   2

#ifdef SUNCC
#pragma packed()
#endif

struct bgp_header
{
	char     marker[16];
	uint16_t len;
	uint8_t  type;
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct bgp_open
{
	uint8_t  version;
	uint16_t as;
	uint16_t holdtime;
	uint32_t bgp_id;
	uint8_t  param_len;
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct bgp_param
{
	uint8_t type;
	uint8_t len;
	char    param[256];
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct bgp_error
{
	uint8_t code;
	uint8_t subcode;
	char    data[6];
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct dump_msg
{
	uint16_t type;
	uint16_t len;
	uint32_t ts;
};

struct dump_header
{
	uint32_t ip;
	uint16_t as;
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct dump_withdrawn
{
	uint8_t  mask;
	uint32_t prefix;
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct dump_announce
{
	uint8_t  mask;
	uint32_t prefix;
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct dump_announce_aspath
{
	uint8_t  code;
	uint16_t len;
	uint16_t data[256];
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct community_record
{
	uint16_t asn;
	uint16_t num;
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct dump_announce_community
{
	uint8_t  code;
	uint16_t len;
	struct community_record data[256];
#ifdef GCC
} __attribute__((packed));
#else
};
#endif

struct config_t
{
	uint32_t ip;
	uint16_t port;
	uint16_t as;
	uint32_t routerid;
	uint16_t holdtime;
	uid_t    uid;
	gid_t    gid;
	int      sock;
	char     *file;
	struct peer_t *peer;
};

struct peer_t
{
	uint8_t  allow;
	uint8_t  newallow;  /* to avoid peer drop during reconfiguration */
	uint8_t  status;    /* 0 offline, 1 connected, 2 authed */
	uint32_t ucount;    /* bgp updates count */
	uint32_t ip;
	uint16_t as;
	uint32_t rmsg;
	uint32_t smsg;
	uint32_t cts;
	uint32_t rts;
	uint32_t sts;
	uint16_t rhold;
	uint16_t shold;
	FILE     *fh;
	uint8_t  empty;
	char     filename[1024];
	uint32_t filets;
	int      ilen;
	int      olen;
	int      sock;
};