%{
extern "C" {
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <syslog.h>
}

#include "aclocal.h"
#include "caida_t.h"

#include <fstream.h>

#include "CflowdConfig.hh"
#include "CflowdRawFlow.hh"
#include "CflowdConfigLex.hh"

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif

  extern int        errno;
  
  const char          *g_configFileName = (const char *)0;
  yyFlexLexer         *lexer = (yyFlexLexer *)0;
  static long          lineNum = 1;
  int                  parenstack = 0;
  int                  i;
  
  void yyerror(const char *msg);
  
  static char rcsid[] = "@(#) $Name: cflowd-2-1-b1 $ $Id: config.lex,v 1.17 1999/05/25 10:27:08 dwm Exp $";

  void yyperror(char *msg)
  {
    fprintf(stderr,"parse error in %s line %ld: %s\n",g_configFileName,lineNum,
	    msg);
    return;
  }
%}

matched_OPTIONS ^[ \t]*OPTIONS[\t ]*[{][\t ]*
matched_LOGFACILITY ^[ \t]*LOGFACILITY[:][\t ]*
matched_TCPCOLLECTPORT ^[ \t]*TCPCOLLECTPORT[:][\t ]*
matched_PKTBUFSIZE ^[ \t]*PKTBUFSIZE[:][\t ]*
matched_RAWFLOWSOCKFILE ^[ \t]*RAWFLOWSOCKFILE[:][ \t]*
matched_TABLESOCKFILE ^[ \t]*TABLESOCKFILE[:][ \t]*
matched_MAPDIR ^[ \t]*MAPDIR[:][\t ]*
matched_FLOWDIR ^[ \t]*FLOWDIR[:][\t ]*
matched_FLOWFILELEN ^[ \t]*FLOWFILELEN[:][\t ]*
matched_NUMFLOWFILES ^[ \t]*NUMFLOWFILES[:][\t ]*
matched_MINLOGMISSED ^[ \t]*MINLOGMISSED[:][\t ]*
matched_CISCOEXPORTER ^[ \t]*CISCOEXPORTER[\t ]*[{][\t ]*
matched_HOST ^[ \t]*HOST[:][\t ]*
matched_number [0-9]+
matched_hex 0x[0-9A-Fa-f]+
matched_ip_address [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
matched_directory \/[^#\*\&\^\$ \t\n\!\~\`\'\"\;]*
matched_ADDRESSES ^[ \t]*ADDRESSES[:][\t ]*[{][\t ]*
matched_CFDATAPORT ^[ \t]*CFDATAPORT[:][\t ]*
matched_SNMPCOMM ^[ \t]*SNMPCOMM[:][\t ]*[\']
matched_LOCALAS ^[ \t]*LOCALAS[:][\t ]*
matched_COLLECT ^[ \t]*COLLECT[:][\t ]*[{][\t ]*
matched_COLLECTOR ^[ \t]*COLLECTOR[\t ]*[{][\t ]*
matched_AUTH ^[ \t]*AUTH[:][\t ]*
matched_flowword srcaddr|dstaddr|input_if|output_if|srcport|dstport|pkts|bytes|nexthop|starttime|endtime|protocol|tos|src_as|dst_as|src_mask|dst_mask|tcp_flags

%x OPTIONS
%x LOGFACILITY
%x TCPCOLLECTPORT
%x PKTBUFSIZE
%x RAWFLOWSOCKFILE
%x TABLESOCKFILE
%x MAPDIR
%x FLOWDIR
%x FLOWFILELEN
%x NUMFLOWFILES
%x MINLOGMISSED
%x CISCOEXPORTER
%x HOST
%x IPADDRESS
%x IFADDRESSES
%x CFDATAPORT
%x SNMPCOMM
%x LOCALAS
%x COLLECT
%x COLLECTOR
%x COLLECTORHOST
%x COLLECTORADDR
%x COLLECTORAUTH
%x CONFIG_LEX_ERROR

%%

<CISCOEXPORTER>[ \t,]+
<HOST>[ \t,]+
<IPADDRESS>[ \t,]+
<IFADDRESSES>[ \t,]+
<CFDATAPORT>[ \t,]+
<MAPDIR>[ \t,]+
<LOCALAS>[ \t,]+
<COLLECT>[ \t,]+
<OPTIONS>[ \t,]+
<LOGFACILITY>[ \t,]+
<TCPCOLLECTPORT>[ \t,]+
<PKTBUFSIZE>[ \t,]+
<RAWFLOWSOCKFILE>[ \t,]+
<TABLESOCKFILE>[ \t,]+
<FLOWDIR>[ \t,]+
<FLOWFILELEN>[ \t,]+
<NUMFLOWFILES>[ \t,]+
<MINLOGMISSED>[ \t,]+
<COLLECTOR>[ \t,]+
<COLLECTORHOST>[ \t,]+
<COLLECTORADDR>[ \t,]+
<COLLECTORAUTH>[ \t,]+

<CISCOEXPORTER>[\n]	{lineNum++;}
<HOST>[\n]		{lineNum++;}
<IPADDRESS>[\n]		{lineNum++;}
<IFADDRESSES>[\n]	{lineNum++;}
<CFDATAPORT>[\n]	{lineNum++;}
<MAPDIR>[\n]		{lineNum++;}
<SNMPCOMM>[\n]          {lineNum++;}
<LOCALAS>[\n]		{lineNum++;}
<COLLECT>[\n]		{lineNum++;}
<OPTIONS>[\n]		{lineNum++;}
<LOGFACILITY>[\n]	{lineNum++;}
<TCPCOLLECTPORT>[\n]	{lineNum++;}
<PKTBUFSIZE>[\n]        {lineNum++;}
<RAWFLOWSOCKFILE>[\n]   {lineNum++;}
<TABLESOCKFILE>[\n]     {lineNum++;}
<FLOWDIR>[\n]		{lineNum++;}
<FLOWFILELEN>[\n]	{lineNum++;}
<NUMFLOWFILES>[\n]	{lineNum++;}
<COLLECTOR>[\n]		{lineNum++;}
<COLLECTORHOST>[\n]	{lineNum++;}
<COLLECTORADDR>[\n]	{lineNum++;}
<COLLECTORAUTH>[\n]	{lineNum++;}

<INITIAL>#.*\n                    {lineNum++;}
<CISCOEXPORTER>#.*\n              {lineNum++;}
<HOST>#.*\n                       {lineNum++;}
<IPADDRESS>#.*\n                  {lineNum++;}
<IFADDRESSES>#.*\n                {lineNum++;}
<CFDATAPORT>#.*\n                 {lineNum++;}
<SNMPCOMM>#.*\n                   {lineNum++;}
<LOCALAS>#.*\n                    {lineNum++;}
<COLLECT>#.*\n                    {lineNum++;}
<OPTIONS>#.*\n                    {lineNum++;}
<LOGFACILITY>#.*\n                {lineNum++;}
<TCPCOLLECTPORT>#.*\n             {lineNum++;}
<PKTBUFSIZE>#.*\n                 {lineNum++;}
<RAWFLOWSOCKFILE>#.*\n            {lineNum++;}
<TABLESOCKFILE>#.*\n              {lineNum++;}
<FLOWDIR>#.*\n              	  {lineNum++;}
<FLOWFILELEN>#.*\n                {lineNum++;}
<NUMFLOWFILES>#.*\n               {lineNum++;}
<MINLOGMISSED>#.*\n               {lineNum++;}
<MAPDIR>#.*\n                     {lineNum++;}
<COLLECTOR>#.*\n		  {lineNum++;}
<COLLECTORHOST>#.*\n              {lineNum++;}
<COLLECTORADDR>#.*\n              {lineNum++;}
<COLLECTORAUTH>#.*\n              {lineNum++;}

<INITIAL>{matched_CISCOEXPORTER}    {parenstack++;BEGIN(CISCOEXPORTER);
				     return(CISCOEXPORTER);}
<INITIAL>{matched_OPTIONS}          {parenstack++;BEGIN(OPTIONS);
				     return(OPTIONS);}
<OPTIONS>{matched_LOGFACILITY}      {BEGIN(LOGFACILITY);}
<LOGFACILITY>[a-zA-Z0-9]+           {BEGIN(OPTIONS);return(LOGFACILITY);}
<OPTIONS>{matched_TCPCOLLECTPORT}   {BEGIN(TCPCOLLECTPORT);}
<TCPCOLLECTPORT>{matched_number}    {BEGIN(OPTIONS);return(TCPCOLLECTPORT);}
<OPTIONS>{matched_PKTBUFSIZE}       {BEGIN(PKTBUFSIZE);}
<PKTBUFSIZE>{matched_number}        {BEGIN(OPTIONS);return(PKTBUFSIZE);}
<OPTIONS>{matched_RAWFLOWSOCKFILE}  {BEGIN(RAWFLOWSOCKFILE);}
<RAWFLOWSOCKFILE>{matched_directory} {BEGIN(OPTIONS);return(RAWFLOWSOCKFILE);}
<OPTIONS>{matched_TABLESOCKFILE}    {BEGIN(TABLESOCKFILE);}
<TABLESOCKFILE>{matched_directory}  {BEGIN(OPTIONS);return(TABLESOCKFILE);}
<OPTIONS>{matched_MAPDIR}	    {BEGIN(MAPDIR);}
<MAPDIR>{matched_directory}         {BEGIN(OPTIONS);return(MAPDIR);}
<OPTIONS>{matched_FLOWDIR}	    {BEGIN(FLOWDIR);}
<FLOWDIR>{matched_directory}	    {BEGIN(OPTIONS);return(FLOWDIR);}
<OPTIONS>{matched_FLOWFILELEN}      {BEGIN(FLOWFILELEN);}
<FLOWFILELEN>{matched_number}       {BEGIN(OPTIONS);return(FLOWFILELEN);}
<OPTIONS>{matched_NUMFLOWFILES}     {BEGIN(NUMFLOWFILES);}
<NUMFLOWFILES>{matched_number}      {BEGIN(OPTIONS);return(NUMFLOWFILES);}
<OPTIONS>{matched_MINLOGMISSED}     {BEGIN(MINLOGMISSED);}
<MINLOGMISSED>{matched_number}      {BEGIN(OPTIONS);return(MINLOGMISSED);}
<OPTIONS>[}]			    {parenstack--;BEGIN(INITIAL);}
<INITIAL>{matched_COLLECTOR}        {parenstack++;BEGIN(COLLECTOR);}
<COLLECTOR>{matched_HOST}           {BEGIN(COLLECTORHOST);}
<COLLECTORHOST>{matched_ip_address} {BEGIN(COLLECTOR);return(COLLECTORHOST);}
<COLLECTOR>{matched_ADDRESSES}      {parenstack++;BEGIN(COLLECTORADDR);}
<COLLECTORADDR>{matched_ip_address} {return(COLLECTORADDR);}
<COLLECTORADDR>[}]		    {parenstack--;BEGIN(COLLECTOR);}
<COLLECTOR>{matched_AUTH}           {BEGIN(COLLECTORAUTH);}
<COLLECTORAUTH>[a-zA-Z]+            {BEGIN(COLLECTOR);return(COLLECTORAUTH);}
<COLLECTOR>[}]                      {parenstack--;BEGIN(INITIAL);}
<CISCOEXPORTER>{matched_HOST}       {BEGIN(IPADDRESS);}
<IPADDRESS>{matched_ip_address}     {BEGIN(CISCOEXPORTER);return(IPADDRESS);}
<CISCOEXPORTER>{matched_ADDRESSES}  {parenstack++;BEGIN(IFADDRESSES);}
<IFADDRESSES>{matched_ip_address}   {return(IFADDRESSES);}
<IFADDRESSES>[}]		    {parenstack--;BEGIN(CISCOEXPORTER);}
<CISCOEXPORTER>{matched_CFDATAPORT} {BEGIN(CFDATAPORT);}
<CFDATAPORT>{matched_number}        {BEGIN(CISCOEXPORTER);return(CFDATAPORT);}
<CISCOEXPORTER>{matched_SNMPCOMM}   {BEGIN(SNMPCOMM);}
<SNMPCOMM>[^\']+                    {return(SNMPCOMM);}
<SNMPCOMM>[\']                      {BEGIN(CISCOEXPORTER);}
<CISCOEXPORTER>{matched_LOCALAS}    {BEGIN(LOCALAS);}
<LOCALAS>{matched_number}           {BEGIN(CISCOEXPORTER);return(LOCALAS);}
<CISCOEXPORTER>{matched_COLLECT}    {parenstack++;BEGIN(COLLECT);}
<COLLECT>port			    {return(COLLECT);}
<COLLECT>portmatrix                 {return(COLLECT);}
<COLLECT>protocol		    {return(COLLECT);}
<COLLECT>netmatrix		    {return(COLLECT);}
<COLLECT>asmatrix		    {return(COLLECT);}
<COLLECT>ifmatrix                   {return(COLLECT);}
<COLLECT>nexthop                    {return(COLLECT);}
<COLLECT>tos                        {return(COLLECT);}
<COLLECT>flows                      {return(COLLECT);}
<COLLECT>[}]			    {parenstack--;BEGIN(CISCOEXPORTER);}
<CISCOEXPORTER>[}]                  {parenstack--;BEGIN(INITIAL);}
<CISCOEXPORTER>{matched_CISCOEXPORTER} {yyperror("found CISCOEXPORTER while "
						 "in CISCOEXPORTER stanza.  "
						 "Missing right paren?"); 
				        return(CONFIG_LEX_ERROR);}
<COLLECT>{matched_CISCOEXPORTER}    {yyperror("found CISCOEXPORTER keyword "
					      "in COLLECT stanza.  "
					      "missing right paren?");
				     return(CONFIG_LEX_ERROR);}
<CISCOEXPORTER>{matched_OPTIONS}    {yyperror("found OPTIONS keyword while "
				              "in CISCOEXPORTER stanza.");
				     return(CONFIG_LEX_ERROR);}
<CISCOEXPORTER>{matched_COLLECTOR}  {yyperror("found COLLECTOR while in "
					      "CISCOEXPORTER stanza.");
				     return(CONFIG_LEX_ERROR);}
<OPTIONS>{matched_CISCOEXPORTER}    {yyperror("found CISCOEXPORTER while "
					      "in OPTIONS stanza.");
                                     return(CONFIG_LEX_ERROR);}
<OPTIONS>{matched_COLLECTOR}	    {yyperror("found COLLECTOR while in "
					      "OPTIONS stanza.");
				     return(CONFIG_LEX_ERROR);}
<OPTIONS>{matched_OPTIONS}	    {yyperror("found OPTIONS keyword while "
					      "in OPTIONS stanza.");
				     return(CONFIG_LEX_ERROR);}
<COLLECTOR>{matched_CISCOEXPORTER}  {yyperror("found CISCOEXPORTER while in "
					      "COLLECTOR stanza.");
				     return(CONFIG_LEX_ERROR);}
<COLLECTOR>{matched_OPTIONS}        {yyperror("found OPTIONS keyword while "
					      "in COLLECTOR stanza.");
				     return(CONFIG_LEX_ERROR);}
<COLLECTOR>{matched_COLLECTOR}	    {yyperror("found COLLECTOR while in "
					      "COLLECTOR stanza.");
				     return(CONFIG_LEX_ERROR);}
  
[ \t,]*
[{]				    {parenstack++;}
[}]				    {parenstack--;}
[\n]                                {lineNum++;}

%%

void yyerror(const char *msg)
{
  syslog(LOG_ERR,"[E] syntax error in %s at line %d: %s %s",
         g_configFileName,lineNum,msg,lexer->YYText());
}

#ifndef HAVE_STRCASECMP
#define HAVE_STRCASECMP
static char charmap[] = {
        '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
        '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
        '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
        '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
        '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
        '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
        '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
        '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
        '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
        '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
        '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
        '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
        '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
        '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
        '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
        '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
        '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
        '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
        '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
        '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
        '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
        '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
        '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
        '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
        '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
        '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
        '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
        '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
        '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
        '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
        '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
        '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};

int strcasecmp(register char *s1, register char *s2)
{
  register char *cm = charmap;
  
  while (cm[*s1] == cm[*s2++])
    if (*s1++ == '\0')
      return(0);
  return(cm[*s1] - cm[*--s2]);
}

int strncasecmp(register char *s1, register char *s2, size_t n)
{
  register char *cm = charmap;
  
  while (--n >= 0 && cm[*s1] == cm[*s2++])
    if (*s1++ == '\0')
      return(0);
  return(n < 0 ? 0 : cm[*s1] - cm[*--s2]);
}
#endif

/*---------------------------------------------------------------------------*
 *               int SyslogFacility(const char *facilityname)		     *
 *...........................................................................*
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *---------------------------------------------------------------------------*/
int SyslogFacility(const char *facilityname)
{
  if (!strcasecmp(facilityname,"daemon"))
    return(LOG_DAEMON);
  if (!strcasecmp(facilityname,"local0"))
    return(LOG_LOCAL0);
  if (!strcasecmp(facilityname,"local1"))
    return(LOG_LOCAL1);
  if (!strcasecmp(facilityname,"local2"))
    return(LOG_LOCAL2);
  if (!strcasecmp(facilityname,"local3"))
    return(LOG_LOCAL3);
  if (!strcasecmp(facilityname,"local4"))
    return(LOG_LOCAL4);
  if (!strcasecmp(facilityname,"local5"))
    return(LOG_LOCAL5);
  if (!strcasecmp(facilityname,"local6"))
    return(LOG_LOCAL6);
  if (!strcasecmp(facilityname,"local7"))
    return(LOG_LOCAL7);
  
  return(LOG_LOCAL6);
}

/*---------------------------------------------------------------------------*
 *               uint16_t CollectionType(const char *colltype)		     *
 *...........................................................................*
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *---------------------------------------------------------------------------*/
uint16_t CollectionType(const char *colltype)
{
  if (!strcasecmp(colltype,"protocol"))
    return(CflowdCisco::k_cflowdProtocolTableMask);
  if (!strcasecmp(colltype,"port"))
    return(CflowdCisco::k_cflowdPortTableMask);
  if (!strcasecmp(colltype,"netmatrix"))
    return(CflowdCisco::k_cflowdNetMatrixMask);
  if (!strcasecmp(colltype,"asmatrix"))
    return(CflowdCisco::k_cflowdAsMatrixMask);
  if (!strncasecmp(colltype,"flows",5))
    return(CflowdCisco::k_cflowdRawFlowMask);
  if (!strcasecmp(colltype,"portmatrix"))
    return(CflowdCisco::k_cflowdPortMatrixMask);
  if (!strcasecmp(colltype,"ifmatrix"))
    return(CflowdCisco::k_cflowdInterfaceMatrixMask);
  if (!strcasecmp(colltype,"nexthop"))
    return(CflowdCisco::k_cflowdNextHopTableMask);
  if (!strcasecmp(colltype,"tos"))
    return(CflowdCisco::k_cflowdTosTableMask);
  
  return(0);
}

/*---------------------------------------------------------------------------*
 *              int CollectorAuthType(const char *authtypestr)		     *
 *...........................................................................*
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *---------------------------------------------------------------------------*/
int CollectorAuthType(const char *authtypestr)
{
  if (strcasecmp(authtypestr,"krb4") == 0)
    return(1);
  if (strcasecmp(authtypestr,"krb5") == 0)
    return(2);
  if (strcasecmp(authtypestr,"passwd") == 0)
    return(3);
  
  return(0);
}

/*-------------------------------------------------------------------------*
 *              int LoadConfigFile(const char *configFileName,             *
 *                                 CflowdConfig & cflowdConfig)            *
 *.........................................................................*
 *                                                                         *
 *-------------------------------------------------------------------------*/
int LoadConfigFile(const char *configFileName,
                   CflowdConfig & cflowdConfig)
{
  int                            rc;
  uint16_t                       indexmask = 0;
  CflowdCisco                   *newCisco = (CflowdCisco *)NULL;
  CflowdCollector               *newCollector = (CflowdCollector *)NULL;
  int                            foundport;
  uint32_t                       IPaddr;
  ifstream                      *configStream;
  CflowdFlowPortList::iterator   flowPortIter;
  CflowdFlowPort                 newFlowPort;
  
  assert(configFileName != NULL);
  
  g_configFileName = configFileName;

  configStream = new ifstream(configFileName);
  if (! configStream || ! *configStream) {
    return(-1);
  }
  
  lexer = new yyFlexLexer(configStream,0);
  assert(lexer != (yyFlexLexer *)0);

  while ((rc = lexer->yylex()) != 0)
  {
    switch (rc)
    {
      case OPTIONS:
        break;
        
      case LOGFACILITY:
        cflowdConfig.LogFacility(SyslogFacility(lexer->YYText()));
        break;
        
      case TCPCOLLECTPORT:
        cflowdConfig.TcpCollectPort(atoi(lexer->YYText()));
        break;
        
      case PKTBUFSIZE:
        cflowdConfig.PacketBufSize(atoi(lexer->YYText()));
        break;
        
      case RAWFLOWSOCKFILE:
        cflowdConfig.RawFlowSockFile(lexer->YYText());
        break;
        
      case TABLESOCKFILE:
        cflowdConfig.TableSockFile(lexer->YYText());
        break;
        
      case MAPDIR:
        cflowdConfig.MapDirectory(lexer->YYText());
        break;
        
      case FLOWDIR:
        cflowdConfig.FlowDirectory(lexer->YYText());
        break;
        
      case FLOWFILELEN:
        cflowdConfig.FlowFileLength(atol(lexer->YYText()));
        break;
        
      case NUMFLOWFILES:
        cflowdConfig.NumFlowFiles(atoi(lexer->YYText()));
        break;
        
      case MINLOGMISSED:
        cflowdConfig.MinLogMissed(atoi(lexer->YYText()));
        break;
        
      case COLLECTORHOST:
        IPaddr = inet_addr(lexer->YYText());
        if (IPaddr == 0xffffffff) {
          yyperror("bad IP address");
          exit(CONFIG_LEX_ERROR);
        }
        else {
          newCollector = new CflowdCollector();
          assert(newCollector != (CflowdCollector *)0);
          newCollector->IpAddress(IPaddr);
          cflowdConfig.CollectorMap()[IPaddr] = newCollector;
        }
        break;
        
      case COLLECTORADDR:
        IPaddr = inet_addr(lexer->YYText());
        if (IPaddr == 0xffffffff) {
          yyperror("bad IP address");
          exit(CONFIG_LEX_ERROR);
        }
        else {
          cflowdConfig.CollectorMap()[IPaddr] = newCollector;
        }
        break;
        
      case COLLECTORAUTH:
        newCollector->AuthType(CollectorAuthType(lexer->YYText()));
        break;
        
      case CISCOEXPORTER:
        newCisco = new CflowdCisco();
        assert(newCisco != (CflowdCisco *)0);
        newCisco->MissedFlowsThreshold(cflowdConfig.MinLogMissed());
        break;
        
      case IPADDRESS:
        IPaddr = inet_addr(lexer->YYText());
        if (IPaddr == 0xffffffff)
        {
          yyperror("bad IP address");
          exit(CONFIG_LEX_ERROR);
        }
        else
        {
          newCisco->IpAddress(IPaddr);
          cflowdConfig.CiscoMap()[IPaddr] = newCisco;
        }
        break;
        
      case IFADDRESSES:
        IPaddr = inet_addr(lexer->YYText());
        if (IPaddr == 0xffffffff)
        {
          yyperror("bad IP address");
          exit(CONFIG_LEX_ERROR);
        }
        else
        {
          cflowdConfig.CiscoMap()[IPaddr] = newCisco;
        }
        break;
        
      case CFDATAPORT:
        newCisco->FlowPort(atoi(lexer->YYText()));
        foundport = FALSE;
        for (flowPortIter = cflowdConfig.FlowPortList().begin();
             flowPortIter != cflowdConfig.FlowPortList().end();
             flowPortIter++) {
          if ((*flowPortIter).portnum == newCisco->FlowPort())
            foundport = TRUE;
        }
        if (!foundport)
        {
          newFlowPort.portnum = newCisco->FlowPort();
          cflowdConfig.FlowPortList().push_back(newFlowPort);
        }
        break;

      case SNMPCOMM:
        newCisco->SnmpCommunity(lexer->YYText());
        break;
        
      case LOCALAS:
        newCisco->LocalAS((uint16_t)(atoi(lexer->YYText())));
        break;
        
      case COLLECT:
        indexmask = CollectionType(lexer->YYText());
        newCisco->TableIndex(newCisco->TableIndex() | indexmask);
        break;
        
      case CONFIG_LEX_ERROR:
        exit(CONFIG_LEX_ERROR);
        break;
      default:
        break;
    }
  }

  delete(lexer);
  delete(configStream);
  
  if (parenstack != 0)
  {
    if (parenstack > 0)
      yyperror("missing right paren?");
    else
      yyperror("missing left paren?");
    fprintf(stderr,"parenstack: %d\n",parenstack);
    
  }
  
  return(0);
}

