/*
    Manipulate the IPX routing table.

    Copyright (C) 1994, 1995  Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>

    This program 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 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <linux/ipx.h>
#include "ipxutil.h"

void rt_print_hdr()
{
  printf("network   type    router                 frame  device\n");
}

void rt_print(struct ipx_route_def* idef)
{
  char dname[17];
  
  ipx_print_network(idef->ipx_network);
  printf("  ");
  if (idef->ipx_router_network!=0)
  {
    printf("remote  ");
    ipx_print_network(idef->ipx_router_network);
    printf(":");
    ipx_print_node(idef->ipx_router_node);
  }
  else
  {
    printf("direct  ********:");
    ipx_print_node(idef->ipx_router_node);
  }
  printf("  ");
  if (idef->ipx_flags&IPX_RT_BLUEBOOK) printf("dix  ");
  else
  {
  if (idef->ipx_flags&IPX_RT_8022) printf("802.2");
  else
  {
  if (idef->ipx_flags&IPX_RT_SNAP) printf("snap ");
  else
  printf("802.3");
  }
  }
  memcpy(dname,idef->ipx_device,16);
  dname[16]=0;
  printf("  %s\n",dname);
}

#define MAX_ROUTE 1024

void rt_dump()
{
	int sock;
	struct ipx_route_def rt_table[MAX_ROUTE];
	struct ipx_route_info rt_info={MAX_ROUTE,rt_table};
	struct ipx_route_def* rt_def;
	
	rt_print_hdr();
	
	sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
	if(sock==-1)
	{
		perror("socket");
		exit(1);
	}
	
	if(ioctl(sock,SIOCGIFCONF,(void *)&rt_info)==-1)
	{
		perror("IFCONF");
		close(sock);
		exit(1);
	}
	
	for(rt_def=rt_info.ipx_rt_list;rt_def<rt_info.ipx_rt_list+rt_info.ipx_rt_len;rt_def++)
	{
  	  rt_print(rt_def);
  	}
	close(sock); 
}

int main(int argc,char *argv[])
{
	struct ipx_route_def rt;
	int sock;
	int node[6];
	int ct;
	int verbose=0;
	
	if (argc==1)
	{
	  rt_dump();
	  exit(1);
	}
	
	if (argc>=2 && strcmp(argv[1],"-v")==0)
	{
		argc--;
		argv++;
		verbose=1;
	}
	
	if (argc!=3)
	{
		fprintf(stderr,	"IPX routing utility v0.9, (c) Ales Dryak, 1995\n"
				"Usage: ipxroute [ [-v] <network> <router>]\n");
		exit(1);
	}
	
	if(sscanf(argv[1],"%lX",&rt.ipx_network)==0)
	{
		fprintf(stderr,"Unable to parse network number '%s'.\n",argv[2]);
		exit(1);
	}
	
	rt.ipx_network=htonl(rt.ipx_network);
	
	/* Parse a router */
	
	if(sscanf(argv[2],"%lX:%x:%x:%x:%x:%x:%x",
		&rt.ipx_router_network,
			&node[0],
			&node[1],
			&node[2],
			&node[3],
			&node[4],
			&node[5])!=7)
				
	{
		fprintf(stderr,"router formatted wrong (expect net:no:de:_a:dd:re:ss).\n");
		exit(1);
	}

	rt.ipx_router_network=htonl(rt.ipx_router_network);		
	rt.ipx_flags=0;
	for(ct=0;ct<6;ct++)
		rt.ipx_router_node[ct]=node[ct];
		
	sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
	if(sock==-1)
	{
		perror("socket");
		exit(1);
	}
	
	if(ioctl(sock,SIOCADDRT,(void *)&rt)==-1)
	{
		perror("add route");
		exit(1);
	}
	if (verbose)
	{
		printf("Adding route to network ");
		ipx_print_network(rt.ipx_network);
	        printf(" via router ");
		ipx_print_network(rt.ipx_router_network);
		printf(":");
		ipx_print_node(rt.ipx_router_node);
		printf("\n");
	}
	close(sock);
	return 0;
}
