/*
 * proto.cpp - protocols selection
 * $Id: proto.cpp,v 1.10 2004/06/05 15:15:18 rdenisc Exp $
 */

/***********************************************************************
 *  Copyright (C) 2002-2004 Remi Denis-Courmont.                       *
 *  This program is free software; you can redistribute and/or modify  *
 *  it under the terms of the GNU General Public License as published  *
 *  by the Free Software Foundation; version 2 of the license.         *
 *                                                                     *
 *  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, you can get it from:              *
 *  http://www.gnu.org/copyleft/gpl.html                               *
 ***********************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <string.h> /* strchr(), memcpy(), memset(), strcmp() */

#include "proto.h"
#include <sys/types.h>
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#include "gettext.h"

static struct protocol_info
{
	const char *p_name;
	int p_af;
} proto_list[] =
{
#ifdef AF_LOCAL
	{ "local",	AF_LOCAL },
#endif
#ifdef AF_UNIX
	{ "unix",	AF_UNIX },
#endif
#ifdef AF_FILE
	{ "file",	AF_FILE },
#endif
#ifdef AF_INET
	{ "tcp",	AF_INET },
	{ "tcpip",	AF_INET },
	{ "tcp4",	AF_INET },
	{ "tcpip4",	AF_INET },
#endif
#ifdef AF_INET6
	{ "tcp6",	AF_INET6 },
	{ "tcpip6",	AF_INET6 },
#endif
	{ NULL,		AF_UNSPEC }
};
#define MAX_PROTONAME 8 /* bytes */

static int
findprotobyname (const char *name, int *af)
{
	struct protocol_info *info;

	for (info = proto_list; info->p_name != NULL; info++)
		if (!strcmp (info->p_name, name))
		{
			*af = info->p_af;
			return 0;
		}

	return -1;
}


int
parse_proto (const char *parm, int *serveraf, int *bridgeaf)
{
	const char *ptr;

	ptr = strchr (parm, '/');
	if (ptr == NULL)
	{
		/* use same protocol twice */
		if (!findprotobyname (parm, serveraf))
		{
			*bridgeaf = *serveraf;
			return 0;
		}
	}
	else
	{
		size_t len;

		len = ptr - parm;
		if (len <= MAX_PROTONAME)
		{
			/* use two different protocols */
			char name[MAX_PROTONAME];

			memcpy (name, parm, len);
			name[len] = 0;

			if (!findprotobyname (name, serveraf)
			 && !findprotobyname (++ptr, bridgeaf))
				return 0;
		}
	}
	return -1;
}


void fprint_proto_list (FILE *stream)
{
	struct protocol_info *info = proto_list;
	int previous = AF_UNSPEC, current;
	const char *name;

	fputs (_("List of available protocols:"), stream);
	while ((name = info->p_name) != NULL)
	{
		current = info->p_af;

		if (current != previous)
		{
			fputc (' ', stream);
			fputs (name, stream);
			previous = current;
		}
		info++;
	}
	fputc ('\n', stream);
}


syntax highlighted by Code2HTML, v. 0.9.1