/*
 * $Id: ipxripd.c,v 1.1 1995/01/05 09:25:54 root Exp $
 *
 * Main program
 */
#include "sap.h"

IPXRouteEnt *net_table;
SAPInfo *sap_table;

int sapsock,ripsock;
/*
 * Read IPX network file
 */
IPXRouteEnt *read_ipxnet_file(char *cmd) {
  FILE *fp = fopen(IPXNET_FILE,"r");
  char *args[LSTRLEN],lbuf[LSTRLEN];
  IPXRouteEnt *p=NULL;

  if (fp == NULL) sysMsg(MSG_FATAL,ERR_ERRNO,"%s-%s",cmd,IPXNET_FILE);
  /*
   * Read net lines one at a time
   */
  while (getline(lbuf,LSTRLEN,fp)) {
    int argc=parse(lbuf,args,lbuf);
    if (argc) {
      if (argc >= 3)
	p = add_local_route(args[0],asc2frame(args[1]),gethex(args[2]),p);
    }
  }
  fclose(fp);
  dump_ipxtab(NULL);
  return p;
}

IPXRouteEnt *rtes=NULL;

void main_loop() {
  int maxfd, i, sendrip=FALSE;
  fd_set readfds;
  struct timeval tmo = { 30, 0} ;

  ripsock = opensock(IPXS_RIP,IPXT_RIP);
  sapsock = opensock(IPXS_SAP,IPXT_SAP);

  maxfd = (ripsock > sapsock ? ripsock : sapsock)+1;
  for (;;) {
    FD_ZERO(&readfds);
    FD_SET(ripsock,&readfds);
    FD_SET(sapsock,&readfds);
    
    do {
      i = select(maxfd,&readfds,NULL,NULL,&tmo);
    } while (i == -1 && errno == EINTR);
    
    if (i < 0) sysMsg(MSG_FATAL,ERR_ERRNO,"select");
    if (i) {
      if (FD_ISSET(ripsock,&readfds)) {
	rtes = read_rip(ripsock,rtes);
      }
      if (FD_ISSET(sapsock,&readfds)) {
	read_sap(sapsock,rtes);
      }
    }
    if (!tmo.tv_sec) {
      rtes = age_rip(rtes);
      age_sap();
      sendrip = !sendrip;
      if (sendrip) {
	/* Broadcast my RIP table */
	broadcast_rip(net_table);
	broadcast_rip(rtes);
      }
      else {
	broadcast_sap(sap_table);
      }
      tmo.tv_sec = 30;
      tmo.tv_usec = 0;
    }
  }
}

/*
 * Main program
 */
int verbose;

void main(int argc,char **argv) {
  verbose = argc > 1;

#ifndef DEBUG
  if (!fork()) {
    int i;
    for (i=0;i<32;close(i++));
  }
  else exit(0);
#endif

  net_table = read_ipxnet_file(argv[0]);	/* Read local routes */
  sap_table = NULL;	/* No services by default */

  sleep(1);	/* ? */
  broadcast_rip(net_table);
  sleep(1);	/* ? */

  /* Fork off now! */

  /* Ok.  We begin listening here */
  alarm(2);
  signal(SIGALRM,general_request);
  main_loop();
}

void general_request(int sig) {
  unsigned char pkt[IPX_MTU];
  IPXRipEnt *p = (IPXRipEnt *) (&pkt[2]);
  IPXRouteEnt *nets = net_table;
  struct sockaddr_ipx sk;

  pkt[0] = 0;
  pkt[1] = IPX_REQ;
  p->network = IPX_GEN_REQ;
  p->hops = p->ticks = 0;

  sk.sipx_family = AF_IPX;	/* Set IPX dest socket */
  memset(sk.sipx_node,0xff,sizeof sk.sipx_node);

  sk.sipx_port = htons(IPXS_RIP);
  sk.sipx_type = IPXT_RIP;

  while (nets) {
    sk.sipx_network = htonl(nets->network);
    if (sendto(ripsock,pkt,sizeof *p+2,0,(struct sockaddr *)&sk,sizeof sk) < 0)
      sysMsg(MSG_FATAL,ERR_ERRNO,"send-ipx-req");
    nets = nets->next;
  }
  pkt[1] = SAP_REQ;
  pkt[2] = SAP_ANY >> 8;
  pkt[3] = SAP_ANY & 0xff;

  sk.sipx_port = htons(IPXS_SAP);
  sk.sipx_type = IPXT_SAP;

  for (nets = net_table ; nets ; nets = nets->next) {
    sk.sipx_network = htonl(nets->network);
    if (sendto(sapsock,pkt,4,0,(struct sockaddr *)&sk,sizeof sk) < 0)
      sysMsg(MSG_FATAL,ERR_ERRNO,"send-sap-req");
  }
}
