/*
 * Public Release 3
 * 
 * $Id: isis_trollutil.c,v 1.2 1997/07/17 22:42:42 chopps Exp $
 */

/*
 * ------------------------------------------------------------------------
 * 
 * Copyright (c) 1996, 1997 The Regents of the University of Michigan
 * All Rights Reserved
 *  
 * Royalty-free licenses to redistribute GateD Release
 * 3 in whole or in part may be obtained by writing to:
 * 
 * 	Merit GateDaemon Project
 * 	4251 Plymouth Road, Suite C
 * 	Ann Arbor, MI 48105
 *  
 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE
 * UNIVERSITY OF MICHIGAN AND MERIT DO NOT WARRANT THAT THE
 * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
 * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the
 * University of Michigan and Merit shall not be liable for
 * any special, indirect, incidental or consequential damages with respect
 * to any claim by Licensee or any third party arising from use of the
 * software. GateDaemon was originated and developed through release 3.0
 * by Cornell University and its collaborators.
 * 
 * Please forward bug fixes, enhancements and questions to the
 * gated mailing list: gated-people@gated.merit.edu.
 * 
 * ------------------------------------------------------------------------
 * 
 * Copyright (c) 1990,1991,1992,1993,1994,1995 by Cornell University.
 *     All rights reserved.
 * 
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * GateD is based on Kirton's EGP, UC Berkeley's routing
 * daemon	 (routed), and DCN's HELLO routing Protocol.
 * Development of GateD has been supported in part by the
 * National Science Foundation.
 * 
 * ------------------------------------------------------------------------
 * 
 * Portions of this software may fall under the following
 * copyrights:
 * 
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms are
 * permitted provided that the above copyright notice and
 * this paragraph are duplicated in all such forms and that
 * any documentation, advertising materials, and other
 * materials related to such distribution and use
 * acknowledge that the software was developed by the
 * University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote
 * products derived from this software without specific
 * prior written permission.  THIS SOFTWARE IS PROVIDED
 * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * ------------------------------------------------------------------------
 * 
 * 	Copyright 1991 D.L.S. Associates
 * 
 * 	Permission to use, copy, modify, distribute, and sell this software
 * 	and its documentation for any purpose is hereby granted without
 * 	fee, provided that the above copyright notice appear in all copies
 * 	and that both that copyright notice and this permission notice
 * 	appear in supporting documentation, and that the name of D.L.S. not
 * 	be used in advertising or publicity pertaining to distribution of
 * 	the software without specific, written prior permission.  D.L.S.
 * 	makes no representations about the suitability of this software for
 * 	any purpose.  It is provided "as is" without express or implied
 * 	warranty.
 * 
 * 	D.L.S. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * 	INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 * 	NO EVENT SHALL D.L.S.  BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * 	CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 * 	OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * 	NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * 	CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 * 
 * 	Authors:  Robert Hagens and Dan Schuh
 * 
 * 
 */


#include "include.h"
#include "isis_includes.h"

extern int isis_snpa;
extern int errno;

short	knowTroll;
struct sockaddr_in trolladdr;

/*
 *	Create a socket to be used for transmitting datagrams to the
 *	troll process. Return fd created.
 */
int
trollTransmitSock()
{
	int	s;
	struct hostent *gethostbyname();

	if (!knowTroll) {
		struct hostent *hp;
		char name[MAXHOSTNAMELEN];

		gethostname(name, MAXHOSTNAMELEN);
		if ((hp = gethostbyname(name)) == NULL) {
			fprintf(stderr, "Can't get hostname\n");
			return(-1);
		}
		trolladdr.sin_family = AF_INET;
		bcopy(hp->h_addr, (char*)&trolladdr.sin_addr, hp->h_length);
		trolladdr.sin_port = htons(TROLL);
		knowTroll++;
	}
#ifdef __GATED__
/* we are operating in gated environment, use its socket utility */
	if ((s = task_floating_socket(isis_task,
				      task_get_socket(isis_task, AF_INET, SOCK_DGRAM, 0),
				      "trollTransmit")) < 0) {
		perror("socket");
		return(-1);
	}
#else	/* __GATED__ */
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		return(-1);
	}
#endif /* __GATED */
	return(s);
}

/*
 *	Create a socket to be used for receiving datagrams from the troll
 *	process. If path is null, create a unique name in /tmp made out of
 *	the process id. Otherwise, use path as the name. Return fd created.
 */
int
trollReceiveSock()
{
	int	s;
	struct sockaddr_in	laddr;

	if (!knowTroll) {
		struct hostent *hp;
		char name[MAXHOSTNAMELEN];

		gethostname(name, MAXHOSTNAMELEN);
		if ((hp = gethostbyname(name)) == NULL) {
			fprintf(stderr, "Can't get hostname\n");
			return(-1);
		}
		trolladdr.sin_family = AF_INET;
		bcopy(hp->h_addr, (char*)&trolladdr.sin_addr, hp->h_length);
		trolladdr.sin_port = htons(TROLL);
		knowTroll++;
	}
#ifdef __GATED__
/* we are operating in gated environment, use its socket utility */
	if ((s = task_floating_socket(isis_task,
				      task_get_socket(isis_task, AF_INET, SOCK_DGRAM, 0),
				      "trollReceive")) < 0) {
		perror("socket");
		return(-1);
	}
#else	/* __GATED__ */
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		return(-1);
	}
#endif	/* __GATED__ */
	laddr.sin_family = AF_INET;
	laddr.sin_addr.s_addr = INADDR_ANY; /* let the kernel fill this in */
	laddr.sin_port = 0;					/* let the kernel choose a port */
	if (bind(s, (struct sockaddr *)&laddr, sizeof laddr) < 0) {
			perror("bind");
	}
	{
		int len = sizeof(laddr);
		if (getsockname(s, (struct sockaddr *) &laddr, &len))
			perror("getsockname FAILS:");
		else
			printf("Listen on port %d\n", ntohs(laddr.sin_port));
	}
	return(s);
}


int
trollRecvData(fd, hdr)
int	fd;
struct NetMessage *hdr;
{
	int cc;
	struct sockaddr_in from;
	int len = sizeof(struct sockaddr_in);

	cc = recvfrom(fd, (char *)hdr, sizeof(struct NetMessage), 0,
			(struct sockaddr *)&from, &len);
	if (cc < 0)
		perror("recvfrom");
	
	return(cc);
}

/*
 *	Receive a packet from fd. Place into buf, and place from address
 *	into from. Fromlen must be the size of from. Return cc.
 */
int
trollReceive(fd, buf, buflen, from, fromlen, snpa)
int	fd;
char *buf;
int	buflen;
struct sockaddr_un	*from;
int			fromlen;
int			*snpa;
{
	int cc;
	struct NetMessage hdr;

	cc = trollRecvData(fd, &hdr);
	*snpa = hdr.snpa;
	return(cc);
}


int
trollSendData(fd, hdr, size)
int			fd;
struct NetMessage	*hdr;
int 		size;			/* Size of hdr */
{
#ifdef notdef
	int cc;
	int len = sizeof(trolladdr);
	struct netdHeader nhdr;

	nhdr.snpa = hdr->snpa;
	nhdr.subnetId = hdr->subnetId;

	check_send_trace(0,&nhdr,hdr->buf,hdr->buflen);
	{
		extern int run_from_log;
		if (run_from_log) /* don't really try to send the msg */
			return (size);
	}

	cc = sendto(fd, (char *)hdr, size, 0,
		(struct sockaddr *)&trolladdr, len);
	if (cc < 0)
		perror("trollSendData: sendto");
	
	return(cc);
#else	/* notdef */
	return(0);
#endif	/* notdef */
}


int
trollTransmit(c, macAddr, buf, buflen)
CircuitEntry	*c;
MACAddress		macAddr;
char *buf;
int	buflen;
{
	struct NetMessage hdr;

	hdr.snpa = isis_snpa;
	hdr.subnetId = c->simSubnetId;
	hdr.flags = OP_SEND;
	if (buflen > MAXNETMESSAGE) {
		fprintf(stderr, "trollTransmit: buffer to large\n");
		return(-1);
	}
	hdr.buflen = buflen;
	bcopy(buf, hdr.buf, buflen);

	trollSendData(c->fd, &hdr, sizeof(hdr));

	return 0;
}


void
trollJoinGroup(fd, subnetId)
int fd;
int	subnetId;
{
	struct NetMessage hdr;

	hdr.snpa = isis_snpa;
	hdr.subnetId = subnetId;
	hdr.flags = OP_JOIN;
	hdr.buflen = 0;

	trollSendData(fd, &hdr, sizeof(hdr));
}
