dslinux/user/net-tools ABOUT-NLS COPYING INSTALLING Makefile README README.ipv6 TODO arp.c config.h config.in config.make configure.sh hostname.c ifconfig.c intl.h ipmaddr.c iptunnel.c mii-tool.c nameif.c netstat.c plipconfig.c rarp.c route.c slattach.c statistics.c

amadeus dslinux_amadeus at user.in-berlin.de
Thu Aug 31 11:32:18 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/net-tools
In directory antilope:/tmp/cvs-serv14346/user/net-tools

Added Files:
	ABOUT-NLS COPYING INSTALLING Makefile README README.ipv6 TODO 
	arp.c config.h config.in config.make configure.sh hostname.c 
	ifconfig.c intl.h ipmaddr.c iptunnel.c mii-tool.c nameif.c 
	netstat.c plipconfig.c rarp.c route.c slattach.c statistics.c 
Log Message:
Add some more applications

--- NEW FILE: ipmaddr.c ---
/*
 * ipmaddr.c		"ip maddress".
 *
 *		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.
 *
 * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
 *
 * Changes:	Arnaldo Carvalho de Melo <acme at conectiva.com.br>
 *		20010404 - use setlocale
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1))
#include <net/if.h>
#else
#include <linux/if.h>
#endif

#include "config.h"
#include "intl.h"
#include "util-ank.h"
#include "net-support.h"
#include "version.h"
#include "pathnames.h"

char filter_dev[16];
int  filter_family;

/* These have nothing to do with rtnetlink. :-) */
#define NEWADDR		1
#define DELADDR		2

char *Release = RELEASE,
     *Version = "ipmaddr 1.1",
     *Signature = "Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>";

static void version(void)
{
	printf("%s\n%s\n%s\n", Release, Version, Signature);
	exit(E_VERSION);
}

static void usage(void) __attribute__((noreturn));

static void usage(void)
{
	fprintf(stderr, _("Usage: ipmaddr [ add | del ] MULTIADDR dev STRING\n"));
	fprintf(stderr, _("       ipmaddr show [ dev STRING ] [ ipv4 | ipv6 | link | all ]\n"));
	fprintf(stderr, _("       ipmaddr -V | -version\n"));
	exit(-1);
}

static void print_lla(FILE *fp, int len, unsigned char *addr)
{
	int i;
	for (i=0; i<len; i++) {
		if (i==0)
			fprintf(fp, "%02x", addr[i]);
		else
			fprintf(fp, ":%02x", addr[i]);
	}
}

static int parse_lla(char *str, unsigned char *addr)
{
	int len=0;

	while (*str) {
		int tmp;
		if (str[0] == ':' || str[0] == '.') {
			str++;
			continue;
		}
		if (str[1] == 0)
			return -1;
		if (sscanf(str, "%02x", &tmp) != 1)
			return -1;
		addr[len] = tmp;
		len++;
		str += 2;
	}
	return len;
}

static int parse_hex(char *str, unsigned char *addr)
{
	int len=0;

	while (*str) {
		int tmp;
		if (str[1] == 0)
			return -1;
		if (sscanf(str, "%02x", &tmp) != 1)
			return -1;
		addr[len] = tmp;
		len++;
		str += 2;
	}
	return len;
}

struct ma_info
{
	struct ma_info *next;
	int		index;
	int		users;
	char		*features;
	char		name[IFNAMSIZ];
	inet_prefix	addr;
};

void maddr_ins(struct ma_info **lst, struct ma_info *m)
{
	struct ma_info *mp;

	for (; (mp=*lst) != NULL; lst = &mp->next) {
		if (mp->index > m->index)
			break;
	}
	m->next = *lst;
	*lst = m;
}

void read_dev_mcast(struct ma_info **result_p)
{
	char buf[256];
	FILE *fp = fopen(_PATH_PROCNET_DEV_MCAST, "r");

	if (!fp)
		return;

	while (fgets(buf, sizeof(buf), fp)) {
		char hexa[256];
		struct ma_info m;
		int len;
		int st;

		memset(&m, 0, sizeof(m));
		sscanf(buf, "%d%s%d%d%s", &m.index, m.name, &m.users, &st,
		       hexa);
		if (filter_dev[0] && strcmp(filter_dev, m.name))
			continue;

		m.addr.family = AF_PACKET;

		len = parse_hex(hexa, (unsigned char*)&m.addr.data);
		if (len >= 0) {
			struct ma_info *ma = malloc(sizeof(m));

			memcpy(ma, &m, sizeof(m));
			ma->addr.bytelen = len;
			ma->addr.bitlen = len<<3;
			if (st)
				ma->features = "static";
			maddr_ins(result_p, ma);
		}
	}
	fclose(fp);
}

void read_igmp(struct ma_info **result_p)
{
	struct ma_info m;
	char buf[256];
	FILE *fp = fopen(_PATH_PROCNET_IGMP, "r");

	if (!fp)
		return;
	memset(&m, 0, sizeof(m));
	fgets(buf, sizeof(buf), fp);

	m.addr.family = AF_INET;
	m.addr.bitlen = 32;
	m.addr.bytelen = 4;

	while (fgets(buf, sizeof(buf), fp)) {
		struct ma_info *ma = malloc(sizeof(m));

		if (buf[0] != '\t') {
			sscanf(buf, "%d%s", &m.index, m.name);
			continue;
		}

		if (filter_dev[0] && strcmp(filter_dev, m.name))
			continue;

		sscanf(buf, "%08x%d", (__u32*)&m.addr.data, &m.users);

		ma = malloc(sizeof(m));
		memcpy(ma, &m, sizeof(m));
		maddr_ins(result_p, ma);
	}
	fclose(fp);
}


void read_igmp6(struct ma_info **result_p)
{
	char buf[256];
	FILE *fp = fopen(_PATH_PROCNET_IGMP6, "r");

	if (!fp)
		return;

	while (fgets(buf, sizeof(buf), fp)) {
		char hexa[256];
		struct ma_info m;
		int len;

		memset(&m, 0, sizeof(m));
		sscanf(buf, "%d%s%s%d", &m.index, m.name, hexa, &m.users);

		if (filter_dev[0] && strcmp(filter_dev, m.name))
			continue;

		m.addr.family = AF_INET6;

		len = parse_hex(hexa, (unsigned char*)&m.addr.data);
		if (len >= 0) {
			struct ma_info *ma = malloc(sizeof(m));

			memcpy(ma, &m, sizeof(m));

			ma->addr.bytelen = len;
			ma->addr.bitlen = len<<3;
			maddr_ins(result_p, ma);
		}
	}
	fclose(fp);
}

static void print_maddr(FILE *fp, struct ma_info *list)
{
	fprintf(fp, "\t");

	if (list->addr.family == AF_PACKET) {
		fprintf(fp, "link  ");
		print_lla(fp, list->addr.bytelen, (unsigned char*)list->addr.data);
	} else {
		char abuf[256];
		switch(list->addr.family) {
		case AF_INET:
			fprintf(fp, "inet  ");
			break;
		case AF_INET6:
			fprintf(fp, "inet6 ");
			break;
		default:
			fprintf(fp, _("family %d "), list->addr.family);
			break;
		}
		if (format_host(list->addr.family, list->addr.data, abuf, sizeof(abuf)))
			fprintf(fp, "%s", abuf);
		else
			fprintf(fp, "?");
	}
	if (list->users != 1)
		fprintf(fp, _(" users %d"), list->users);
	if (list->features)
		fprintf(fp, " %s", list->features);
	fprintf(fp, "\n");
}

static void print_mlist(FILE *fp, struct ma_info *list)
{
	int cur_index = 0;

	for (; list; list = list->next) {
		if (cur_index != list->index) {
			cur_index = list->index;
			fprintf(fp, "%d:\t%s\n", cur_index, list->name);
		}
		print_maddr(fp, list);
	}
}

static int multiaddr_list(int argc, char **argv)
{
	struct ma_info *list = NULL;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			if (filter_dev[0])
				usage();
			strcpy(filter_dev, *argv);
		} else if (strcmp(*argv, "all") == 0) {
			filter_family = AF_UNSPEC;
		} else if (strcmp(*argv, "ipv4") == 0) {
			filter_family = AF_INET;
		} else if (strcmp(*argv, "ipv6") == 0) {
			filter_family = AF_INET6;
		} else if (strcmp(*argv, "link") == 0) {
			filter_family = AF_PACKET;
		} else {
			if (filter_dev[0])
				usage();
			strcpy(filter_dev, *argv);
		}
		argv++; argc--;
	}

	if (!filter_family || filter_family == AF_PACKET)
		read_dev_mcast(&list);
	if (!filter_family || filter_family == AF_INET)
		read_igmp(&list);
	if (!filter_family || filter_family == AF_INET6)
		read_igmp6(&list);
	print_mlist(stdout, list);
	return 0;
}

int multiaddr_modify(int cmd, int argc, char **argv)
{
	struct ifreq ifr;
	int fd;

	memset(&ifr, 0, sizeof(ifr));

	if (cmd == NEWADDR)
		cmd = SIOCADDMULTI;
	else
		cmd = SIOCDELMULTI;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			if (ifr.ifr_name[0])
				usage();
			strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
		} else {
			if (ifr.ifr_hwaddr.sa_data[0])
				usage();
			if (parse_lla(*argv, ifr.ifr_hwaddr.sa_data) < 0)
				usage();
		}
		argc--; argv++;
	}
	if (ifr.ifr_name[0] == 0)
		usage();

	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0) {
		perror(_("Cannot create socket"));
		exit(1);
	}
	if (ioctl(fd, cmd, (char*)&ifr) != 0) {
		perror("ioctl");
		exit(1);
	}
	close(fd);

	exit(0);
}


int do_multiaddr(int argc, char **argv)
{
	if (argc < 1)
		return multiaddr_list(0, NULL);
	if (matches(*argv, "add") == 0)
		return multiaddr_modify(NEWADDR, argc-1, argv+1);
	if (matches(*argv, "delete") == 0)
		return multiaddr_modify(DELADDR, argc-1, argv+1);
	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
	    || matches(*argv, "lst") == 0)
		return multiaddr_list(argc-1, argv+1);
	usage();
}

int preferred_family = AF_UNSPEC;
int show_stats = 0;
int resolve_hosts = 0;

int main(int argc, char **argv)
{
	char *basename;

#if I18N
	setlocale (LC_ALL, "");
	bindtextdomain("net-tools", "/usr/share/locale");
	textdomain("net-tools");
#endif

	basename = strrchr(argv[0], '/');
	if (basename == NULL)
		basename = argv[0];
	else
		basename++;
	
	while (argc > 1) {
		if (argv[1][0] != '-')
			break;
		if (matches(argv[1], "-family") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
			if (strcmp(argv[1], "inet") == 0)
				preferred_family = AF_INET;
			else if (strcmp(argv[1], "inet6") == 0)
				preferred_family = AF_INET6;
			else
				usage();
		} else if (matches(argv[1], "-stats") == 0 ||
			   matches(argv[1], "-statistics") == 0) {
			++show_stats;
		} else if (matches(argv[1], "-resolve") == 0) {
			++resolve_hosts;
		} else if ((matches(argv[1], "-V") == 0) || matches(argv[1], "--version") == 0) {
			version();
		} else
			usage();
		argc--;	argv++;
	}

	return do_multiaddr(argc-1, argv+1);
}

--- NEW FILE: plipconfig.c ---
/*

   plipconfig.c: plip-ifconfig program for the Linux PLIP device driver
   Copyright (c) 1994 John Paul Morrison (VE7JPM).

   version 0.2
   
   Changed by Alan Cox, to reflect the way SIOCDEVPRIVATE is meant to work
   and for the extra parameter added by Niibe.

   plipconfig is a quick hack to set PLIP parameters by using driver
   ioctls.  plipconfig will no doubt be revised many times as the Linux
   PLIP driver and Linux 1.1 mutates.

*/

/*
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2, as
   published by the Free Software Foundation.

   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 <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_plip.h>

#include "config.h"
#include "intl.h"
#include "net-support.h"
#include "version.h"

int opt_a = 0;
int opt_i = 0;
int opt_v = 0;
int skfd = -1;

struct ifreq ifr;
struct plipconf *plip;

char *Release = RELEASE,
     *Version = "plipconfig 0.2",
     *Signature = "John Paul Morrison, Alan Cox et al.";

static void version(void)
{
    printf("%s\n%s\n%s\n", Release, Version, Signature);
    exit(E_VERSION);
}

void usage(void)
{
    fprintf(stderr, _("Usage: plipconfig [-a] [-i] [-v] interface\n"));
    fprintf(stderr, _("                  [nibble NN] [trigger NN]\n"));
    fprintf(stderr, _("       plipconfig -V | --version\n"));
    exit(-1);
}

void print_plip(void)
{
    printf(_("%s\tnibble %lu  trigger %lu\n"), ifr.ifr_name, plip->nibble, plip->trigger);
}

int main(int argc, char **argv)
{
    int ret = 0;
    char **spp;

#if I18N
    setlocale (LC_ALL, "");
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket");
	exit(-1);
    }
    /* Find any options. */
    argc--;
    argv++;
    while (argv[0] && *argv[0] == '-') {
	if (!strcmp(*argv, "-a"))
	    opt_a = 1;
	if (!strcmp(*argv, "-v"))
	    opt_v = 1;
	if (!strcmp(*argv, "-V") || !strcmp(*argv, "--version"))
	    version();
	argv++;
	argc--;
    }

    if (argc == 0)
	usage();

    spp = argv;
    strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
    plip=(struct plipconf *)&ifr.ifr_data;

    plip->pcmd = PLIP_GET_TIMEOUT;	/* get current settings for device */
    if (ioctl(skfd, SIOCDEVPLIP, &ifr) < 0) {
	perror("ioctl");
	exit(-1);
    }
    if (*spp == (char *) NULL) {
	print_plip();
	(void) close(skfd);
	exit(0);
    }
    while (*spp != (char *) NULL) {
	if (!strcmp(*spp, "nibble")) {
	    if (*++spp == NULL)
		usage();
	    plip->nibble = atoi(*spp);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "trigger")) {
	    if (*++spp == NULL)
		usage();
	    plip->trigger = atoi(*spp);
	    spp++;
	    continue;
	}
	usage();
    }

    plip->pcmd = PLIP_SET_TIMEOUT;
    if (ioctl(skfd, SIOCDEVPLIP, &ifr) < 0)
	perror("ioctl");

    print_plip();

    /* Close the socket. */
    (void) close(skfd);

    return (ret);
}

--- NEW FILE: netstat.c ---
/*
 * netstat    This file contains an implementation of the command
 *              that helps in debugging the networking modules.
 *
 * NET-TOOLS    A collection of programs that form the base set of the
 *              NET-3 Networking Distribution for the LINUX operating
 *              system.
 *
 * Version:     $Id: netstat.c,v 1.2 2006-08-31 09:32:16 dslinux_amadeus Exp $
 *
 * Authors:     Fred Baumgarten, <dc6iq at insu1.etec.uni-karlsruhe.de>
 *              Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
 *              Phil Packer, <pep at wicked.demon.co.uk>
 *              Johannes Stille, <johannes at titan.os.open.de>
 *              Bernd Eckenfels, <net-tools at lina.inka.de>
 *              Phil Blundell <philb at gnu.org>
 *              Tuan Hoang <tqhoang at bigfoot.com>
 *
 * Tuned for NET3 by:
[...1815 lines suppressed...]
	}
	if (!flag_arg || flag_netrom) {
#if HAVE_AFNETROM
	    i = netrom_info();
	    if (i)
		return (i);
#else
	    if (flag_arg) {
		i = 1;
		ENOSUPP("netstat", "AF NETROM");
	    }
#endif
	}
	if (!flag_cnt || i)
	    break;
	sleep(1);
	prg_cache_clear();
    }
    return (i);
}

--- NEW FILE: Makefile ---
#
# Makefile	Main Makefile for the net-tools Package
#
# NET-TOOLS	A collection of programs that form the base set of the
#		NET-3 Networking Distribution for the LINUX operating
#		system.
#
# Version:	2001-02-13
#
# Author:	Bernd Eckenfels <net-tools at lina.inka.de>
#		Copyright 1995-1996 Bernd Eckenfels, Germany
#
# URLs:		ftp://ftp.inka.de/pub/comp/Linux/networking/NetTools/ 
#		ftp://ftp.linux.org.uk/pub/linux/Networking/PROGRAMS/NetTools/
#		http://www.inka.de/sites/lina/linux/NetTools/index_en.html
#
# Based on:	Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
#		Copyright 1988-1993 MicroWalt Corporation
#
# Modifications:
#		Extensively modified from 01/21/94 onwards by
#		Alan Cox <A.Cox at swansea.ac.uk>
#		Copyright 1993-1994 Swansea University Computer Society
#
# Be careful! 
# This Makefile doesn't describe complete dependencies for all include files.
# If you change include files you might need to do make clean. 
#
#	{1.20}	Bernd Eckenfels:	Even more modifications for the new 
#					package layout
#	{1.21}	Bernd Eckenfels:	Check if config.in is newer than 
#					config.status
#	{1.22}  Bernd Eckenfels:	Include ypdomainname and nisdomainame
#
#	1.3.50-BETA6 private Release
#				
#960125	{1.23}	Bernd Eckenfels:	Peter Tobias' rewrite for 
#					makefile-based installation
#	1.3.50-BETA6a private Release
#
#960201 {1.24}	Bernd Eckenfels:	net-features.h added
#
#960201 1.3.50-BETA6b private Release
#
#960203 1.3.50-BETA6c private Release
#
#960204 1.3.50-BETA6d private Release
#
#960204 {1.25}	Bernd Eckenfels:	DISTRIBUTION added
#
#960205 1.3.50-BETA6e private Release
#
#960206	{1.26}	Bernd Eckenfels:	afrt.o removed (cleaner solution)
#
#960215 1.3.50-BETA6f Release
#
#960216 {1.30}	Bernd Eckenfels:	net-lib support
#960322 {1.31}	Bernd Eckenfels:	moveable netlib, TOPDIR
#960424 {1.32}	Bernd Eckenfels:	included the URLs in the Comment
#
#960514 1.31-alpha release
#
#960518 {1.33}	Bernd Eckenfels:	-I/usr/src/linux/include comment added
#
#	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.
#

# set the base of the Installation 
# BASEDIR = /mnt

# path to the net-lib support library. Default: lib
NET_LIB_PATH = lib
NET_LIB_NAME = net-tools

PROGS	= ifconfig hostname arp netstat route rarp slattach plipconfig
ifdef CONFIG_USER_NET_TOOLS_NAMEIF
PROGS 	+= nameif
endif
ifdef CONFIG_USER_NET_TOOLS_IPTUNNEL
PROGS 	+= iptunnel
endif
ifdef CONFIG_USER_NET_TOOLS_IPMADDR
PROGS 	+= ipmaddr
endif
ifdef CONFIG_USER_NET_TOOLS_MII_TOOL
PROGS 	+= mii-tool
endif

BINDIR=/bin
ifeq ($(ARCH),sh)
SBINDIR=/sbin
else
ifeq ($(ARCH),i386)
SBINDIR=/sbin
else
ifeq ($(ARCH),arm)
SBINDIR=/sbin
else
SBINDIR=/bin
endif
endif
endif

-include config.make

# Compiler and Linker Options
# You may need to uncomment and edit these if you are using libc5 and IPv6.
COPTS = -D_GNU_SOURCE -D__USE_BSD
LOPTS = 
RESLIB = # -L/usr/inet6/lib -linet6

ifeq ($(HAVE_AFDECnet),1)
DNLIB = -ldnet
endif

# -------- end of user definitions --------

MAINTAINER = Philip.Blundell at pobox.com
RELEASE	   = 1.60

.EXPORT_ALL_VARIABLES:

ifeq ("$(NET_LIB_PATH)","lib2")
TOPDIR   = ..
else
TOPDIR  := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
endif

NET_LIB = $(NET_LIB_PATH)/lib$(NET_LIB_NAME).a

CFLAGS	+= $(COPTS) -I. -idirafter ./include/ -I$(NET_LIB_PATH)
LDFLAGS	+= $(LOPTS) -L$(NET_LIB_PATH)

SUBDIRS	= man/ $(NET_LIB_PATH)/

NLIB	= -l$(NET_LIB_NAME)

MDEFINES = COPTS='$(COPTS)' LOPTS='$(LOPTS)' TOPDIR='$(TOPDIR)'

%.o:		%.c config.h version.h intl.h net-features.h $<
		$(CC) $(CFLAGS) -c $<

all:		config.h version.h subdirs $(PROGS)

config: 	cleanconfig config.h

install:	all savebin installbin installdata

update: 	all installbin installdata

mostlyclean:
		rm -f *.o DEADJOE config.new *~ *.orig lib/*.o

GDBPROGS := $(PROGS:%=%.gdb)

clean: mostlyclean
		rm -f $(PROGS) $(GDBPROGS)
		@for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean) ; done
		@cd po && $(MAKE) clean

cleanconfig:
		rm -f config.h

clobber: 	clean
		rm -f $(PROGS) config.h version.h config.status config.make
		@for i in $(SUBDIRS); do (cd $$i && $(MAKE) clobber) ; done


dist: 		clobber
		@echo Creating net-tools-$(RELEASE) in ..
		@tar -cvz -f ../net-tools-$(RELEASE).tar.gz -C .. net-tools


config.h: 	config.in
		@echo "Configuring the Linux net-tools (NET-3 Base Utilities)..." ; echo
		@if [ config.status -nt config.in ]; \
			then ./configure.sh config.status; \
		   else ./configure.sh config.in; \
		 fi


version.h:	Makefile
		@echo "#define RELEASE \"net-tools $(RELEASE)\"" >version.h


$(NET_LIB):	config.h version.h intl.h libdir

i18n.h:		i18ndir

libdir:
		@$(MAKE) -C $(NET_LIB_PATH) $(MDEFINES)

i18ndir:
		@$(MAKE) -C po

subdirs:
		@for i in $(SUBDIRS); do $(MAKE) -C $$i $(MDEFINES) ; done

ifconfig:	$(NET_LIB) ifconfig.o
		$(CC) $(LDFLAGS) -o ifconfig ifconfig.o $(NLIB) $(RESLIB) $(LDLIBS)
		
nameif:	nameif.o
		$(CC) $(LDFLAGS) -o nameif nameif.o $(LDLIBS)

hostname:	hostname.o
		$(CC) $(LDFLAGS) -o hostname hostname.o $(DNLIB) $(LDLIBS)

route:		$(NET_LIB) route.o
		$(CC) $(LDFLAGS) -o route route.o $(NLIB) $(RESLIB) $(LDLIBS)

arp:		$(NET_LIB) arp.o
		$(CC) $(LDFLAGS) -o arp arp.o $(NLIB) $(RESLIB) $(LDLIBS)

rarp:		$(NET_LIB) rarp.o
		$(CC) $(LDFLAGS) -o rarp rarp.o $(NLIB) $(LDLIBS)

slattach:	$(NET_LIB) slattach.o
		$(CC) $(LDFLAGS) -o slattach slattach.o $(NLIB) $(LDLIBS)

plipconfig:	$(NET_LIB) plipconfig.o
		$(CC) $(LDFLAGS) -o plipconfig plipconfig.o $(NLIB) $(LDLIBS)

netstat:	$(NET_LIB) netstat.o statistics.o
		$(CC) $(LDFLAGS) -o netstat netstat.o statistics.o $(NLIB) $(RESLIB) $(LDLIBS)

iptunnel:	$(NET_LIB) iptunnel.o
		$(CC) $(LDFLAGS) -o iptunnel iptunnel.o $(NLIB) $(RESLIB) $(LDLIBS)

ipmaddr:	$(NET_LIB) ipmaddr.o
		$(CC) $(LDFLAGS) -o ipmaddr ipmaddr.o $(NLIB) $(RESLIB) $(LDLIBS)

mii-tool:	mii-tool.o
		$(CC) $(LDFLAGS) -o mii-tool mii-tool.o $(LDLIBS)

installbin:
	install -m 0755 -d ${BASEDIR}/sbin
	install -m 0755 -d ${BASEDIR}/bin
	install -m 0755 arp        ${BASEDIR}/sbin
	install -m 0755 hostname   ${BASEDIR}/bin
	install -m 0755 ifconfig   ${BASEDIR}/sbin
	install -m 0755 nameif     ${BASEDIR}/sbin
	install -m 0755 netstat    ${BASEDIR}/bin
	install -m 0755 plipconfig $(BASEDIR)/sbin
	install -m 0755 rarp       ${BASEDIR}/sbin
	install -m 0755 route      ${BASEDIR}/sbin
	install -m 0755 slattach   $(BASEDIR)/sbin
ifeq ($(HAVE_IP_TOOLS),1)
	install -m 0755 ipmaddr    $(BASEDIR)/sbin
	install -m 0755 iptunnel   $(BASEDIR)/sbin
endif
ifeq ($(HAVE_MII),1)
	install -m 0755 mii-tool   $(BASEDIR)/sbin
endif
	ln -fs hostname $(BASEDIR)/bin/dnsdomainname
	ln -fs hostname $(BASEDIR)/bin/ypdomainname
	ln -fs hostname $(BASEDIR)/bin/nisdomainname
	ln -fs hostname $(BASEDIR)/bin/domainname
ifeq ($(HAVE_AFDECnet),1)
	ln -fs hostname $(BASEDIR)/bin/nodename
endif

savebin:
	@for i in ${BASEDIR}/sbin/arp ${BASEDIR}/sbin/ifconfig \
                 ${BASEDIR}/bin/netstat \
		 ${BASEDIR}/sbin/rarp ${BASEDIR}/sbin/route \
		 ${BASEDIR}/bin/hostname ${BASEDIR}/bin/ypdomainname \
                 ${BASEDIR}/bin/dnsdomainname ${BASEDIR}/bin/nisdomainname \
		 ${BASEDIR}/bin/domainname ; do \
		 [ -f $$i ] && cp -f $$i $$i.old ; done ; echo Saved.

installdata:
	$(MAKE) -C man install
	$(MAKE) -C po install

romfs:
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_ARP	/$(SBINDIR)/arp
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_HOSTNAME	/$(BINDIR)/hostname
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_IFCONFIG	/$(SBINDIR)/ifconfig
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_NAMEIF	/$(SBINDIR)/nameif
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_NETSTAT	/$(BINDIR)/netstat
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_PLIPCONFIG /$(SBINDIR)/plipconfig
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_RARP	/$(SBINDIR)/rarp
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_ROUTE	/$(SBINDIR)/route
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_SLATTACH	/$(SBINDIR)/slattach
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_IPMADDR	/$(SBINDIR)/ipmaddr
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_IPTUNNEL	/$(SBINDIR)/iptunnel
	$(ROMFSINST) -e CONFIG_USER_NET_TOOLS_MII_TOOL	/$(SBINDIR)/mii-tool

# End of Makefile.

--- NEW FILE: route.c ---
/*
 * route        This file contains an implementation of the command
 *              that manages the IP routing table in the kernel.
 *
 * Version:     $Id: route.c,v 1.2 2006-08-31 09:32:16 dslinux_amadeus Exp $
 *
 * Maintainer:  Bernd 'eckes' Eckenfels, <net-tools at lina.inka.de>
 *
 * Author:      Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
 *              (derived from FvK's 'route.c     1.70    01/04/94')
 *
 * Modifications:
 *              Johannes Stille:        for Net-2Debugged by 
 *                                      <johannes at titan.os.open.de>
 *              Linus Torvalds:         Misc Changes
 *              Alan Cox:               add the new mtu/window stuff
 *              Miquel van Smoorenburg: rt_add and rt_del
 *       {1.79} Bernd Eckenfels:        route_info
 *       {1.80} Bernd Eckenfels:        reject, metric, irtt, 1.2.x support.
 *       {1.81} Bernd Eckenfels:        reject routes need a dummy device
 *960127 {1.82} Bernd Eckenfels:        'mod' and 'dyn' 'reinstate' added
 *960129 {1.83} Bernd Eckenfels:        resolve and getsock now in lib/, 
 *                                      REJECT displays '-' as gatway.
 *960202 {1.84} Bernd Eckenfels:        net-features support added
 *960203 {1.85} Bernd Eckenfels:        "#ifdef' in '#if' for net-features
 *                                      -A  (aftrans) support, get_longopts
 *960206 {1.86} Bernd Eckenfels:        route_init();
 *960218 {1.87} Bernd Eckenfels:        netinet/in.h added
 *960221 {1.88} Bernd Eckenfels:        aftrans_dfl support
 *960222 {1.90} Bernd Eckenfels:        moved all AF specific code to lib/.
 *960413 {1.91} Bernd Eckenfels:        new RTACTION support+FLAG_CACHE/FIB
 *960426 {1.92} Bernd Eckenfels:        FLAG_SYM/-N support
 *960823 {x.xx} Frank Strauss:          INET6 stuff
 *980629 {1.95} Arnaldo Carvalho de Melo: gettext instead of catgets
 *990101 {1.96} Bernd Eckenfels:	fixed usage and FLAG_CACHE Output
 *20010404 {1.97} Arnaldo Carvalho de Melo: use setlocale
 *
 */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
/* #include <net/route.h> realy broken */
#include <netinet/in.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <linux/param.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <ctype.h>
#include "net-support.h"
#include "config.h"
#include "intl.h"
#include "pathnames.h"
#include "version.h"

#define DFLT_AF "inet"

#define FEATURE_ROUTE
#include "lib/net-features.h"	/* needs some of the system includes above! */

char *Release = RELEASE, *Version = "route 1.98 (2001-04-15)";

int opt_n = 0;			/* numerical output flag        */
int opt_v = 0;			/* debugging output flag        */
int opt_e = 1;			/* 1,2,3=type of routetable     */
int opt_fc = 0;			/* routing cache/FIB */
int opt_h = 0;			/* help selected                */
struct aftype *ap;		/* current address family       */

static void usage(void)
{
    fprintf(stderr, _("Usage: route [-nNvee] [-FC] [<AF>]           List kernel routing tables\n"));
    fprintf(stderr, _("       route [-v] [-FC] {add|del|flush} ...  Modify routing table for AF.\n\n"));

    fprintf(stderr, _("       route {-h|--help} [<AF>]              Detailed usage syntax for specified AF.\n"));
    fprintf(stderr, _("       route {-V|--version}                  Display version/author and exit.\n\n"));

    fprintf(stderr, _("        -v, --verbose            be verbose\n"));
    fprintf(stderr, _("        -n, --numeric            don't resolve names\n"));
    fprintf(stderr, _("        -e, --extend             display other/more information\n"));
    fprintf(stderr, _("        -F, --fib                display Forwarding Information Base (default)\n"));
    fprintf(stderr, _("        -C, --cache              display routing cache instead of FIB\n\n"));

    fprintf(stderr, _("  <AF>=Use '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
    fprintf(stderr, _("  List of possible address families (which support routing):\n"));
    print_aflist(1); /* 1 = routeable */
    exit(E_USAGE);
}


static void version(void)
{
    fprintf(stderr, "%s\n%s\n%s\n", Release, Version, Features);
    exit(E_VERSION);
}


int main(int argc, char **argv)
{
    int i, lop, what = 0;
    struct option longopts[] =
    {
	AFTRANS_OPTS,
	{"extend", 0, 0, 'e'},
	{"verbose", 0, 0, 'v'},
	{"version", 0, 0, 'V'},
	{"numeric", 0, 0, 'n'},
	{"symbolic", 0, 0, 'N'},
	{"protocol", 1, 0, 'A'},
	{"cache", 0, 0, 'C'},
	{"fib", 0, 0, 'F'},
	{"help", 0, 0, 'h'},
	{NULL, 0, 0, 0}
    };
    char **tmp;
    char *progname;
    int options;
#if I18N
    setlocale (LC_ALL, "");
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif
    getroute_init();		/* Set up AF routing support */
    setroute_init();
    afname[0] = '\0';
    progname = argv[0];

    /* getopts and -net wont work :-/ */
    for (tmp = argv; *tmp; tmp++) {
	if (!strcmp(*tmp, "-net"))
	    strcpy(*tmp, "#net");
	else if (!strcmp(*tmp, "-host"))
	    strcpy(*tmp, "#host");
    }

    /* Fetch the command-line arguments. */
    while ((i = getopt_long(argc, argv, "A:eCFhnNVv?", longopts, &lop)) != EOF)
	switch (i) {
	case -1:
	    break;
	case 'n':
	    opt_n |= FLAG_NUM;
	    break;
	case 'N':
	    opt_n |= FLAG_SYM;
	    break;
	case 'v':
	    opt_v |= FLAG_VERBOSE;
	    break;
	case 'e':
	    opt_e++;
	    break;
	case 1:
	    if (lop < 0 || lop >= AFTRANS_CNT) {
		EINTERN("route.c", "longopts 1 range");
		break;
	    }
	    if ((i = aftrans_opt(longopts[lop].name)))
		exit(i);
	    break;
	case 'C':
	    opt_fc |= FLAG_CACHE;
	    break;
	case 'F':
	    opt_fc |= FLAG_FIB;
	    break;
	case 'A':
	    if ((i = aftrans_opt(optarg)))
		exit(i);
	    break;
	case 'V':
	    version();
	case 'h':
	case '?':
	    opt_h++;
	    break;
	default:
	    usage();
	}

    argv += optind;
    argc -= optind;

    if (opt_h) {
	if (!afname[0])
	    usage();
	else
	    what = RTACTION_HELP;
    } else {
	if (!afname[0])
	    /* this will initialise afname[] */
	    aftrans_def("route", progname, DFLT_AF);

	/* Do we have to show the contents of the routing table? */
	if (*argv == NULL) {
	    what = RTACTION_SHOW;
	} else {
	    if (!strcmp(*argv, "add"))
		what = RTACTION_ADD;
	    else if (!strcmp(*argv, "del") || !strcmp(*argv, "delete"))
		what = RTACTION_DEL;
	    else if (!strcmp(*argv, "flush"))
		what = RTACTION_FLUSH;
	    else
		usage();
	}
    }

    options = (opt_e & FLAG_EXT) | opt_n | opt_fc | opt_v;
    if (!opt_fc)
	options |= FLAG_FIB;

    if (what == RTACTION_SHOW)
	i = route_info(afname, options);
    else
	i = route_edit(what, afname, options, ++argv);

    if (i == E_OPTERR)
	usage();

    return (i);
}

--- NEW FILE: statistics.c ---
/*
 * Copyright 1997,1999,2000 Andi Kleen. Subject to the GPL. 
 * $Id: statistics.c,v 1.2 2006-08-31 09:32:16 dslinux_amadeus Exp $
 * 19980630 - i18n - Arnaldo Carvalho de Melo <acme at conectiva.com.br> 
 * 19981113 - i18n fixes - Arnaldo Carvalho de Melo <acme at conectiva.com.br> 
 * 19990101 - added net/netstat, -t, -u, -w supprt - Bernd Eckenfels 
 */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "intl.h"

/* #define WARN 1 */

#ifdef WARN
#define UFWARN(x) x
#else
#define UFWARN(x)
#endif

int print_static,f_raw,f_tcp,f_udp,f_unknown = 1;

enum State {
    number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg,
    MaxState
};

#define normal number

struct entry {
    char *title;
    char *out;
    enum State type;
};

struct statedesc { 
    int indent;
    char *title; 
}; 

struct statedesc states[] = { 
    [number] = { 4, NULL },
    [opt_number] = { 4, NULL }, 
    [i_forward] = { 4, NULL },
    [i_inp_icmp] = { 8, N_("ICMP input histogram:") },
    [i_outp_icmp] = { 8, N_("ICMP output histogram:") },
    [MaxState] = {0},
}; 

static enum State state;

#define I_STATIC (1<<16)	/* static configuration option. */
#define I_TITLE  (1<<17)

/* 
 * XXX check against the snmp mib rfc.
 *
 * Don't mark the first field as translatable! It's a snmp MIB standard.
 * - acme
 */
struct entry Iptab[] =
{
    {"Forwarding", N_("Forwarding is %s"), i_forward | I_STATIC},
    {"DefaultTTL", N_("Default TTL is %u"), number | I_STATIC},
    {"InReceives", N_("%u total packets received"), number},
    {"InHdrErrors", N_("%u with invalid headers"), opt_number},
    {"InAddrErrors", N_("%u with invalid addresses"), opt_number},
    {"ForwDatagrams", N_("%u forwarded"), number},
    {"InUnknownProtos", N_("%u with unknown protocol"), opt_number},
    {"InDiscards", N_("%u incoming packets discarded"), number},
    {"InDelivers", N_("%u incoming packets delivered"), number},
    {"OutRequests", N_("%u requests sent out"), number},	/*? */
    {"OutDiscards", N_("%u outgoing packets dropped"), opt_number},
    {"OutNoRoutes", N_("%u dropped because of missing route"), opt_number},
    {"ReasmTimeout", N_("%u fragments dropped after timeout"), opt_number},
    {"ReasmReqds", N_("%u reassemblies required"), opt_number},	/* ? */
    {"ReasmOKs", N_("%u packets reassembled ok"), opt_number},
    {"ReasmFails", N_("%u packet reassembles failed"), opt_number},
    {"FragOKs", N_("%u fragments received ok"), opt_number},
    {"FragFails", N_("%u fragments failed"), opt_number},
    {"FragCreates", N_("%u fragments created"), opt_number}
};

struct entry Icmptab[] =
{
    {"InMsgs", N_("%u ICMP messages received"), number},
    {"InErrors", N_("%u input ICMP message failed."), number},
    {"InDestUnreachs", N_("destination unreachable: %u"), i_inp_icmp | I_TITLE},
    {"InTimeExcds", N_("timeout in transit: %u"), i_inp_icmp | I_TITLE},
    {"InParmProbs", N_("wrong parameters: %u"), i_inp_icmp | I_TITLE},	/*? */
    {"InSrcQuenchs", N_("source quenches: %u"), i_inp_icmp | I_TITLE},
    {"InRedirects", N_("redirects: %u"), i_inp_icmp | I_TITLE},
    {"InEchos", N_("echo requests: %u"), i_inp_icmp | I_TITLE},
    {"InEchoReps", N_("echo replies: %u"), i_inp_icmp | I_TITLE},
    {"InTimestamps", N_("timestamp request: %u"), i_inp_icmp | I_TITLE},
    {"InTimestampReps", N_("timestamp reply: %u"), i_inp_icmp | I_TITLE},
    {"InAddrMasks", N_("address mask request: %u"), i_inp_icmp | I_TITLE},	/*? */
    {"InAddrMaskReps", N_("address mask replies: %u"), i_inp_icmp | I_TITLE},	/*? */
    {"OutMsgs", N_("%u ICMP messages sent"), number},
    {"OutErrors", N_("%u ICMP messages failed"), number},
    {"OutDestUnreachs", N_("destination unreachable: %u"), i_outp_icmp | I_TITLE},
    {"OutTimeExcds", N_("time exceeded: %u"), i_outp_icmp | I_TITLE},
    {"OutParmProbs", N_("wrong parameters: %u"), i_outp_icmp | I_TITLE},	/*? */
    {"OutSrcQuenchs", N_("source quench: %u"), i_outp_icmp | I_TITLE},
    {"OutRedirects", N_("redirect: %u"), i_outp_icmp | I_TITLE},
    {"OutEchos", N_("echo request: %u"), i_outp_icmp | I_TITLE},
    {"OutEchoReps", N_("echo replies: %u"), i_outp_icmp | I_TITLE},
    {"OutTimestamps", N_("timestamp requests: %u"), i_outp_icmp | I_TITLE},
    {"OutTimestampReps", N_("timestamp replies: %u"), i_outp_icmp | I_TITLE},
    {"OutAddrMasks", N_("address mask requests: %u"), i_outp_icmp | I_TITLE},
    {"OutAddrMaskReps", N_("address mask replies: %u"), i_outp_icmp | I_TITLE},
};

struct entry Tcptab[] =
{
    {"RtoAlgorithm", N_("RTO algorithm is %s"), i_rto_alg | I_STATIC},
    {"RtoMin", "", number},
    {"RtoMax", "", number},
    {"MaxConn", "", number},
    {"ActiveOpens", N_("%u active connections openings"), number},
    {"PassiveOpens", N_("%u passive connection openings"), number},
    {"AttemptFails", N_("%u failed connection attempts"), number},
    {"EstabResets", N_("%u connection resets received"), number},
    {"CurrEstab", N_("%u connections established"), number},
    {"InSegs", N_("%u segments received"), number},
    {"OutSegs", N_("%u segments send out"), number},
    {"RetransSegs", N_("%u segments retransmited"), number},
    {"InErrs", N_("%u bad segments received."), number},
    {"OutRsts", N_("%u resets sent"), number},
};

struct entry Udptab[] =
{
    {"InDatagrams", N_("%u packets received"), number},
    {"NoPorts", N_("%u packets to unknown port received."), number},
    {"InErrors", N_("%u packet receive errors"), number},
    {"OutDatagrams", N_("%u packets sent"), number},
};

struct entry Tcpexttab[] =
{
    {"SyncookiesSent", N_("%u SYN cookies sent"), opt_number},
    {"SyncookiesRecv", N_("%u SYN cookies received"), opt_number},
    {"SyncookiesFailed", N_("%u invalid SYN cookies received"), opt_number},

    { "EmbryonicRsts", N_("%u resets received for embryonic SYN_RECV sockets"),
      opt_number },  
    { "PruneCalled", N_("%u packets pruned from receive queue because of socket"
			" buffer overrun"), opt_number },  
    /* obsolete: 2.2.0 doesn't do that anymore */
    { "RcvPruned", N_("%u packets pruned from receive queue"), opt_number },
    { "OfoPruned", N_("%u packets dropped from out-of-order queue because of"
		      " socket buffer overrun"), opt_number }, 
    { "OutOfWindowIcmps", N_("%u ICMP packets dropped because they were "
			     "out-of-window"), opt_number }, 
    { "LockDroppedIcmps", N_("%u ICMP packets dropped because"
			     " socket was locked"), opt_number },
    { "TW", N_("%u TCP sockets finished time wait in fast timer"), opt_number },
    { "TWRecycled", N_("%u time wait sockets recycled by time stamp"), opt_number }, 
    { "TWKilled", N_("%u TCP sockets finished time wait in slow timer"), opt_number },
    { "PAWSPassive", N_("%u passive connections rejected because of"
			" time stamp"), opt_number },
    { "PAWSActive", N_("%u active connections rejected because of "
		       "time stamp"), opt_number },
    { "PAWSEstab", N_("%u packets rejects in established connections because of"
		      " timestamp"), opt_number },
    { "DelayedACKs", N_("%u delayed acks sent"), opt_number },
    { "DelayedACKLocked", N_("%u delayed acks further delayed because of"
			     " locked socket"), opt_number },
    { "DelayedACKLost", N_("Quick ack mode was activated %u times"), opt_number },
    { "ListenOverflows", N_("%u times the listen queue of a socket overflowed"),
      opt_number },
    { "ListenDrops", N_("%u SYNs to LISTEN sockets ignored"), opt_number },
    { "TCPPrequeued", N_("%u packets directly queued to recvmsg prequeue."), 
      opt_number },
    { "TCPDirectCopyFromBacklog", N_("%u packets directly received"
				     " from backlog"), opt_number },
    { "TCPDirectCopyFromPrequeue", N_("%u packets directly received"
				      " from prequeue"), opt_number },
    { "TCPPrequeueDropped", N_("%u packets dropped from prequeue"), opt_number },
    { "TCPHPHits", N_("%u packets header predicted"), number },
    { "TCPHPHitsToUser", N_("%u packets header predicted and "
			    "directly queued to user"), opt_number },
    { "SockMallocOOM", N_("Ran %u times out of system memory during " 
			  "packet sending"), opt_number }, 
};

struct tabtab {
    char *title;
    struct entry *tab;
    size_t size;
    int *flag; 
};

struct tabtab snmptabs[] =
{
    {"Ip", Iptab, sizeof(Iptab), &f_raw},
    {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
    {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
    {"Udp", Udptab, sizeof(Udptab), &f_udp},
    {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
    {NULL}
};

/* XXX IGMP */

int cmpentries(const void *a, const void *b)
{
    return strcmp(((struct entry *) a)->title, ((struct entry *) b)->title);
}

void printval(struct tabtab *tab, char *title, int val)
{
    struct entry *ent = NULL, key;
    int type;
    char buf[512];

    key.title = title;
	if (tab->tab) 
	    ent = bsearch(&key, tab->tab, tab->size / sizeof(struct entry),
			  sizeof(struct entry), cmpentries);
    if (!ent) {			/* try our best */
	printf("%*s%s: %d\n", states[state].indent, "", title, val);
	return;
    }
    type = ent->type;
    if (type & I_STATIC) {
	type &= ~I_STATIC;
	if (!print_static)
	    return;
    }
    if (*ent->out == '\0')
	return;

    if (type & I_TITLE) {
	type &= ~I_TITLE;
	if (state != type)
	    printf("%*s%s\n", states[state].indent, "", _(states[type].title));
    }
    buf[0] = '\0';
    switch (type) {
    case opt_number:
	if (val == 0) 
	    break;
	/*FALL THOUGH*/
    case number:
	snprintf(buf, sizeof(buf), _(ent->out), val);
	break;
    case i_forward:
	type = normal;
	snprintf(buf, sizeof(buf), _(ent->out), val == 2 ? _("enabled") : _("disabled"));
	break;
    case i_outp_icmp:
    case i_inp_icmp:
	if (val > 0)
	    snprintf(buf, sizeof(buf), _(ent->out), val);
	break;
    case i_rto_alg:		/* XXXX */
	break;
    default:
	abort();
    }
    if (buf[0])
	printf("%*s%s\n", states[type].indent, "", buf);

    state = type;
}

struct tabtab *newtable(struct tabtab *tabs, char *title)
{
    struct tabtab *t;
	static struct tabtab dummytab;
	
    for (t = tabs; t->title; t++) {
		if (!strcmp(title, t->title)) {
	    	if (*(t->flag))
				printf("%s:\n", _(title));
		    state = normal;
	   		return t;
		}
	}
	if (!f_unknown) 
		return NULL; 
	printf("%s:\n", _(title));
	dummytab.title = title;
	dummytab.flag = &f_unknown; 
	return &dummytab;
}

void process_fd(FILE *f)
{
    char buf1[1024], buf2[1024];
    char *sp, *np, *p;
    while (fgets(buf1, sizeof buf1, f)) {
	int endflag;
	struct tabtab *tab;

	if (!fgets(buf2, sizeof buf2, f))
	    break;
	sp = strchr(buf1, ':');
	np = strchr(buf2, ':');
	if (!np || !sp)
	    goto formaterr;
	*sp = '\0';

	tab = newtable(snmptabs, buf1);
	if (tab == NULL) {
		printf("unknown %s\n", buf1);
		continue;
	}
	np++;
	sp++;

	endflag = 0;
	while (!endflag) {
	    sp += strspn(sp, " \t\n"); 
	    np += strspn(np, " \t\n"); 
	    /*if (*np == '\0') goto formaterr; */

	    p = sp+strcspn(sp, " \t\n");
	    if (*p == '\0')
		endflag = 1;
	    *p = '\0';

	    if (*sp != '\0' && *(tab->flag)) 	
		printval(tab, sp, strtoul(np, &np, 10));

	    sp = p + 1;
	}
    }
  return;
  
formaterr:
  perror(_("error parsing /proc/net/snmp"));
  return;
}


void parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
{
    FILE *f;

    f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
    
    f = fopen("/proc/net/snmp", "r");
    if (!f) {
	perror(_("cannot open /proc/net/snmp"));
	return;
    }
    process_fd(f);

    if (ferror(f))
	perror("/proc/net/snmp");

    fclose(f);

    f = fopen("/proc/net/netstat", "r");

    if (f) {
    	process_fd(f);

        if (ferror(f))
	    perror("/proc/net/netstat");
    
        fclose(f);
    }
    return;
}
    

void inittab(void)
{
    struct tabtab *t;

    /* we sort at runtime because I'm lazy ;) */
    for (t = snmptabs; t->title; t++)
	qsort(t->tab, t->size / sizeof(struct entry),
	      sizeof(struct entry), cmpentries);
}

--- NEW FILE: mii-tool.c ---
/*

    mii-tool: monitor and control the MII for a network interface

    Usage:

	mii-tool [-VvRrw] [-A media,... | -F media] [interface ...]

    This program is based on Donald Becker's "mii-diag" program, which
    is more capable and verbose than this tool, but also somewhat
    harder to use.

    Copyright (C) 2000 David A. Hinds -- dhinds at pcmcia.sourceforge.org

    mii-diag is written/copyright 1997-2000 by Donald Becker
        <becker at scyld.com>

    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.

    Donald Becker may be reached as becker at scyld.com, or C/O
    Scyld Computing Corporation, 410 Severn Av., Suite 210,
    Annapolis, MD 21403

    References
	http://www.scyld.com/diag/mii-status.html
	http://www.scyld.com/expert/NWay.html
	http://www.national.com/pf/DP/DP83840.html
*/

static char version[] =
"mii-tool.c 1.9 2000/04/28 00:56:08 (David Hinds)\n";

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <time.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#if !defined(__GLIBC__) && !defined(__UC_LIBC__)
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#endif
#include "mii.h"

#define MAX_ETH		8		/* Maximum # of interfaces */

/* Table of known MII's */
static struct {
    u_short	id1, id2;
    char	*name;
} mii_id[] = {
    { 0x0022, 0x5610, "AdHoc AH101LF" },
    { 0x0022, 0x5520, "Altimata AC101LF" },
    { 0x0000, 0x6b90, "AMD 79C901A HomePNA" },
    { 0x0000, 0x6b70, "AMD 79C901A 10baseT" },
    { 0x0181, 0xb800, "Davicom DM9101" },
    { 0x0043, 0x7411, "Enable EL40-331" },
    { 0x0015, 0xf410, "ICS 1889" },
    { 0x0015, 0xf420, "ICS 1890" },
    { 0x0015, 0xf430, "ICS 1892" },
    { 0x02a8, 0x0150, "Intel 82555" },
    { 0x7810, 0x0000, "Level One LXT970/971" },
    { 0x2000, 0x5c00, "National DP83840A" },
    { 0x0181, 0x4410, "Quality QS6612" },
    { 0x0282, 0x1c50, "SMSC 83C180" },
    { 0x0300, 0xe540, "TDK 78Q2120" },
};
#define NMII (sizeof(mii_id)/sizeof(mii_id[0]))

/*--------------------------------------------------------------------*/

struct option longopts[] = {
 /* { name  has_arg  *flag  val } */
    {"advertise",	1, 0, 'A'},	/* Change capabilities advertised. */
    {"force",		1, 0, 'F'},	/* Change capabilities advertised. */
    {"phy",		1, 0, 'p'},	/* Set PHY (MII address) to report. */
    {"log",		0, 0, 'l'},	/* Set PHY (MII address) to report. */
    {"restart",		0, 0, 'r'},	/* Restart link negotiation */
    {"reset",		0, 0, 'R'},	/* Reset the transceiver. */
    {"verbose", 	0, 0, 'v'},	/* Report each action taken.  */
    {"version", 	0, 0, 'V'},	/* Emit version information.  */
    {"watch", 		0, 0, 'w'},	/* Constantly monitor the port.  */
    {"help", 		0, 0, '?'},	/* Give help */
    { 0, 0, 0, 0 }
};

static unsigned int
    verbose = 0,
    opt_version = 0,
    opt_restart = 0,
    opt_reset = 0,
    opt_log = 0,
    opt_watch = 0;
static int nway_advertise = 0;
static int fixed_speed = 0;
static int override_phy = -1;

static int skfd = -1;		/* AF_INET socket for ioctl() calls. */
static struct ifreq ifr;

/*--------------------------------------------------------------------*/

static int mdio_read(int skfd, int location)
{
    struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
    mii->reg_num = location;
    if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) {
	fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
		strerror(errno));
	return -1;
    }
    return mii->val_out;
}

static void mdio_write(int skfd, int location, int value)
{
    struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
    mii->reg_num = location;
    mii->val_in = value;
    if (ioctl(skfd, SIOCSMIIREG, &ifr) < 0) {
	fprintf(stderr, "SIOCSMIIREG on %s failed: %s\n", ifr.ifr_name,
		strerror(errno));
    }
}

/*--------------------------------------------------------------------*/

const struct {
    char	*name;
    u_short	value;
} media[] = {
    /* The order through 100baseT4 matches bits in the BMSR */
    { "10baseT-HD",	MII_AN_10BASET_HD },
    { "10baseT-FD",	MII_AN_10BASET_FD },
    { "100baseTx-HD",	MII_AN_100BASETX_HD },
    { "100baseTx-FD",	MII_AN_100BASETX_FD },
    { "100baseT4",	MII_AN_100BASET4 },
    { "100baseTx",	MII_AN_100BASETX_FD | MII_AN_100BASETX_HD },
    { "10baseT",	MII_AN_10BASET_FD | MII_AN_10BASET_HD },
};
#define NMEDIA (sizeof(media)/sizeof(media[0]))
	
/* Parse an argument list of media types */
static int parse_media(char *arg)
{
    int mask, i;
    char *s;
    mask = strtoul(arg, &s, 16);
    if ((*arg != '\0') && (*s == '\0')) {
	if ((mask & MII_AN_ABILITY_MASK) &&
	    !(mask & ~MII_AN_ABILITY_MASK))
	    return mask;
	goto failed;
    } else {
	mask = 0;
	s = strtok(arg, ", ");
	do {
	    for (i = 0; i < NMEDIA; i++)
		if (strcasecmp(media[i].name, s) == 0) break;
	    if (i == NMEDIA) goto failed;
	    mask |= media[i].value;
	} while ((s = strtok(NULL, ", ")) != NULL);
    }
    return mask;
failed:
    fprintf(stderr, "Invalid media specification '%s'.\n", arg);
    return -1;
}

/*--------------------------------------------------------------------*/

static char *media_list(int mask, int best)
{
    static char buf[100];
    int i;
    *buf = '\0';
    mask >>= 5;
    for (i = 4; i >= 0; i--) {
	if (mask & (1<<i)) {
	    strcat(buf, " ");
	    strcat(buf, media[i].name);
	    if (best) break;
	}
    }
    if (mask & (1<<5))
	strcat(buf, " flow-control");
    return buf;
}

int show_basic_mii(int sock, int phy_id)
{
    char buf[100];
    int i, mii_val[32];
    int bmcr, bmsr, advert, lkpar;

    /* Some bits in the BMSR are latched, but we can't rely on being
       the only reader, so only the current values are meaningful */
    mdio_read(sock, MII_BMSR);
    for (i = 0; i < ((verbose > 1) ? 32 : 8); i++)
	mii_val[i] = mdio_read(sock, i);

    if (mii_val[MII_BMCR] == 0xffff) {
	fprintf(stderr, "  No MII transceiver present!.\n");
	return -1;
    }

    /* Descriptive rename. */
    bmcr = mii_val[MII_BMCR]; bmsr = mii_val[MII_BMSR];
    advert = mii_val[MII_ANAR]; lkpar = mii_val[MII_ANLPAR];

    sprintf(buf, "%s: ", ifr.ifr_name);
    if (bmcr & MII_BMCR_AN_ENA) {
	if (bmsr & MII_BMSR_AN_COMPLETE) {
	    if (advert & lkpar) {
		strcat(buf, (lkpar & MII_AN_ACK) ?
		       "negotiated" : "no autonegotiation,");
		strcat(buf, media_list(advert & lkpar, 1));
		strcat(buf, ", ");
	    } else {
		strcat(buf, "autonegotiation failed, ");
	    }
	} else if (bmcr & MII_BMCR_RESTART) {
	    strcat(buf, "autonegotiation restarted, ");
	}
    } else {
	sprintf(buf+strlen(buf), "%s Mbit, %s duplex, ",
	       (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
	       (bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
    }
    strcat(buf, (bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link");

    if (opt_watch) {
	if (opt_log) {
	    syslog(LOG_INFO, buf);
	} else {
	    char s[20];
	    time_t t = time(NULL);
	    strftime(s, sizeof(s), "%T", localtime(&t));
	    printf("%s %s\n", s, buf);
	}
    } else {
	printf("%s\n", buf);
    }

    if (verbose > 1) {
	printf("  registers for MII PHY %d: ", phy_id);
	for (i = 0; i < 32; i++)
	    printf("%s %4.4x", ((i % 8) ? "" : "\n   "), mii_val[i]);
	printf("\n");
    }

    if (verbose) {
	printf("  product info: ");
	for (i = 0; i < NMII; i++)
	    if ((mii_id[i].id1 == mii_val[2]) &&
		(mii_id[i].id2 == (mii_val[3] & 0xfff0)))
		break;
	if (i < NMII)
	    printf("%s rev %d\n", mii_id[i].name, mii_val[3]&0x0f);
	else
	    printf("vendor %02x:%02x:%02x, model %d rev %d\n",
		   mii_val[2]>>10, (mii_val[2]>>2)&0xff,
		   ((mii_val[2]<<6)|(mii_val[3]>>10))&0xff,
		   (mii_val[3]>>4)&0x3f, mii_val[3]&0x0f);
	printf("  basic mode:   ");
	if (bmcr & MII_BMCR_RESET)
	    printf("software reset, ");
	if (bmcr & MII_BMCR_LOOPBACK)
	    printf("loopback, ");
	if (bmcr & MII_BMCR_ISOLATE)
	    printf("isolate, ");
	if (bmcr & MII_BMCR_COLTEST)
	    printf("collision test, ");
	if (bmcr & MII_BMCR_AN_ENA) {
	    printf("autonegotiation enabled\n");
	} else {
	    printf("%s Mbit, %s duplex\n",
		   (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
		   (bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
	}
	printf("  basic status: ");
	if (bmsr & MII_BMSR_AN_COMPLETE)
	    printf("autonegotiation complete, ");
	else if (bmcr & MII_BMCR_RESTART)
	    printf("autonegotiation restarted, ");
	if (bmsr & MII_BMSR_REMOTE_FAULT)
	    printf("remote fault, ");
	printf((bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link");
	printf("\n  capabilities:%s", media_list(bmsr >> 6, 0));
	printf("\n  advertising: %s", media_list(advert, 0));
	if (lkpar & MII_AN_ABILITY_MASK)
	    printf("\n  link partner:%s", media_list(lkpar, 0));
	printf("\n");
    }
    return 0;
}

/*--------------------------------------------------------------------*/

static int do_one_xcvr(int skfd, char *ifname, int maybe)
{
    struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;

    /* Get the vitals from the interface. */
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    if (ioctl(skfd, SIOCGMIIPHY, &ifr) < 0) {
	if (!maybe || (errno != ENODEV))
	    fprintf(stderr, "SIOCGMIIPHY on '%s' failed: %s\n",
		    ifname, strerror(errno));
	return 1;
    }

    if (override_phy >= 0) {
	printf("using the specified MII index %d.\n", override_phy);
	mii->phy_id = override_phy;
    }

    if (opt_reset) {
	printf("resetting the transceiver...\n");
	mdio_write(skfd, MII_BMCR, MII_BMCR_RESET);
    }
    if (nway_advertise) {
	mdio_write(skfd, MII_ANAR, nway_advertise | 1);
	opt_restart = 1;
    }
    if (opt_restart) {
	printf("restarting autonegotiation...\n");
	mdio_write(skfd, MII_BMCR, 0x0000);
	mdio_write(skfd, MII_BMCR, MII_BMCR_AN_ENA|MII_BMCR_RESTART);
    }
    if (fixed_speed) {
	int bmcr = 0;
	if (fixed_speed & (MII_AN_100BASETX_FD|MII_AN_100BASETX_HD))
	    bmcr |= MII_BMCR_100MBIT;
	if (fixed_speed & (MII_AN_100BASETX_FD|MII_AN_10BASET_FD))
	    bmcr |= MII_BMCR_DUPLEX;
	mdio_write(skfd, MII_BMCR, bmcr);
    }

    if (!opt_restart && !opt_reset && !fixed_speed && !nway_advertise)
	show_basic_mii(skfd, mii->phy_id);

    return 0;
}

/*--------------------------------------------------------------------*/

static void watch_one_xcvr(int skfd, char *ifname, int index)
{
    struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
    static int status[MAX_ETH] = { 0, /* ... */ };
    int now;

    /* Get the vitals from the interface. */
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    if (ioctl(skfd, SIOCGMIIPHY, &ifr) < 0) {
	if (errno != ENODEV)
	    fprintf(stderr, "SIOCGMIIPHY on '%s' failed: %s\n",
		    ifname, strerror(errno));
	return;
    }
    now = (mdio_read(skfd, MII_BMCR) |
	   (mdio_read(skfd, MII_BMSR) << 16));
    if (status[index] && (status[index] != now))
	show_basic_mii(skfd, mii->phy_id);
    status[index] = now;
}

/*--------------------------------------------------------------------*/

const char *usage =
"usage: %s [-VvRrwl] [-A media,... | -F media] [interface ...]\n\
       -V, --version               display version information\n\
       -v, --verbose               more verbose output\n\
       -R, --reset                 reset MII to poweron state\n\
       -r, --restart               restart autonegotiation\n\
       -w, --watch                 monitor for link status changes\n\
       -l, --log                   with -w, write events to syslog\n\
       -A, --advertise=media,...   advertise only specified media\n\
       -F, --force=media           force specified media technology\n\
media: 100baseT4, 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD,\n\
       (to advertise both HD and FD) 100baseTx, 10baseT\n";

int main(int argc, char **argv)
{
    int i, c, ret, errflag = 0;
    char s[6];
    
    while ((c = getopt_long(argc, argv, "A:F:p:lrRvVw?", longopts, 0)) != EOF)
	switch (c) {
	case 'A': nway_advertise = parse_media(optarg); break;
	case 'F': fixed_speed = parse_media(optarg); break;
	case 'p': override_phy = atoi(optarg); break;
	case 'r': opt_restart++;	break;
	case 'R': opt_reset++;		break;
	case 'v': verbose++;		break;
	case 'V': opt_version++;	break;
	case 'w': opt_watch++;		break;
	case 'l': opt_log++;		break;
	case '?': errflag++;
	}
    /* Check for a few inappropriate option combinations */
    if (opt_watch) verbose = 0;
    if (errflag || (fixed_speed & (fixed_speed-1)) ||
	(fixed_speed && (opt_restart || nway_advertise))) {
	fprintf(stderr, usage, argv[0]);
	return 2;
    }

    if (opt_version)
	printf(version);

    /* Open a basic socket. */
    if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
	perror("socket");
	exit(-1);
    }

    /* No remaining args means show all interfaces. */
    if (optind == argc) {
	ret = 1;
	for (i = 0; i < MAX_ETH; i++) {
	    sprintf(s, "eth%d", i);
	    ret &= do_one_xcvr(skfd, s, 1);
	}
	if (ret)
	    fprintf(stderr, "no MII interfaces found\n");
    } else {
	ret = 0;
	for (i = optind; i < argc; i++) {
	    ret |= do_one_xcvr(skfd, argv[i], 0);
	}
    }

    if (opt_watch && (ret == 0)) {
	while (1) {
	    sleep(1);
	    if (optind == argc) {
		for (i = 0; i < MAX_ETH; i++) {
		    sprintf(s, "eth%d", i);
		    watch_one_xcvr(skfd, s, i);
		}
	    } else {
		for (i = optind; i < argc; i++)
		    watch_one_xcvr(skfd, argv[i], i-optind);
	    }
	}
    }

    close(skfd);
    return ret;
}

--- NEW FILE: arp.c ---
/*
 * arp                This file contains an implementation of the command
 *              that maintains the kernel's ARP cache.  It is derived
 *              from Berkeley UNIX arp(8), but cleaner and with sup-
 *              port for devices other than Ethernet.
 *
 * NET-TOOLS    A collection of programs that form the base set of the
 *              NET-3 Networking Distribution for the LINUX operating
 *              system.
 *
 * Version:     $Id: arp.c,v 1.2 2006-08-31 09:32:15 dslinux_amadeus Exp $
 *
 * Maintainer:  Bernd 'eckes' Eckenfels, <net-tools at lina.inka.de>
 *
 * Author:      Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
 *
 * Changes:
 *              (based on work from Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>)
 *              Alan Cox        :       modified for NET3
 *              Andrew Tridgell :       proxy arp netmasks
 *              Bernd Eckenfels :       -n option
 *              Bernd Eckenfels :       Use only /proc for display
 *       {1.60} Bernd Eckenfels :       new arpcode (-i) for 1.3.42 but works 
 *                                      with 1.2.x, too
 *       {1.61} Bernd Eckenfels :       more verbose messages
 *       {1.62} Bernd Eckenfels :       check -t for hw adresses and try to
 *                                      explain EINVAL (jeff)
 *970125 {1.63} Bernd Eckenfels :       -a print hardwarename instead of tiltle
 *970201 {1.64} Bernd Eckenfels :       net-features.h support
 *970203 {1.65} Bernd Eckenfels :       "#define" in "#if", 
 *                                      -H|-A additional to -t|-p
 *970214 {1.66} Bernd Eckenfels :       Fix optarg required for -H and -A
 *970412 {1.67} Bernd Eckenfels :       device=""; is default
 *970514 {1.68} Bernd Eckenfels :       -N and -D
 *970517 {1.69} Bernd Eckenfels :       usage() fixed
 *970622 {1.70} Bernd Eckenfels :       arp -d priv
 *970106 {1.80} Bernd Eckenfels :       new syntax without -D and with "dev <If>",
 *                                      ATF_MAGIC, ATF_DONTPUB support. 
 *                                      Typo fix (Debian Bug#5728 Giuliano Procida)
 *970803 {1.81} Bernd Eckenfels :       removed junk comment line 1
 *970925 {1.82} Bernd Eckenfels :       include fix for libc6
 *980213 (1.83) Phil Blundell:          set ATF_COM on new entries
 *980629 (1.84) Arnaldo Carvalho de Melo: gettext instead of catgets
 *990101 {1.85} Bernd Eckenfels		fixed usage and return codes
 *990105 (1.86) Phil Blundell:		don't ignore EINVAL in arp_set
 *991121 (1.87) Bernd Eckenfels:	yes --device has a mandatory arg
 *010404 (1.88) Arnaldo Carvalho de Melo: use setlocale
 *
 *              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.
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
/* #include <linux/netdevice.h> */
/* #include <linux/if_arp.h>    */
#include <net/if_arp.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include "net-support.h"
#include "pathnames.h"
#include "version.h"
#include "config.h"
#include "intl.h"
#include "util.h"

#define DFLT_AF	"inet"
#define DFLT_HW	"ether"

#define FEATURE_ARP
#include "lib/net-features.h"

char *Release = RELEASE, *Version = "arp 1.88 (2001-04-04)";

int opt_n = 0;			/* do not resolve addresses     */
int opt_N = 0;			/* use symbolic names           */
int opt_v = 0;			/* debugging output flag        */
int opt_D = 0;			/* HW-address is devicename     */
int opt_e = 0;			/* 0=BSD output, 1=new linux    */
int opt_a = 0;			/* all entries, substring match */
struct aftype *ap;		/* current address family       */
struct hwtype *hw;		/* current hardware type        */
int sockfd = 0;			/* active socket descriptor     */
int hw_set = 0;			/* flag if hw-type was set (-H) */
char device[16] = "";		/* current device               */
static void usage(void);

/* Delete an entry from the ARP cache. */
static int arp_del(char **args)
{
    char host[128];
    struct arpreq req;
    struct sockaddr sa;
    int flags = 0;
    int err;

    memset((char *) &req, 0, sizeof(req));

    /* Resolve the host name. */
    if (*args == NULL) {
	fprintf(stderr, _("arp: need host name\n"));
	return (-1);
    }
    safe_strncpy(host, *args, (sizeof host));
    if (ap->input(0, host, &sa) < 0) {
	ap->herror(host);
	return (-1);
    }
    /* If a host has more than one address, use the correct one! */
    memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));

    if (hw_set)
	req.arp_ha.sa_family = hw->type;

    req.arp_flags = ATF_PERM;
    args++;
    while (*args != NULL) {
	if (opt_v)
	    fprintf(stderr, "args=%s\n", *args);
	if (!strcmp(*args, "pub")) {
	    flags |= 1;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "priv")) {
	    flags |= 2;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "temp")) {
	    req.arp_flags &= ~ATF_PERM;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "trail")) {
	    req.arp_flags |= ATF_USETRAILERS;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "dontpub")) {
#ifdef HAVE_ATF_DONTPUB
	    req.arp_flags |= ATF_DONTPUB;
#else
	    ENOSUPP("arp", "ATF_DONTPUB");
#endif
	    args++;
	    continue;
	}
	if (!strcmp(*args, "auto")) {
#ifdef HAVE_ATF_MAGIC
	    req.arp_flags |= ATF_MAGIC;
#else
	    ENOSUPP("arp", "ATF_MAGIC");
#endif
	    args++;
	    continue;
	}
	if (!strcmp(*args, "dev")) {
	    if (*++args == NULL)
		usage();
	    safe_strncpy(device, *args, sizeof(device));
	    args++;
	    continue;
	}
	if (!strcmp(*args, "netmask")) {
	    if (*++args == NULL)
		usage();
	    if (strcmp(*args, "255.255.255.255") != 0) {
		strcpy(host, *args);
		if (ap->input(0, host, &sa) < 0) {
		    ap->herror(host);
		    return (-1);
		}
		memcpy((char *) &req.arp_netmask, (char *) &sa,
		       sizeof(struct sockaddr));
		req.arp_flags |= ATF_NETMASK;
	    }
	    args++;
	    continue;
	}
	usage();
    }
    if (flags == 0)
	flags = 3;

    strcpy(req.arp_dev, device);

    err = -1;

    /* Call the kernel. */
    if (flags & 2) {
	if (opt_v)
	    fprintf(stderr, "arp: SIOCDARP(nopub)\n");
	if ((err = ioctl(sockfd, SIOCDARP, &req) < 0)) {
	    if (errno == ENXIO) {
		if (flags & 1)
		    goto nopub;
		printf(_("No ARP entry for %s\n"), host);
		return (-1);
	    }
	    perror("SIOCDARP(priv)");
	    return (-1);
	}
    }
    if ((flags & 1) && (err)) {
      nopub:
	req.arp_flags |= ATF_PUBL;
	if (opt_v)
	    fprintf(stderr, "arp: SIOCDARP(pub)\n");
	if (ioctl(sockfd, SIOCDARP, &req) < 0) {
	    if (errno == ENXIO) {
		printf(_("No ARP entry for %s\n"), host);
		return (-1);
	    }
	    perror("SIOCDARP(pub)");
	    return (-1);
	}
    }
    return (0);
}

/* Get the hardware address to a specified interface name */
static int arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw)
{
    struct ifreq ifr;
    struct hwtype *xhw;

    strcpy(ifr.ifr_name, ifname);
    if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
	fprintf(stderr, _("arp: cant get HW-Address for `%s': %s.\n"), ifname, strerror(errno));
	return (-1);
    }
    if (hw && (ifr.ifr_hwaddr.sa_family != hw->type)) {
	fprintf(stderr, _("arp: protocol type mismatch.\n"));
	return (-1);
    }
    memcpy((char *) sa, (char *) &(ifr.ifr_hwaddr), sizeof(struct sockaddr));

    if (opt_v) {
	if (!(xhw = get_hwntype(ifr.ifr_hwaddr.sa_family)) || (xhw->print == 0)) {
	    xhw = get_hwntype(-1);
	}
	fprintf(stderr, _("arp: device `%s' has HW address %s `%s'.\n"), ifname, xhw->name, xhw->print((char *)&ifr.ifr_hwaddr.sa_data));
    }
    return (0);
}

/* Set an entry in the ARP cache. */
static int arp_set(char **args)
{
    char host[128];
    struct arpreq req;
    struct sockaddr sa;
    int flags;

    memset((char *) &req, 0, sizeof(req));

    /* Resolve the host name. */
    if (*args == NULL) {
	fprintf(stderr, _("arp: need host name\n"));
	return (-1);
    }
    safe_strncpy(host, *args++, (sizeof host));
    if (ap->input(0, host, &sa) < 0) {
	ap->herror(host);
	return (-1);
    }
    /* If a host has more than one address, use the correct one! */
    memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));

    /* Fetch the hardware address. */
    if (*args == NULL) {
	fprintf(stderr, _("arp: need hardware address\n"));
	return (-1);
    }
    if (opt_D) {
	if (arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL) < 0)
	    return (-1);
    } else {
	if (hw->input(*args++, &req.arp_ha) < 0) {
	    fprintf(stderr, _("arp: invalid hardware address\n"));
	    return (-1);
	}
    }

    /* Check out any modifiers. */
    flags = ATF_PERM | ATF_COM;
    while (*args != NULL) {
	if (!strcmp(*args, "temp")) {
	    flags &= ~ATF_PERM;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "pub")) {
	    flags |= ATF_PUBL;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "priv")) {
	    flags &= ~ATF_PUBL;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "trail")) {
	    flags |= ATF_USETRAILERS;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "dontpub")) {
#ifdef HAVE_ATF_DONTPUB
	    flags |= ATF_DONTPUB;
#else
	    ENOSUPP("arp", "ATF_DONTPUB");
#endif
	    args++;
	    continue;
	}
	if (!strcmp(*args, "auto")) {
#ifdef HAVE_ATF_MAGIC
	    flags |= ATF_MAGIC;
#else
	    ENOSUPP("arp", "ATF_MAGIC");
#endif
	    args++;
	    continue;
	}
	if (!strcmp(*args, "dev")) {
	    if (*++args == NULL)
		usage();
	    safe_strncpy(device, *args, sizeof(device));
	    args++;
	    continue;
	}
	if (!strcmp(*args, "netmask")) {
	    if (*++args == NULL)
		usage();
	    if (strcmp(*args, "255.255.255.255") != 0) {
		strcpy(host, *args);
		if (ap->input(0, host, &sa) < 0) {
		    ap->herror(host);
		    return (-1);
		}
		memcpy((char *) &req.arp_netmask, (char *) &sa,
		       sizeof(struct sockaddr));
		flags |= ATF_NETMASK;
	    }
	    args++;
	    continue;
	}
	usage();
    }

    /* Fill in the remainder of the request. */
    req.arp_flags = flags;

    strcpy(req.arp_dev, device);

    /* Call the kernel. */
    if (opt_v)
	fprintf(stderr, "arp: SIOCSARP()\n");
    if (ioctl(sockfd, SIOCSARP, &req) < 0) {
        perror("SIOCSARP");
	return (-1);
    }
    return (0);
}


/* Process an EtherFile */
static int arp_file(char *name)
{
    char buff[1024];
    char *sp, *args[32];
    int linenr, argc;
    FILE *fp;

    if ((fp = fopen(name, "r")) == NULL) {
	fprintf(stderr, _("arp: cannot open etherfile %s !\n"), name);
	return (-1);
    }
    /* Read the lines in the file. */
    linenr = 0;
    while (fgets(buff, sizeof(buff), fp) != (char *) NULL) {
	linenr++;
	if (opt_v == 1)
	    fprintf(stderr, ">> %s", buff);
	if ((sp = strchr(buff, '\n')) != (char *) NULL)
	    *sp = '\0';
	if (buff[0] == '#' || buff[0] == '\0')
	    continue;

	argc = getargs(buff, args);
	if (argc < 2) {
	    fprintf(stderr, _("arp: format error on line %u of etherfile %s !\n"),
		    linenr, name);
	    continue;
	}
	if (strchr (args[0], ':') != NULL) {
	    /* We have a correct ethers file, switch hw adress and hostname
	       for arp */
	    char *cp;
	    cp = args[1];
	    args[1] = args[0];
	    args[0] = cp;
	}
	if (arp_set(args) != 0)
	    fprintf(stderr, _("arp: cannot set entry on line %u of etherfile %s !\n"),
		    linenr, name);
    }

    (void) fclose(fp);
    return (0);
}


/* Print the contents of an ARP request block. */
static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mask, char *dev)
{
    static int title = 0;
    struct hwtype *xhw;
    char flags[10];

    xhw = get_hwntype(type);
    if (xhw == NULL)
	xhw = get_hwtype(DFLT_HW);

    if (title++ == 0) {
	printf(_("Address                  HWtype  HWaddress           Flags Mask            Iface\n"));
    }
    /* Setup the flags. */
    flags[0] = '\0';
    if (arp_flags & ATF_COM)
	strcat(flags, "C");
    if (arp_flags & ATF_PERM)
	strcat(flags, "M");
    if (arp_flags & ATF_PUBL)
	strcat(flags, "P");
#ifdef HAVE_ATF_MAGIC
    if (arp_flags & ATF_MAGIC)
	strcat(flags, "A");
#endif
#ifdef HAVE_ATF_DONTPUB
    if (arp_flags & ATF_DONTPUB)
	strcat(flags, "!");
#endif
    if (arp_flags & ATF_USETRAILERS)
	strcat(flags, "T");

    if (!(arp_flags & ATF_NETMASK))
	mask = "";

    printf("%-23.23s  ", name);

    if (!(arp_flags & ATF_COM)) {
	if (arp_flags & ATF_PUBL)
	    printf("%-8.8s%-20.20s", "*", "*");
	else
	    printf("%-8.8s%-20.20s", "", _("(incomplete)"));
    } else {
	printf("%-8.8s%-20.20s", xhw->name, hwa);
    }

    printf("%-6.6s%-15.15s %s\n", flags, mask, dev);
}

/* Print the contents of an ARP request block. */
static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, char *mask, char *dev)
{
    struct hwtype *xhw;

    xhw = get_hwntype(type);
    if (xhw == NULL)
	xhw = get_hwtype(DFLT_HW);

    printf(_("%s (%s) at "), name, ip);

    if (!(arp_flags & ATF_COM)) {
	if (arp_flags & ATF_PUBL)
	    printf("* ");
	else
	    printf(_("<incomplete> "));
    } else {
	printf("%s [%s] ", hwa, xhw->name);
    }

    if (arp_flags & ATF_NETMASK)
	printf(_("netmask %s "), mask);

    if (arp_flags & ATF_PERM)
	printf("PERM ");
    if (arp_flags & ATF_PUBL)
	printf("PUP ");
#ifdef HAVE_ATF_MAGIC
    if (arp_flags & ATF_MAGIC)
	printf("AUTO ");
#endif
#ifdef HAVE_ATF_DONTPUB
    if (arp_flags & ATF_DONTPUB)
	printf("DONTPUB ");
#endif
    if (arp_flags & ATF_USETRAILERS)
	printf("TRAIL ");

    printf(_("on %s\n"), dev);
}


/* Display the contents of the ARP cache in the kernel. */
static int arp_show(char *name)
{
    char host[100];
    struct sockaddr sa;
    char ip[100];
    char hwa[100];
    char mask[100];
    char line[200];
    char dev[100];
    int type, flags;
    FILE *fp;
    char *hostname;
    int num, entries = 0, showed = 0;

    host[0] = '\0';

    if (name != NULL) {
	/* Resolve the host name. */
	safe_strncpy(host, name, (sizeof host));
	if (ap->input(0, host, &sa) < 0) {
	    ap->herror(host);
	    return (-1);
	}
	safe_strncpy(host, ap->sprint(&sa, 1), sizeof(host));
    }
    /* Open the PROCps kernel table. */
    if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
	perror(_PATH_PROCNET_ARP);
	return (-1);
    }
    /* Bypass header -- read until newline */
    if (fgets(line, sizeof(line), fp) != (char *) NULL) {
	strcpy(mask, "-");
	strcpy(dev, "-");
	/* Read the ARP cache entries. */
	for (; fgets(line, sizeof(line), fp);) {
	    num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
			 ip, &type, &flags, hwa, mask, dev);
	    if (num < 4)
		break;

	    entries++;
	    /* if the user specified hw-type differs, skip it */
	    if (hw_set && (type != hw->type))
		continue;

	    /* if the user specified address differs, skip it */
	    if (host[0] && strcmp(ip, host))
		continue;

	    /* if the user specified device differs, skip it */
	    if (device[0] && strcmp(dev, device))
		continue;

	    showed++;
	    /* This IS ugly but it works -be */
	    if (opt_n)
		hostname = "?";
	    else {
		if (ap->input(0, ip, &sa) < 0)
		    hostname = ip;
		else
		    hostname = ap->sprint(&sa, opt_n | 0x8000);
		if (strcmp(hostname, ip) == 0)
		    hostname = "?";
	    }

	    if (opt_e)
		arp_disp_2(hostname[0] == '?' ? ip : hostname, type, flags, hwa, mask, dev);
	    else
		arp_disp(hostname, ip, type, flags, hwa, mask, dev);
	}
    }
    if (opt_v)
	printf(_("Entries: %d\tSkipped: %d\tFound: %d\n"), entries, entries - showed, showed);

    if (!showed) {
	if (host[0] && !opt_a)
	    printf(_("%s (%s) -- no entry\n"), name, host);
	else if (hw_set || host[0] || device[0]) {
	    printf(_("arp: in %d entries no match found.\n"), entries);
	}
    }
    (void) fclose(fp);
    return (0);
}

static void version(void)
{
    fprintf(stderr, "%s\n%s\n%s\n", Release, Version, Features);
    exit(E_VERSION);
}

static void usage(void)
{
    fprintf(stderr, _("Usage:\n  arp [-vn]  [<HW>] [-i <if>] [-a] [<hostname>]             <-Display ARP cache\n"));
    fprintf(stderr, _("  arp [-v]          [-i <if>] -d  <hostname> [pub][nopub]    <-Delete ARP entry\n"));
    fprintf(stderr, _("  arp [-vnD] [<HW>] [-i <if>] -f  [<filename>]              <-Add entry from file\n"));
    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -s  <hostname> <hwaddr> [temp][nopub] <-Add entry\n"));
    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -s  <hostname> <hwaddr> [netmask <nm>] pub  <-''-\n"));
    fprintf(stderr, _("  arp [-v]   [<HW>] [-i <if>] -Ds <hostname> <if> [netmask <nm>] pub      <-''-\n\n"));
    
    fprintf(stderr, _("        -a                       display (all) hosts in alternative (BSD) style\n"));
    fprintf(stderr, _("        -s, --set                set a new ARP entry\n"));
    fprintf(stderr, _("        -d, --delete             delete a specified entry\n"));
    fprintf(stderr, _("        -v, --verbose            be verbose\n"));
    fprintf(stderr, _("        -n, --numeric            don't resolve names\n"));
    fprintf(stderr, _("        -i, --device             specify network interface (e.g. eth0)\n"));
    fprintf(stderr, _("        -D, --use-device         read <hwaddr> from given device\n"));
    fprintf(stderr, _("        -A, -p, --protocol       specify protocol family\n"));
    fprintf(stderr, _("        -f, --file               read new entries from file or from /etc/ethers\n\n"));

    fprintf(stderr, _("  <HW>=Use '-H <hw>' to specify hardware address type. Default: %s\n"), DFLT_HW);
    fprintf(stderr, _("  List of possible hardware types (which support ARP):\n"));
    print_hwlist(1); /* 1 = ARPable */
    exit(E_USAGE);
}

int main(int argc, char **argv)
{
    int i, lop, what;
    struct option longopts[] =
    {
	{"verbose", 0, 0, 'v'},
	{"version", 0, 0, 'V'},
	{"all", 0, 0, 'a'},
	{"delete", 0, 0, 'd'},
	{"file", 0, 0, 'f'},
	{"numeric", 0, 0, 'n'},
	{"set", 0, 0, 's'},
	{"protocol", 1, 0, 'A'},
	{"hw-type", 1, 0, 'H'},
	{"device", 1, 0, 'i'},
	{"help", 0, 0, 'h'},
	{"use-device", 0, 0, 'D'},
	{"symbolic", 0, 0, 'N'},
	{NULL, 0, 0, 0}
    };

#if I18N
    setlocale (LC_ALL, "");
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif

    /* Initialize variables... */
    if ((hw = get_hwtype(DFLT_HW)) == NULL) {
	fprintf(stderr, _("%s: hardware type not supported!\n"), DFLT_HW);
	return (-1);
    }
    if ((ap = get_aftype(DFLT_AF)) == NULL) {
	fprintf(stderr, _("%s: address family not supported!\n"), DFLT_AF);
	return (-1);
    }
    what = 0;

    /* Fetch the command-line arguments. */
    /* opterr = 0; */
    while ((i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV", longopts, &lop)) != EOF)
	switch (i) {
	case 'a':
	    what = 1;
	    opt_a = 1;
	    break;
	case 'f':
	    what = 2;
	    break;
	case 'd':
	    what = 3;
	    break;
	case 's':
	    what = 4;
	    break;


	case 'e':
	    opt_e = 1;
	    break;
	case 'n':
	    opt_n = FLAG_NUM;
	    break;
	case 'D':
	    opt_D = 1;
	    break;
	case 'N':
	    opt_N = FLAG_SYM;
	    fprintf(stderr, _("arp: -N not yet supported.\n"));
	    break;
	case 'v':
	    opt_v = 1;
	    break;

	case 'A':
	case 'p':
	    ap = get_aftype(optarg);
	    if (ap == NULL) {
		fprintf(stderr, _("arp: %s: unknown address family.\n"),
			optarg);
		exit(-1);
	    }
	    break;
	case 'H':
	case 't':
	    hw = get_hwtype(optarg);
	    if (hw == NULL) {
		fprintf(stderr, _("arp: %s: unknown hardware type.\n"),
			optarg);
		exit(-1);
	    }
	    hw_set = 1;
	    break;
	case 'i':
	    safe_strncpy(device, optarg, sizeof(device));
	    break;

	case 'V':
	    version();
	case '?':
	case 'h':
	default:
	    usage();
	}

    if (ap->af != AF_INET) {
	fprintf(stderr, _("arp: %s: kernel only supports 'inet'.\n"),
		ap->name);
	exit(-1);
    }

    /* If not hw type specified get default */
    if(hw_set==0)
	if ((hw = get_hwtype(DFLT_HW)) == NULL) {
	  fprintf(stderr, _("%s: hardware type not supported!\n"), DFLT_HW);
	  return (-1);
	}

    if (hw->alen <= 0) {
	fprintf(stderr, _("arp: %s: hardware type without ARP support.\n"),
		hw->name);
	exit(-1);
    }
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket");
	exit(-1);
    }
    /* Now see what we have to do here... */
    switch (what) {
    case 0:
	opt_e = 1;
	what = arp_show(argv[optind]);
	break;

    case 1:			/* show an ARP entry in the cache */
	what = arp_show(argv[optind]);
	break;

    case 2:			/* process an EtherFile */
	what = arp_file(argv[optind] ? argv[optind] : "/etc/ethers");
	break;

    case 3:			/* delete an ARP entry from the cache */
	what = arp_del(&argv[optind]);
	break;

    case 4:			/* set an ARP entry in the cache */
	what = arp_set(&argv[optind]);
	break;

    default:
	usage();
    }

    exit(what);
}

--- NEW FILE: COPYING ---
		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                          675 Mass Ave, Cambridge, MA 02139, USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	Appendix: How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    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.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.

--- NEW FILE: ifconfig.c ---
/*
 * ifconfig   This file contains an implementation of the command
 *              that either displays or sets the characteristics of
 *              one or more of the system's networking interfaces.
 *
 * Version:     $Id: ifconfig.c,v 1.2 2006-08-31 09:32:15 dslinux_amadeus Exp $
 *
 * Author:      Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
 *              and others.  Copyright 1993 MicroWalt Corporation
 *
 *              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.
 *
 * Patched to support 'add' and 'del' keywords for INET(4) addresses
 * by Mrs. Brisby <mrs.brisby at nimh.org>
 *
[...1200 lines suppressed...]
#else
			exit(1);
#endif
		}
	} else if (pid < 0) {
		fprintf(stderr, "Couldn't fork\n");
		exit(1);
	}

	if (waitpid(pid, &status, 0) < 0) {
		fprintf(stderr, "Error waiting for vconfig - %m\n");
		return -1;
	}

	if (WEXITSTATUS(status) != 0) {
		return -1;
	}

	return 0;
}

--- NEW FILE: config.in ---
#
# config.in	Configure.sh source for the net-tools.
#		This file contains the definition of what the support
#		library contains.  Most of all, it defines which types
#		of address families and hardware we know of.
#
# NET-TOOLS	A collection of programs that form the base set of the
#		NET-3 Networking Distribution for the LINUX operating
#		system.
#
# Version:	config.in 1.22	(99-04-19)
#
# Author:	Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
#		Copyright 1988-1993 MicroWalt Corporation
#
#		Bernd 'eckes' Eckenfels <net-tools at lina.inka.de>
#		Arnaldo Carvalho de Melo <acme at conectiva.com.br>
#		  GNU gettext - I18N
#
#		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.
#
= /*
=  * config.h	Automatically generated configuration includefile
=  *
=  * NET-TOOLS	A collection of programs that form the base set of the
=  *		NET-3 Networking Distribution for the LINUX operating
=  *		system.
=  *
=  *		DO  NOT  EDIT  DIRECTLY
=  *
=  */
*
*
*              Internationalization
*
* The net-tools package has currently been translated to French,
* German and Brazilian Portugese.  Other translations are, of
* course, welcome.  Answer `n' here if you have no support for
* internationalization on your system.
*
bool 'Does your system support GNU gettext?' I18N n
*
*
*             Protocol Families.
* 
bool 'UNIX protocol family' HAVE_AFUNIX y
bool 'INET (TCP/IP) protocol family' HAVE_AFINET y
bool 'INET6 (IPv6) protocol family' HAVE_AFINET6 n
bool 'Novell IPX/SPX protocol family' HAVE_AFIPX y
bool 'Appletalk DDP protocol family' HAVE_AFATALK y
bool 'AX25 (packet radio) protocol family' HAVE_AFAX25 y
bool 'NET/ROM (packet radio) protocol family' HAVE_AFNETROM y
bool 'Rose (packet radio) protocol family' HAVE_AFROSE n
bool 'X.25 (CCITT) protocol family' HAVE_AFX25 y
bool 'Econet protocol family' HAVE_AFECONET n
bool 'DECnet protocol family' HAVE_AFDECnet n
bool 'Ash protocol family' HAVE_AFASH n
*
*
*            Device Hardware types.
*
bool 'Ethernet (generic) support' HAVE_HWETHER y
bool 'ARCnet support' HAVE_HWARC y
bool 'SLIP (serial line) support' HAVE_HWSLIP y
bool 'PPP (serial line) support' HAVE_HWPPP y
bool 'IPIP Tunnel support' HAVE_HWTUNNEL y
bool 'STRIP (Metricom radio) support' HAVE_HWSTRIP y
bool 'Token ring (generic) support' HAVE_HWTR y
bool 'AX25 (packet radio) support' HAVE_HWAX25 y
bool 'Rose (packet radio) support' HAVE_HWROSE n
bool 'NET/ROM (packet radio) support' HAVE_HWNETROM y
bool 'X.25 (generic) support' HAVE_HWX25 y
bool 'DLCI/FRAD (frame relay) support' HAVE_HWFR y
bool 'SIT (IPv6-in-IPv4) support' HAVE_HWSIT n
bool 'FDDI (generic) support' HAVE_HWFDDI n
bool 'HIPPI (generic) support' HAVE_HWHIPPI n
bool 'Ash hardware support' HAVE_HWASH n
bool '(Cisco)-HDLC/LAPB support' HAVE_HWHDLCLAPB n
bool 'IrDA support' HAVE_HWIRDA y
bool 'Econet hardware support' HAVE_HWEC n
*
*
*           Other Features.
*
bool 'IP Masquerading support' HAVE_FW_MASQUERADE n
bool 'Build iptunnel and ipmaddr' HAVE_IP_TOOLS n
bool 'Build mii-tool' HAVE_MII n

--- NEW FILE: iptunnel.c ---
/*
 * iptunnel.c	       "ip tunnel"
 *
 *		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.
 *
 * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
 *
 *
 * Changes:
 *
 * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
 * Rani Assaf <rani at magic.metawire.com> 980930:	do not allow key for ipip/sit
 * Bernd Eckenfels 990715: add linux/types.h (not clean but solves missing __u16
 * Arnaldo Carvalho de Melo 20010404: use setlocale
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1))
#include <net/if.h>
#include <net/if_arp.h>
#else
#include <linux/if.h>
#include <linux/if_arp.h>
#endif
#include <linux/types.h>
#include <linux/if_tunnel.h>

#include "config.h"
#include "intl.h"
#include "net-support.h"
#include "version.h"
#include "util.h"

#undef GRE_CSUM
#define GRE_CSUM	htons(0x8000)
#undef GRE_ROUTING
#define GRE_ROUTING	htons(0x4000)
#undef GRE_KEY
#define GRE_KEY		htons(0x2000)
#undef GRE_SEQ
#define GRE_SEQ		htons(0x1000)
#undef GRE_STRICT
#define GRE_STRICT	htons(0x0800)
#undef GRE_REC
#define GRE_REC		htons(0x0700)
#undef GRE_FLAGS
#define GRE_FLAGS	htons(0x00F8)
#undef GRE_VERSION
#define GRE_VERSION	htons(0x0007)

/* Old versions of glibc do not define this */
#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 0
#define IPPROTO_GRE	47
#endif

#include "util-ank.h"

char *Release = RELEASE,
     *Version = "iptunnel 1.01",
     *Signature = "Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>";

static void version(void)
{
	printf("%s\n%s\n%s\n", Release, Version, Signature);
	exit(E_VERSION);
}

static void usage(void) __attribute__((noreturn));

static void usage(void)
{
	fprintf(stderr, _("Usage: iptunnel { add | change | del | show } [ NAME ]\n"));
	fprintf(stderr, _("          [ mode { ipip | gre | sit } ] [ remote ADDR ] [ local ADDR ]\n"));
	fprintf(stderr, _("          [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n"));
	fprintf(stderr, _("          [ ttl TTL ] [ tos TOS ] [ nopmtudisc ] [ dev PHYS_DEV ]\n"));
	fprintf(stderr, _("       iptunnel -V | --version\n\n"));
	fprintf(stderr, _("Where: NAME := STRING\n"));
	fprintf(stderr, _("       ADDR := { IP_ADDRESS | any }\n"));
	fprintf(stderr, _("       TOS  := { NUMBER | inherit }\n"));
	fprintf(stderr, _("       TTL  := { 1..255 | inherit }\n"));
	fprintf(stderr, _("       KEY  := { DOTTED_QUAD | NUMBER }\n"));
	exit(-1);
}

static int do_ioctl_get_ifindex(char *dev)
{
	struct ifreq ifr;
	int fd;
	int err;

	strcpy(ifr.ifr_name, dev);
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, SIOCGIFINDEX, &ifr);
	if (err) {
		perror("ioctl");
		return 0;
	}
	close(fd);
	return ifr.ifr_ifindex;
}

static int do_ioctl_get_iftype(char *dev)
{
	struct ifreq ifr;
	int fd;
	int err;

	strcpy(ifr.ifr_name, dev);
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, SIOCGIFHWADDR, &ifr);
	if (err) {
		perror("ioctl");
		return -1;
	}
	close(fd);
	return ifr.ifr_addr.sa_family;
}


static char * do_ioctl_get_ifname(int idx)
{
	static struct ifreq ifr;
	int fd;
	int err;

	ifr.ifr_ifindex = idx;
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, SIOCGIFNAME, &ifr);
	if (err) {
		perror("ioctl");
		return NULL;
	}
	close(fd);
	return ifr.ifr_name;
}



static int do_get_ioctl(char *basedev, struct ip_tunnel_parm *p)
{
	struct ifreq ifr;
	int fd;
	int err;

	strcpy(ifr.ifr_name, basedev);
	ifr.ifr_ifru.ifru_data = (void*)p;
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, SIOCGETTUNNEL, &ifr);
	if (err)
		perror("ioctl");
	close(fd);
	return err;
}

static int do_add_ioctl(int cmd, char *basedev, struct ip_tunnel_parm *p)
{
	struct ifreq ifr;
	int fd;
	int err;

	strcpy(ifr.ifr_name, basedev);
	ifr.ifr_ifru.ifru_data = (void*)p;
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, cmd, &ifr);
	if (err)
		perror("ioctl");
	close(fd);
	return err;
}

static int do_del_ioctl(char *basedev, struct ip_tunnel_parm *p)
{
	struct ifreq ifr;
	int fd;
	int err;

	strcpy(ifr.ifr_name, basedev);
	ifr.ifr_ifru.ifru_data = (void*)p;
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	err = ioctl(fd, SIOCDELTUNNEL, &ifr);
	if (err)
		perror("ioctl");
	close(fd);
	return err;
}

static int parse_args(int argc, char **argv, struct ip_tunnel_parm *p)
{
	char medium[IFNAMSIZ];

	memset(p, 0, sizeof(*p));
	memset(&medium, 0, sizeof(medium));

	p->iph.version = 4;
	p->iph.ihl = 5;
#ifndef IP_DF
#define IP_DF		0x4000		/* Flag: "Don't Fragment"	*/
#endif
	p->iph.frag_off = htons(IP_DF);

	while (argc > 0) {
		if (strcmp(*argv, "mode") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "ipip") == 0) {
				if (p->iph.protocol)
					usage();
				p->iph.protocol = IPPROTO_IPIP;
			} else if (strcmp(*argv, "gre") == 0) {
				if (p->iph.protocol)
					usage();
				p->iph.protocol = IPPROTO_GRE;
			} else if (strcmp(*argv, "sit") == 0) {
				if (p->iph.protocol)
					usage();
				p->iph.protocol = IPPROTO_IPV6;
			} else
				usage();
		} else if (strcmp(*argv, "key") == 0) {
			unsigned uval;
			NEXT_ARG();
			p->i_flags |= GRE_KEY;
			p->o_flags |= GRE_KEY;
			if (strchr(*argv, '.'))
				p->i_key = p->o_key = get_addr32(*argv);
			else {
				if (scan_number(*argv, &uval)<0)
					usage();
				p->i_key = p->o_key = htonl(uval);
			}
		} else if (strcmp(*argv, "ikey") == 0) {
			unsigned uval;
			NEXT_ARG();
			p->i_flags |= GRE_KEY;
			if (strchr(*argv, '.'))
				p->o_key = get_addr32(*argv);
			else {
				if (scan_number(*argv, &uval)<0)
					usage();
				p->i_key = htonl(uval);
			}
		} else if (strcmp(*argv, "okey") == 0) {
			unsigned uval;
			NEXT_ARG();
			p->o_flags |= GRE_KEY;
			if (strchr(*argv, '.'))
				p->o_key = get_addr32(*argv);
			else {
				if (scan_number(*argv, &uval)<0)
					usage();
				p->o_key = htonl(uval);
			}
		} else if (strcmp(*argv, "seq") == 0) {
			p->i_flags |= GRE_SEQ;
			p->o_flags |= GRE_SEQ;
		} else if (strcmp(*argv, "iseq") == 0) {
			p->i_flags |= GRE_SEQ;
		} else if (strcmp(*argv, "oseq") == 0) {
			p->o_flags |= GRE_SEQ;
		} else if (strcmp(*argv, "csum") == 0) {
			p->i_flags |= GRE_CSUM;
			p->o_flags |= GRE_CSUM;
		} else if (strcmp(*argv, "icsum") == 0) {
			p->i_flags |= GRE_CSUM;
		} else if (strcmp(*argv, "ocsum") == 0) {
			p->o_flags |= GRE_CSUM;
		} else if (strcmp(*argv, "nopmtudisc") == 0) {
			p->iph.frag_off = 0;
		} else if (strcmp(*argv, "remote") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "any"))
				p->iph.daddr = get_addr32(*argv);
		} else if (strcmp(*argv, "local") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "any"))
				p->iph.saddr = get_addr32(*argv);
		} else if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			safe_strncpy(medium, *argv, IFNAMSIZ-1);
		} else if (strcmp(*argv, "ttl") == 0) {
			unsigned uval;
			NEXT_ARG();
			if (strcmp(*argv, "inherit") != 0) {
				if (scan_number(*argv, &uval)<0)
					usage();
				if (uval > 255)
					usage();
				p->iph.ttl = uval;
			}
		} else if (strcmp(*argv, "tos") == 0) {
			unsigned uval;
			NEXT_ARG();
			if (strcmp(*argv, "inherit") != 0) {
				if (scan_number(*argv, &uval)<0)
					usage();
				if (uval > 255)
					usage();
				p->iph.tos = uval;
			} else
				p->iph.tos = 1;
		} else {
			if (p->name[0])
				usage();
			safe_strncpy(p->name, *argv, IFNAMSIZ);
		}
		argc--; argv++;
	}

	if (p->iph.protocol == 0) {
		if (memcmp(p->name, "gre", 3) == 0)
			p->iph.protocol = IPPROTO_GRE;
		else if (memcmp(p->name, "ipip", 4) == 0)
			p->iph.protocol = IPPROTO_IPIP;
		else if (memcmp(p->name, "sit", 3) == 0)
			p->iph.protocol = IPPROTO_IPV6;
	}

	if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) {
		if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) {
			fprintf(stderr, _("Keys are not allowed with ipip and sit.\n"));
			return -1;
		}
	}

	if (medium[0]) {
		p->link = do_ioctl_get_ifindex(medium);
		if (p->link == 0)
			return -1;
	}

	if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
		p->i_key = p->iph.daddr;
		p->i_flags |= GRE_KEY;
	}
	if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
		p->o_key = p->iph.daddr;
		p->o_flags |= GRE_KEY;
	}
	if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) {
		fprintf(stderr, _("Broadcast tunnel requires a source address.\n"));
		return -1;
	}
	return 0;
}


static int do_add(int cmd, int argc, char **argv)
{
	struct ip_tunnel_parm p;

	if (parse_args(argc, argv, &p) < 0)
		return -1;

	if (p.iph.ttl && p.iph.frag_off == 0) {
		fprintf(stderr, _("ttl != 0 and noptmudisc are incompatible\n"));
		return -1;
	}

	switch (p.iph.protocol) {
	case IPPROTO_IPIP:
		return do_add_ioctl(cmd, "tunl0", &p);
	case IPPROTO_GRE:
		return do_add_ioctl(cmd, "gre0", &p);
	case IPPROTO_IPV6:
		return do_add_ioctl(cmd, "sit0", &p);
	default:	
		fprintf(stderr, _("cannot determine tunnel mode (ipip, gre or sit)\n"));
		return -1;
	}
	return -1;
}

int do_del(int argc, char **argv)
{
	struct ip_tunnel_parm p;

	if (parse_args(argc, argv, &p) < 0)
		return -1;

	switch (p.iph.protocol) {
	case IPPROTO_IPIP:	
		return do_del_ioctl(p.name[0] ? p.name : "tunl0", &p);
	case IPPROTO_GRE:	
		return do_del_ioctl(p.name[0] ? p.name : "gre0", &p);
	case IPPROTO_IPV6:	
		return do_del_ioctl(p.name[0] ? p.name : "sit0", &p);
	default:	
		return do_del_ioctl(p.name, &p);
	}
	return -1;
}

void print_tunnel(struct ip_tunnel_parm *p)
{
	char s1[256];
	char s2[256];
	char s3[64];
	char s4[64];

	format_host(AF_INET, &p->iph.daddr, s1, sizeof(s1));
	format_host(AF_INET, &p->iph.saddr, s2, sizeof(s2));
	inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
	inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));

	printf(_("%s: %s/ip  remote %s  local %s "),
	       p->name,
	       p->iph.protocol == IPPROTO_IPIP ? "ip" :
	       (p->iph.protocol == IPPROTO_GRE ? "gre" :
		(p->iph.protocol == IPPROTO_IPV6 ? "ipv6" : _("unknown"))),
	       p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any");
	if (p->link) {
		char *n = do_ioctl_get_ifname(p->link);
		if (n)
			printf(" dev %s ", n);
	}
	if (p->iph.ttl)
		printf(" ttl %d ", p->iph.ttl);
	else
		printf(" ttl inherit ");
	if (p->iph.tos) {
		printf(" tos");
		if (p->iph.tos&1)
			printf(" inherit");
		if (p->iph.tos&~1)
			printf("%c%02x ", p->iph.tos&1 ? '/' : ' ', p->iph.tos&~1);
	}
	if (!(p->iph.frag_off&htons(IP_DF)))
		printf(" nopmtudisc");

	if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key)
		printf(" key %s", s3);
	else if ((p->i_flags|p->o_flags)&GRE_KEY) {
		if (p->i_flags&GRE_KEY)
			printf(" ikey %s ", s3);
		if (p->o_flags&GRE_KEY)
			printf(" okey %s ", s4);
	}
	printf("\n");

	if (p->i_flags&GRE_SEQ)
		printf(_("  Drop packets out of sequence.\n"));
	if (p->i_flags&GRE_CSUM)
		printf(_("  Checksum in received packet is required.\n"));
	if (p->o_flags&GRE_SEQ)
		printf(_("  Sequence packets on output.\n"));
	if (p->o_flags&GRE_CSUM)
		printf(_("  Checksum output packets.\n"));
}

static int do_tunnels_list(struct ip_tunnel_parm *p)
{
	char name[IFNAMSIZ];
	unsigned long  rx_bytes, rx_packets, rx_errs, rx_drops,
	rx_fifo, rx_frame,
	tx_bytes, tx_packets, tx_errs, tx_drops,
	tx_fifo, tx_colls, tx_carrier, rx_multi;
	int type;
	struct ip_tunnel_parm p1;

	char buf[512];
	FILE *fp = fopen("/proc/net/dev", "r");
	if (fp == NULL) {
		perror("fopen");
		return -1;
	}

	fgets(buf, sizeof(buf), fp);
	fgets(buf, sizeof(buf), fp);

	while (fgets(buf, sizeof(buf), fp) != NULL) {
		char *ptr;
		buf[sizeof(buf) - 1] = 0;
		if ((ptr = strchr(buf, ':')) == NULL ||
		    (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
			fprintf(stderr, _("Wrong format of /proc/net/dev. Sorry.\n"));
			return -1;
		}
		if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld",
			   &rx_bytes, &rx_packets, &rx_errs, &rx_drops,
			   &rx_fifo, &rx_frame, &rx_multi,
			   &tx_bytes, &tx_packets, &tx_errs, &tx_drops,
			   &tx_fifo, &tx_colls, &tx_carrier) != 14)
			continue;
		if (p->name[0] && strcmp(p->name, name))
			continue;
		type = do_ioctl_get_iftype(name);
		if (type == -1) {
			fprintf(stderr, _("Failed to get type of [%s]\n"), name);
			continue;
		}
		if (type != ARPHRD_TUNNEL && type != ARPHRD_IPGRE && type != ARPHRD_SIT)
			continue;
		memset(&p1, 0, sizeof(p1));
		if (do_get_ioctl(name, &p1))
			continue;
		if ((p->link && p1.link != p->link) ||
		    (p->name[0] && strcmp(p1.name, p->name)) ||
		    (p->iph.daddr && p1.iph.daddr != p->iph.daddr) ||
		    (p->iph.saddr && p1.iph.saddr != p->iph.saddr) ||
		    (p->i_key && p1.i_key != p->i_key))
			continue;
		print_tunnel(&p1);
		if (show_stats) {
			printf(_("RX: Packets    Bytes        Errors CsumErrs OutOfSeq Mcasts\n"));
			printf("    %-10ld %-12ld %-6ld %-8ld %-8ld %-8ld\n",
			       rx_packets, rx_bytes, rx_errs, rx_frame, rx_fifo, rx_multi);
			printf(_("TX: Packets    Bytes        Errors DeadLoop NoRoute  NoBufs\n"));
			printf("    %-10ld %-12ld %-6ld %-8ld %-8ld %-6ld\n\n",
			       tx_packets, tx_bytes, tx_errs, tx_colls, tx_carrier, tx_drops);
		}
	}
	return 0;
}

static int do_show(int argc, char **argv)
{
	int err;
	struct ip_tunnel_parm p;

	if (parse_args(argc, argv, &p) < 0)
		return -1;

	switch (p.iph.protocol) {
	case IPPROTO_IPIP:	
		err = do_get_ioctl(p.name[0] ? p.name : "tunl0", &p);
		break;
	case IPPROTO_GRE:
		err = do_get_ioctl(p.name[0] ? p.name : "gre0", &p);
		break;
	case IPPROTO_IPV6:
		err = do_get_ioctl(p.name[0] ? p.name : "sit0", &p);
		break;
	default:
		do_tunnels_list(&p);
		return 0;
	}
	if (err)
		return -1;

	print_tunnel(&p);
	return 0;
}

int do_iptunnel(int argc, char **argv)
{
	if (argc > 0) {
		if (matches(*argv, "add") == 0)
			return do_add(SIOCADDTUNNEL, argc-1, argv+1);
		if (matches(*argv, "change") == 0)
			return do_add(SIOCCHGTUNNEL, argc-1, argv+1);
		if (matches(*argv, "del") == 0)
			return do_del(argc-1, argv+1);
		if (matches(*argv, "show") == 0 ||
		    matches(*argv, "lst") == 0 ||
		    matches(*argv, "list") == 0)
			return do_show(argc-1, argv+1);
	} else
		return do_show(0, NULL);

	usage();
}


int preferred_family = AF_UNSPEC;
int show_stats = 0;
int resolve_hosts = 0;

int main(int argc, char **argv)
{
	char *basename;

#if I18N
	setlocale (LC_ALL, "");
	bindtextdomain("net-tools", "/usr/share/locale");
	textdomain("net-tools");
#endif

	basename = strrchr(argv[0], '/');
	if (basename == NULL)
		basename = argv[0];
	else
		basename++;
	
	while (argc > 1) {
		if (argv[1][0] != '-')
			break;
		if (matches(argv[1], "-family") == 0) {
			argc--;
			argv++;
			if (argc <= 1)
				usage();
			if (strcmp(argv[1], "inet") == 0)
				preferred_family = AF_INET;
			else if (strcmp(argv[1], "inet6") == 0)
				preferred_family = AF_INET6;
			else
				usage();
		} else if (matches(argv[1], "-stats") == 0 ||
			   matches(argv[1], "-statistics") == 0) {
			++show_stats;
		} else if (matches(argv[1], "-resolve") == 0) {
			++resolve_hosts;
		} else if ((matches(argv[1], "-V") == 0) || (matches(argv[1], "--version") == 0)) {
			version();
		} else
			usage();
		argc--;	argv++;
	}

	return do_iptunnel(argc-1, argv+1);
}

--- NEW FILE: config.h ---
/*
* config.h	No longer automatically generated configuration includefile
*
* NET-TOOLS	A collection of programs that form the base set of the
*		NET-3 Networking Distribution for the LINUX operating
*		system.
*
*		DO  NOT  EDIT  DIRECTLY
*
*/

/* 
 * 
 * Internationalization
 * 
 * The net-tools package has currently been translated to French,
 * German and Brazilian Portugese.  Other translations are, of
 * course, welcome.  Answer `n' here if you have no support for
 * internationalization on your system.
 * 
 */
#include <linux/config.h>
#include <config/autoconf.h>

#define I18N 0

/* 
 * 
 * Protocol Families.
 * 
 */
#define HAVE_AFUNIX 1
#define HAVE_AFINET 1
#ifdef CONFIG_IPV6
#define HAVE_AFINET6 1
#else
#define HAVE_AFINET6 0
#endif
#define HAVE_AFIPX 0
#define HAVE_AFATALK 0
#define HAVE_AFAX25 0
#define HAVE_AFNETROM 0
#define HAVE_AFROSE 0
#define HAVE_AFX25 0
#define HAVE_AFECONET 0
#define HAVE_AFDECnet 0
#define HAVE_AFASH 0

/* 
 * 
 * Device Hardware types.
 * 
 */
#define HAVE_HWETHER 1
#define HAVE_HWARC 0
#define HAVE_HWSLIP 0
#define HAVE_HWPPP 1
#define HAVE_HWTUNNEL 0
#define HAVE_HWSTRIP 0
#define HAVE_HWTR 0
#define HAVE_HWAX25 0
#define HAVE_HWROSE 0
#define HAVE_HWNETROM 0
#define HAVE_HWX25 0
#define HAVE_HWFR 0
#ifdef CONFIG_USER_IPV6
#define HAVE_HWSIT 1
#else
#define HAVE_HWSIT 0
#endif
#define HAVE_HWFDDI 0
#define HAVE_HWHIPPI 0
#define HAVE_HWASH 0
#define HAVE_HWHDLCLAPB 0
#define HAVE_HWIRDA 0
#define HAVE_HWEC 0

/* 
 * 
 * Other Features.
 * 
 */
#define HAVE_FW_MASQUERADE 1
#define HAVE_IP_TOOLS 1
#define HAVE_MII 1

--- NEW FILE: configure.sh ---
#!/usr/bin/env bash
#
# Configure.sh	Generates interactively a config.h from config.in
#
# net-tools	A collection of programs that form the base set of the
#		NET-3 Networking Distribution for the LINUX operating
#		system.
#
# Usage:	Install.sh [--nobackup] [--test]
#
# Version:	Install.sh 1.65	(1996-01-12)
#
# Authors:	Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
#		Johannes Grosen, <grosen at argv.cs.ndsu.nodak.edu>
#		Copyright 1988-1993 MicroWalt Corporation
#
# Modified:
#        {1.65} Bernd eckes Eckenfels <net-tools at lina.inka.de>
#		some layout cleanups, slattach/plipconfig removed.
#		--test for testinstallations added.
#
#		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.
#
#
# Make sure we're really running bash.
#
# I would really have preferred to write this script in a language with
# better string handling, but alas, bash is the only scripting language
# that I can be reasonable sure everybody has on their Linux machine.
#

CONFIG=config.h
MAKECONFIG=config.make


[ -z "$BASH" ] && { echo "Configure requires bash" 1>&2; exit 1; }

# Disable filename globbing once and for all.
# Enable function cacheing.
set -f -h

# set up reading of config file
if [ "$#" != "1" ] || [ ! -f "$1" ]; then
	echo "usage: $0 configfile" 1>&2
	exit 1
fi
exec 7<$1
config_fd_redir='<&7'

#
# readln reads a line into $ans.
#
#	readln prompt default
#
function readln()
{
  echo -n "$1"
  IFS='@' read ans || exit 1
  [ -z "$ans" ] && ans=$2
}

# bool processes a boolean argument
#
#	bool tail
#
function bool()
{
  # Slimier hack to get bash to rescan a line.
  eval "set -- $1"
  ans=""
  while [ "$ans" != "y" -a "$ans" != "n" ]
  do
	readln "$1 ($2) [$3] " "$3"
  done
  if [ "$ans" = "y" ]; then
	echo "#define $2 1" >>${CONFIG}
	echo "$2=1" >>${MAKECONFIG}
    else
	echo "#define $2 0" >>${CONFIG}
	echo "# $2=0" >> ${MAKECONFIG}
  fi
  raw_input_line="bool '$1' $2 $ans"
  eval "$2=$ans"
}

# int processes an integer argument
#
#	int tail
#
function int()
{
  # Slimier hack to get bash to rescan a line.
  eval "set -- $1"
  ans="x"
  while [ $[$ans+0] != "$ans" ];
  do
	readln "$1 ($2) [$3] " "$3"
  done
  echo "#define $2 ($ans)" >>${CONFIG}
  raw_input_line="int '$1' $2 $ans"
  eval "$2=$ans"
}

  #
  # Make sure we start out with a clean slate.
  #
  > config.new
  > ${CONFIG}
  > ${MAKECONFIG}

  stack=''
  branch='t'

  while IFS='@' eval read raw_input_line ${config_fd_redir}
  do
	# Slimy hack to get bash to rescan a line.
	read cmd rest <<-END_OF_COMMAND
		$raw_input_line
	END_OF_COMMAND

	if [ "$cmd" = "*" ]; then
		if [ "$branch" = "t" ]; then
			echo "$raw_input_line"
			# echo "# $rest" >>$CONFIG
			if [ "$prevcmd" != "*" ]; then
				echo >>${CONFIG}
				echo "/* $rest" >>${CONFIG}
			else
				echo " * $rest" >>${CONFIG}
			fi
			prevcmd="*"
		fi
	else
		[ "$prevcmd" = "*" ] && echo " */" >>${CONFIG}
		prevcmd=""
		case "$cmd" in
		=)	[ "$branch" = "t" ] && echo "$rest" >>${CONFIG};;
		:)	[ "$branch" = "t" ] && echo "$raw_input_line" ;;
		int)	[ "$branch" = "t" ] && int "$rest" ;;
		bool)	[ "$branch" = "t" ] && bool "$rest" ;;
		exec)	[ "$branch" = "t" ] && ( sh -c "$rest" ) ;;
		if)	stack="$branch $stack"
			if [ "$branch" = "t" ] && eval "$rest"; then
				branch=t
			else
				branch=f
			fi ;;
		else)	if [ "$branch" = "t" ]; then
				branch=f
			else
				read branch rest <<-END_OF_STACK
					$stack
				END_OF_STACK
			fi ;;
		fi)	[ -z "$stack" ] && echo "Error!  Extra fi." 1>&2
			read branch stack <<-END_OF_STACK
				$stack
			END_OF_STACK
			;;
		esac
	fi
	echo "$raw_input_line" >>config.new
  done
  [ "$prevcmd" = "*" ] && echo " */" >>${CONFIG}

  [ -z "$stack" ] || echo "Error!  Unterminated if." 1>&2

  mv config.new config.status
  exit 0

--- NEW FILE: config.make ---
# I18N=0
HAVE_AFUNIX=1
HAVE_AFINET=1
# HAVE_AFINET6=0
# HAVE_AFIPX=0
# HAVE_AFATALK=0
# HAVE_AFAX25=0
# HAVE_AFNETROM=0
# HAVE_AFROSE=0
# HAVE_AFX25=0
# HAVE_AFECONET=0
# HAVE_AFDECnet=0
# HAVE_AFASH=0
HAVE_HWETHER=1
# HAVE_HWARC=0
# HAVE_HWSLIP= 0
HAVE_HWPPP=1
# HAVE_HWTUNNEL=0
# HAVE_HWSTRIP=0
# HAVE_HWTR=0
# HAVE_HWAX25=0
# HAVE_HWROSE=0
# HAVE_HWNETROM=0
# HAVE_HWX25=0
# HAVE_HWFR=0
# HAVE_HWSIT=0
# HAVE_HWFDDI=0
# HAVE_HWHIPPI=0
# HAVE_HWASH=0
# HAVE_HWHDLCLAPB=0
# HAVE_HWIRDA=0
# HAVE_HWEC=0
HAVE_FW_MASQUERADE=1
HAVE_IP_TOOLS=1
HAVE_MII=1

--- NEW FILE: TODO ---
TODO for net-tools

[ ] pt_BR man pages translation revision, it was done for net-tools 1.33...
[ ] more translations! see the contents of the po directory and ABOUT-NLS
[ ] netstat ddp support
[ ] lib/netrom_rt.c rprint should not rewind _PATH_PROCNET_NR_NEIGH
[ ] ARPHRD_METRICOM [1.3.82]
[ ] include proxy arp description into man page.
[ ] netstat -i: XOVR!=compressed
[ ] nettools.8 man-page
[ ] lib/ddp.c: /etc/atalk.names support
[ ] ARPHRD_LOOPBACK in new kernels, ok? dont think so :-/
[ ] ARPHRD_LOCALTLK and aarp?
[ ] ARCNET support? linux/drivers/net/arcnet.c
[ ] ifconfig support for isdn4linux, linefill...
[ ] Wilfred's Suggestion for config files for route and ifconfig (expand arp
    file format)
[ ] make netstat display more interesting states from interface
	(CSLIP? BSDCOMP?)
[ ] netstat netconfiguration info screen (forwarding, supplied protocols...)
[ ] net-features.h in all tools
[ ] check netstat -o
[ ] supply some informations about new features to HOWTOs
[ ] Config file only works with bash not ash.
[ ] Token ring is almost totally untested.
[ ] additional tools for IPX, AX.25 etc be bundled [ipxripd004, ipx_* tools 
	from caldera, axattach] into existing bins
[ ] "SIOCAX25OPTRT" [Joerg (DL1BKE)]. 1.3.75
[ ] dummy NOARP?! (2. default route for preveting hostunreachables on linedrop)
[ ] ppp_dev_stat called for each dev in ifconfig, why? (1.3.17)
[ ] linux/include/net/br.h?
[ ] get rid of local ipx.h copy

--- NEW FILE: README.ipv6 ---
Notes for IPv6
--------------

If you are using libc5, you may need to edit the Makefile so that
libinet6 is linked in and your IPv6 include files are found in the
right place.  The definitions in question are at about line 91.  You may
also find that the header files provided with inet6-apps are not exactly
what net-tools expects.  This is not a bug in net-tools as such and will
not be fixed in future releases (though if anybody would like to contribute
a patch I would be happy to add a pointer to it here.)  If you have the
option you might consider changing to glibc instead (see below) in which
case you can use the header files supplied with the C library.

If you use glibc, you should ensure that you have version 2.1 or later
installed.  The 2.1 release is available from
<ftp://sourceware.cygnus.com/pub/glibc among> other places.  With this
version of the C library there should be no need to edit the Makefile
or apply any patches to net-tools.

Version 2.0 of glibc has no support for IPv6; patches did exist at one
point but they are now seriously outdated.  Instead you should upgrade
to glibc 2.1.

BUGS
----

"ifconfig eth0 add ..." does not currently auto-load the IPv6 module.


--- NEW FILE: INSTALLING ---
net-tools

                               INSTALLING

Please read the file `README' before you start with the installation of the
net-tools.



HACKERS WAY
-----------
cd /usr/src ; tar xvzf net-tools*.tar.gz
less Makefile ; make config ; make ; make -n install ; make install



CONFIGURE
---------
First of all change into the net-tools directory.

Before you start with the Installation please have a look into the toplevel
Makefile. There are some configuration options with explanations.

To configure the compilation use "make config".  The default answers should
be safe for all configurations.  If you have kernel 2.2 and glibc 2.1 most
of the other options should work as well.


COMPILE
-------  
To compile simply use "make".

There should be no warnings or errors.



INSTALLATION
------------
If you want to install the binaries use "make install".

This will generate backups of your old binaries. If you dont want the
backups, please use "make update" instead. To change the default permissions
and ownerships of the installed binaries and manpages edit the Makefile. You
can test the Installation with "make -n install". This will tell make: Don't
run any commands, just print them.



Bernd 'eckes' Eckenfels
<net-tools at lina.inka.de>

--- NEW FILE: slattach.c ---
/*
 * slattach	A program for handling dialup IP connecions.
 *		This program forces a TTY line to go into a special
 *		terminal line discipline, so that it can be used for
 *		network traffic instead of the regular terminal I/O.
 *
 * Usage:	slattach [-ehlmnqv] [ -k keepalive ] [ -o outfill ]
 * 			[-c cmd] [-s speed] [-p protocol] tty | -
 *
 * Version:	@(#)slattach.c	1.20  1999-05-29
 *
 * Author:      Fred N. van Kempen, <waltje at uWalt.NL.Mugnet.ORG>
 *		Copyright 1988-1993 MicroWalt Corporation
 *
 * Modified:
 *		Alan Cox, <A.Cox at swansea.ac.uk> , July 16 1994
 *		Miquel van Smoorenburg, <miquels at drinkel.ow.org>, October 1994
 *		George Shearer, <gshearer at one.net>, January 3, 1995
 *		Yossi Gottlieb, <yogo at math.tau.ac.il>, February 11, 1995
 *		Peter Tobias, <tobias at et-inf.fho-emden.de>, July 30 1995
 *		Bernd Eckenfels <net-tools at lina.inka.de>, May 29, 1999
 *			added some more printf's for debug and NOBLOCK to open
 *			this should be enough to support 2.2 ttyS-style locks
 *
 *		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.
 */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>          
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <linux/if_slip.h>

#if defined(__GLIBC__)
#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 0
# include <termbits.h>
#else
# include <termios.h>
#endif
#endif

#include "pathnames.h"
#include "net-support.h"
#include "version.h"
#include "config.h"
#include "intl.h"
#include "util.h"

#ifndef _PATH_LOCKD
#define _PATH_LOCKD		"/var/lock"		/* lock files   */
#endif
#ifndef _UID_UUCP
#define _UID_UUCP		"uucp"			/* owns locks   */
#endif


#define DEF_PROTO	"cslip"


const char *Release = RELEASE,
	   *Version = "@(#) slattach 1.21 (1999-11-21)",
	   *Signature = "net-tools, Fred N. van Kempen et al.";


struct {
  const char	*speed;
  int	code;
} tty_speeds[] = {			/* table of usable baud rates	*/
  { "50",	B50	}, { "75",	B75  	},	
  { "110",	B110	}, { "300",	B300	},
  { "600",	B600	}, { "1200",	B1200	},
  { "2400",	B2400	}, { "4800",	B4800	},
  { "9600",	B9600	},
#ifdef B14400
  { "14400",	B14400	},
#endif
#ifdef B19200
  { "19200",	B19200	},
#endif
#ifdef B38400
  { "38400",	B38400	},
#endif
#ifdef B57600
  { "57600",	B57600	},
#endif
#ifdef B115200
  { "115200",	B115200	},
#endif
  { NULL,	0	}
};
struct termios	tty_saved,		/* saved TTY device state	*/
		tty_current;		/* current TTY device state	*/
int		tty_sdisc,		/* saved TTY line discipline	*/
		tty_ldisc,		/* current TTY line discipline	*/
		tty_fd = -1;		/* TTY file descriptor		*/
int		opt_c = 0;		/* "command" to run at exit	*/
int		opt_e = 0;		/* "activate only" flag		*/
int		opt_h = 0;		/* "hangup" on carrier loss	*/
#ifdef SIOCSKEEPALIVE
int		opt_k = 0;		/* "keepalive" value		*/
#endif
int		opt_l = 0;		/* "lock it" flag		*/
int		opt_L = 0;		/* clocal flag			*/
int		opt_m = 0;		/* "set RAW mode" flag		*/
int		opt_n = 0;		/* "set No Mesg" flag		*/
#ifdef SIOCSOUTFILL
int		opt_o = 0;		/* "outfill" value		*/
#endif
int		opt_q = 0;		/* "quiet" flag			*/
int		opt_d = 0;		/* debug flag			*/
int		opt_v = 0;		/* Verbose flag			*/

/* Disable any messages to the input channel of this process. */
static int
tty_nomesg(int fd)
{
  if (opt_n == 0) return(0);
  return(fchmod(fd, 0600));
}

/* Check for an existing lock file on our device */
static int
tty_already_locked(char *nam)
{
  int  i = 0, pid = 0;
  FILE *fd = (FILE *)0;

  /* Does the lock file on our device exist? */
  if ((fd = fopen(nam, "r")) == (FILE *)0)
    return(0); /* No, return perm to continue */

  /* Yes, the lock is there.  Now let's make sure */
  /* at least there's no active process that owns */
  /* that lock.                                   */
  i = fscanf(fd, "%d", &pid);
  (void) fclose(fd);
 
  if (i != 1) /* Lock file format's wrong! Kill't */
    return(0);

  /* We got the pid, check if the process's alive */
  if (kill(pid, 0) == 0)      /* it found process */
      return(1);          /* Yup, it's running... */

  /* Dead, we can proceed locking this device...  */
  return(0);
}

/* Lock or unlock a terminal line. */
static int
tty_lock(char *path, int mode)
{
  static char saved_path[PATH_MAX];
  static int saved_lock = 0;
  struct passwd *pw;
  int fd;
  char apid[16];

  /* We do not lock standard input. */
  if ((opt_l == 0) || ((path == NULL) && (saved_lock == 0))) return(0);

  if (mode == 1) {	/* lock */
	sprintf(saved_path, "%s/LCK..%s", _PATH_LOCKD, path);
	if (tty_already_locked(saved_path)) {
		fprintf(stderr, _("slattach: /dev/%s already locked!\n"), path);
		return(-1);
	}
	if ((fd = creat(saved_path, 0644)) < 0) {
		if (errno != EEXIST)
			if (opt_q == 0) fprintf(stderr,
				_("slattach: tty_lock: (%s): %s\n"),
					saved_path, strerror(errno));
		return(-1);
	}
	sprintf(apid, "%10d\n", getpid());
	if (write(fd, apid, strlen(apid)) != strlen(apid)) {
		fprintf(stderr, _("slattach: cannot write PID file\n"));
		close(fd);
		unlink(saved_path);
		return(-1);
	}

	(void) close(fd);

	/* Make sure UUCP owns the lockfile.  Required by some packages. */
	if ((pw = getpwnam(_UID_UUCP)) == NULL) {
		if (opt_q == 0) fprintf(stderr, _("slattach: tty_lock: UUCP user %s unknown!\n"),
					_UID_UUCP);
		return(0);	/* keep the lock anyway */
	}
	(void) chown(saved_path, pw->pw_uid, pw->pw_gid);
	saved_lock = 1;
  } else {	/* unlock */
	if (saved_lock != 1) return(0);
	if (unlink(saved_path) < 0) {
		if (opt_q == 0) fprintf(stderr,
			"slattach: tty_unlock: (%s): %s\n", saved_path,
							strerror(errno));
		return(-1);
	}
	saved_lock = 0;
  }

  return(0);
}


/* Find a serial speed code in the table. */
static int
tty_find_speed(const char *speed)
{
  int i;

  i = 0;
  while (tty_speeds[i].speed != NULL) {
	if (!strcmp(tty_speeds[i].speed, speed)) return(tty_speeds[i].code);
	i++;
  }
  return(-EINVAL);
}


/* Set the number of stop bits. */
static int
tty_set_stopbits(struct termios *tty, char *stopbits)
{
  if (opt_d) printf("slattach: tty_set_stopbits: %c\n", *stopbits);
  switch(*stopbits) {
	case '1':
		tty->c_cflag &= ~CSTOPB;
		break;

	case '2':
		tty->c_cflag |= CSTOPB;
		break;

	default:
		return(-EINVAL);
  }
  return(0);
}


/* Set the number of data bits. */
static int
tty_set_databits(struct termios *tty, char *databits)
{
  if (opt_d) printf("slattach: tty_set_databits: %c\n", *databits);
  tty->c_cflag &= ~CSIZE;
  switch(*databits) {
	case '5':
		tty->c_cflag |= CS5;
		break;

	case '6':
		tty->c_cflag |= CS6;
		break;

	case '7':
		tty->c_cflag |= CS7;
		break;

	case '8':
		tty->c_cflag |= CS8;
		break;

	default:
		return(-EINVAL);
  }
  return(0);
}


/* Set the type of parity encoding. */
static int
tty_set_parity(struct termios *tty, char *parity)
{
  if (opt_d) printf("slattach: tty_set_parity: %c\n", *parity);
  switch(toupper(*parity)) {
	case 'N':
		tty->c_cflag &= ~(PARENB | PARODD);
		break;  

	case 'O':
		tty->c_cflag &= ~(PARENB | PARODD);
		tty->c_cflag |= (PARENB | PARODD);
		break;

	case 'E':
		tty->c_cflag &= ~(PARENB | PARODD);
		tty->c_cflag |= (PARENB);
		break;

	default:
		return(-EINVAL);
  }
  return(0);
}


/* Set the line speed of a terminal line. */
static int
tty_set_speed(struct termios *tty, const char *speed)
{
  int code;

  if (opt_d) printf("slattach: tty_set_speed: %s\n", speed);
  if ((code = tty_find_speed(speed)) < 0) return(code);
  tty->c_cflag &= ~CBAUD;
  tty->c_cflag |= code;
  return(0);
}


/* Put a terminal line in a transparent state. */
static int
tty_set_raw(struct termios *tty)
{
  int i;
  int speed;

  for(i = 0; i < NCCS; i++)
		tty->c_cc[i] = '\0';		/* no spec chr		*/
  tty->c_cc[VMIN] = 1;
  tty->c_cc[VTIME] = 0;
  tty->c_iflag = (IGNBRK | IGNPAR);		/* input flags		*/
  tty->c_oflag = (0);				/* output flags		*/
  tty->c_lflag = (0);				/* local flags		*/
  speed = (tty->c_cflag & CBAUD);		/* save current speed	*/
  tty->c_cflag = (CRTSCTS | HUPCL | CREAD);	/* UART flags		*/
  if (opt_L) 
	tty->c_cflag |= CLOCAL;
  tty->c_cflag |= speed;			/* restore speed	*/
  return(0);
}


/* Fetch the state of a terminal. */
static int
tty_get_state(struct termios *tty)
{
  if (ioctl(tty_fd, TCGETS, tty) < 0) {
	if (opt_q == 0) fprintf(stderr,
		"slattach: tty_get_state: %s\n", strerror(errno));
	return(-errno);
  }
  return(0);
}


/* Set the state of a terminal. */
static int
tty_set_state(struct termios *tty)
{
  if (ioctl(tty_fd, TCSETS, tty) < 0) {
	if (opt_q == 0) fprintf(stderr,
		"slattach: tty_set_state: %s\n", strerror(errno));
	return(-errno);
  }
  return(0);
}


/* Get the line discipline of a terminal line. */
static int
tty_get_disc(int *disc)
{
  if (ioctl(tty_fd, TIOCGETD, disc) < 0) {
	if (opt_q == 0) fprintf(stderr,
		"slattach: tty_get_disc: %s\n", strerror(errno));
	return(-errno);
  }
  return(0);
}


/* Set the line discipline of a terminal line. */
static int
tty_set_disc(int disc)
{
  if (disc == -1) disc = tty_sdisc;

  if (ioctl(tty_fd, TIOCSETD, &disc) < 0) {
	if (opt_q == 0) fprintf(stderr,
		"slattach: tty_set_disc(%d, %d): %s\n", tty_fd,
			disc, strerror(errno));
	return(-errno);
  }
  return(0);
}


/* Fetch the name of the network interface attached to this terminal. */
static int
tty_get_name(char *name)
{
  if (ioctl(tty_fd, SIOCGIFNAME, name) < 0) {
	if (opt_q == 0) 
	    perror("tty_get_name");
	return(-errno);
  }
  return(0);
}


/* Hangup the line. */
static int
tty_hangup(void)
{
  struct termios tty;

  tty = tty_current;
  (void) tty_set_speed(&tty, "0");
  if (tty_set_state(&tty) < 0) {
	if (opt_q == 0) fprintf(stderr, _("slattach: tty_hangup(DROP): %s\n"), strerror(errno));
	return(-errno);
  }

  (void) sleep(1);

  if (tty_set_state(&tty_current) < 0) {
	if (opt_q == 0) fprintf(stderr, _("slattach: tty_hangup(RAISE): %s\n"), strerror(errno));
	return(-errno);
  }
  return(0);
}


/* Close down a terminal line. */
static int
tty_close(void)
{
  (void) tty_set_disc(tty_sdisc);
  (void) tty_hangup();
  (void) tty_lock(NULL, 0);
  return(0);
}


/* Open and initialize a terminal line. */
static int
tty_open(char *name, const char *speed)
{
  char pathbuf[PATH_MAX];
  register char *path_open, *path_lock;
  int fd;

  /* Try opening the TTY device. */
  if (name != NULL) {
	if (name[0] != '/') {
		if (strlen(name + 6) > sizeof(pathbuf)) {
			if (opt_q == 0) fprintf(stderr, 
				_("slattach: tty name too long\n"));
			return (-1);
		}
		sprintf(pathbuf, "/dev/%s", name);
		path_open = pathbuf;
		path_lock = name;
	} else if (!strncmp(name, "/dev/", 5)) {
		path_open = name;
		path_lock = name + 5;
	} else {
		path_open = name;
		path_lock = name;
	}
	if (opt_d) printf("slattach: tty_open: looking for lock\n");
	if (tty_lock(path_lock, 1)) return(-1); /* can we lock the device? */
	if (opt_d) printf("slattach: tty_open: trying to open %s\n", path_open);
	if ((fd = open(path_open, O_RDWR|O_NDELAY)) < 0) {
		if (opt_q == 0) fprintf(stderr,
			"slattach: tty_open(%s, RW): %s\n",
					path_open, strerror(errno));
		return(-errno);
	}
	tty_fd = fd;
	if (opt_d) printf("slattach: tty_open: %s (fd=%d) ", path_open, fd);
  } else {
	tty_fd = 0;
  }

  /* Fetch the current state of the terminal. */
  if (tty_get_state(&tty_saved) < 0) {
	if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot get current state!\n"));
	return(-errno);
  }
  tty_current = tty_saved;

  /* Fetch the current line discipline of this terminal. */
  if (tty_get_disc(&tty_sdisc) < 0) {
	if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot get current line disc!\n"));
	return(-errno);
  } 
  tty_ldisc = tty_sdisc;

  /* Put this terminal line in a 8-bit transparent mode. */
  if (opt_m == 0) {
	if (tty_set_raw(&tty_current) < 0) {
		if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot set RAW mode!\n"));
		return(-errno);
	}

	/* Set the default speed if we need to. */
	if (speed != NULL) {
		if (tty_set_speed(&tty_current, speed) != 0) {
			if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot set %s bps!\n"),
						speed);
			return(-errno);
		}
	}

	/* Set up a completely 8-bit clean line. */
	if (tty_set_databits(&tty_current, "8") ||
	    tty_set_stopbits(&tty_current, "1") ||
	    tty_set_parity(&tty_current, "N")) {
		if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot set 8N1 mode!\n"));
		return(-errno);
  	}

	/* Set the new line mode. */
	if ((fd = tty_set_state(&tty_current)) < 0) return(fd);
  }

  /* OK, line is open.  Do we need to "silence" it? */
  (void) tty_nomesg(tty_fd);

  return(0);
}


/* Catch any signals. */
static void
sig_catch(int sig)
{
/*  (void) signal(sig, sig_catch); */
  tty_close();
  exit(0);
}


static void
usage(void)
{
  char *usage_msg = "Usage: slattach [-ehlLmnqv] "
#ifdef SIOCSKEEPALIVE
	  "[-k keepalive] "
#endif
#ifdef SIOCSOUTFILL
	  "[-o outfill] "
#endif
	  "[-c cmd] [-s speed] [-p protocol] tty | -\n"
	  "       slattach -V | --version\n";

  fprintf(stderr, usage_msg);
  exit(1);
}


static void 
version(void)
{
    printf("%s\n%s\n%s\n", Release, Version, Signature);
    exit(E_VERSION);
}


int
main(int argc, char *argv[])
{
  char path_buf[128];
  char *path_dev;
  char buff[128];
  const char *speed = NULL;
  const char *proto = DEF_PROTO;
  const char *extcmd = NULL;
  int s;
  static struct option longopts[] = {
    { "version", 0, NULL, 'V' },
    { NULL, 0, NULL, 0 }
  };

  strcpy(path_buf, "");
  path_dev = path_buf;

  /* Scan command line for any arguments. */
  opterr = 0;
  while ((s = getopt_long(argc, argv, "c:ehlLmnp:qs:vdVk:o:", longopts, NULL)) != EOF) switch(s) {
	case 'c':
		extcmd = optarg;
		break;

	case 'e':
		opt_e = 1 - opt_e;
		break;

	case 'h':
		opt_h = 1 - opt_h;
		break;

#ifdef SIOCSKEEPALIVE
	case 'k':
		opt_k = atoi(optarg);
		break;
#endif

	case 'L':
		opt_L = 1 - opt_L;
		break;

	case 'l':
		opt_l = 1 - opt_l;
		break;

	case 'm':
		opt_m = 1 - opt_m;
		break;

	case 'n':
		opt_n = 1 - opt_n;
		break;

#ifdef SIOCSOUTFILL
	case 'o':
		opt_o = atoi(optarg);
		break;
#endif

	case 'p':
		proto = optarg;
		break;

	case 'q':
		opt_q = 1 - opt_q;
		break;

	case 's':
		speed = optarg;
		break;

	case 'd':
		opt_d = 1 - opt_d;
		break;

	case 'v':
		opt_v = 1 - opt_v;
		break;

        case 'V':
		version();
		/*NOTREACHED*/

	default:
		usage();
		/*NOTREACHED*/
  }
  
  if (setvbuf(stdout,0,_IOLBF,0)) {
	if (opt_q == 0) fprintf(stderr, _("slattach: setvbuf(stdout,0,_IOLBF,0) : %s\n"),
				strerror(errno));
	exit(1);
  }

  activate_init();

  if (!strcmp(proto, "tty"))
       opt_m++;

  /* Is a terminal given? */
  if (optind != (argc - 1)) usage();
  safe_strncpy(path_buf, argv[optind], sizeof(path_buf));
  if (!strcmp(path_buf, "-")) {
	opt_e = 1;
	path_dev = NULL;
	if (tty_open(NULL, speed) < 0) { return(3); }
  } else {
	path_dev = path_buf;
	if (tty_open(path_dev, speed) < 0) { return(3); }
  }

  /* Start the correct protocol. */
  if (!strcmp(proto, "tty")) {
	tty_sdisc = N_TTY;
	tty_close();
	return(0);
  }
  if (activate_ld(proto, tty_fd))
        return(1);
  if ((opt_v == 1) || (opt_d == 1)) {
        if (tty_get_name(buff)) { return(3); }
	printf(_("%s started"), proto);
	if (path_dev != NULL) printf(_(" on %s"), path_dev);
	printf(_(" interface %s\n"), buff);
  }

  /* Configure keepalive and outfill. */
#ifdef SIOCSKEEPALIVE
  if (opt_k && (ioctl(tty_fd, SIOCSKEEPALIVE, &opt_k) < 0))
	  fprintf(stderr, "slattach: ioctl(SIOCSKEEPALIVE): %s\n", strerror(errno));
#endif
#ifdef SIOCSOUTFILL
  if (opt_o && (ioctl(tty_fd, SIOCSOUTFILL, &opt_o) < 0))
	  fprintf(stderr, "slattach: ioctl(SIOCSOUTFILL): %s\n", strerror(errno));
#endif

  (void) signal(SIGHUP, sig_catch);
  (void) signal(SIGINT, sig_catch);
  (void) signal(SIGQUIT, sig_catch);
  (void) signal(SIGTERM, sig_catch);

  /* Wait until we get killed if hanging on a terminal. */
  if (opt_e == 0) {
	while(1) {
		if(opt_h == 1) { /* hangup on carrier loss */
			int n = 0;

		        ioctl(tty_fd, TIOCMGET, &n);
			if(!(n & TIOCM_CAR))
				break;
			sleep(15);
		}
		else
			sleep(60);
	};

	tty_close();
	if(extcmd)	/* external command on exit */
		system(extcmd);
  }
  exit(0);
}

--- NEW FILE: rarp.c ---
/*
 * rarp               This file contains an implementation of the command
 *              that maintains the kernel's RARP cache.  It is derived
 *              from Fred N. van Kempen's arp command.
 *
 * Version:	$Id: rarp.c,v 1.2 2006-08-31 09:32:16 dslinux_amadeus Exp $
 *
 * Usage:       rarp -d hostname                      Delete entry
 *              rarp -s hostname ethernet_address     Add entry
 *              rarp -a                               Print entries
 *              rarp -f                               Add frop /etc/ethers
 *
 * Rewritten: Phil Blundell <Philip.Blundell at pobox.com>  1997-08-03
 * gettext instead of catgets: Arnaldo Carvalho de Melo <acme at conectiva.com.br> 1998-06-29
 * 1998-01-01 Bernd Eckenfels	reorganised usage()
 * 2001-04-04 Arnaldo Carvalho de Melo - use setlocale
 *
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>

#define DFLT_HW "ether"

#include "config.h"
#include "intl.h"
#include "net-support.h"
#include "version.h"
#include "pathnames.h"

static char no_rarp_message[] = N_("This kernel does not support RARP.\n");

static char version_string[] = RELEASE "\nrarp 1.03 (2001-04-04)\n";

static struct hwtype *hardware = NULL;

/* Delete an entry from the RARP cache. */
static int rarp_delete(int fd, struct hostent *hp)
{
    struct arpreq req;
    struct sockaddr_in *si;
    unsigned int found = 0;
    char **addr;

    /* The host can have more than one address, so we loop on them. */
    for (addr = hp->h_addr_list; *addr != NULL; addr++) {
	memset((char *) &req, 0, sizeof(req));
	si = (struct sockaddr_in *) &req.arp_pa;
	si->sin_family = hp->h_addrtype;
	memcpy((char *) &si->sin_addr, *addr, hp->h_length);

	/* Call the kernel. */
	if (ioctl(fd, SIOCDRARP, &req) == 0) {
	    found++;
	} else {
	    switch (errno) {
	    case ENXIO:
		break;
	    case ENODEV:
		fputs(_(no_rarp_message), stderr);
		return 1;
	    default:
		perror("SIOCDRARP");
		return 1;
	    }
	}
    }

    if (found == 0)
	printf(_("no RARP entry for %s.\n"), hp->h_name);
    return 0;
}


/* Set an entry in the RARP cache. */
static int rarp_set(int fd, struct hostent *hp, char *hw_addr)
{
    struct arpreq req;
    struct sockaddr_in *si;
    struct sockaddr sap;

    if (hardware->input(hw_addr, &sap)) {
	fprintf(stderr, _("%s: bad hardware address\n"), hw_addr);
	return 1;
    }
    /* Clear and fill in the request block. */
    memset((char *) &req, 0, sizeof(req));
    si = (struct sockaddr_in *) &req.arp_pa;
    si->sin_family = hp->h_addrtype;
    memcpy((char *) &si->sin_addr, hp->h_addr_list[0], hp->h_length);
    req.arp_ha.sa_family = hardware->type;
    memcpy(req.arp_ha.sa_data, sap.sa_data, hardware->alen);

    /* Call the kernel. */
    if (ioctl(fd, SIOCSRARP, &req) < 0) {
	if (errno == ENODEV)
	    fputs(_(no_rarp_message), stderr);
	else
	    perror("SIOCSRARP");
	return 1;
    }
    return 0;
}

/* Process an EtherFile */
static int rarp_file(int fd, const char *name)
{
    char buff[1024];
    char *host, *addr;
    int linenr;
    FILE *fp;
    struct hostent *hp;

    if ((fp = fopen(name, "r")) == NULL) {
	fprintf(stderr, _("rarp: cannot open file %s:%s.\n"), name, strerror(errno));
	return -1;
    }
    /* Read the lines in the file. */
    linenr = 0;
    while (fgets(buff, sizeof(buff), fp)) {
	++linenr;
	if (buff[0] == '#' || buff[0] == '\0')
	    continue;
	if ((addr = strtok(buff, "\n \t")) == NULL)
	    continue;
	if ((host = strtok(NULL, "\n \t")) == NULL) {
	    fprintf(stderr, _("rarp: format error at %s:%u\n"), name, linenr);
	    continue;
	}
	if ((hp = gethostbyname(host)) == NULL) {
	    fprintf(stderr, _("rarp: %s: unknown host\n"), host);
	}
	if (rarp_set(fd, hp, addr) != 0) {
	    fprintf(stderr, _("rarp: cannot set entry from %s:%u\n"), name, linenr);
	}
    }

    (void) fclose(fp);
    return 0;
}

static int display_cache(void)
{
    FILE *fd = fopen(_PATH_PROCNET_RARP, "r");
    char buffer[256];
    if (fd == NULL) {
	if (errno == ENOENT)
	    fputs(_(no_rarp_message), stderr);
	else
	    perror(_PATH_PROCNET_RARP);
	return 1;
    }
    while (feof(fd) == 0) {
	if (fgets(buffer, 255, fd))
	    fputs(buffer, stdout);
    }
    fclose(fd);
    return 0;
}

static void usage(void)
{
    fprintf(stderr, _("Usage: rarp -a                               list entries in cache.\n"));
    fprintf(stderr, _("       rarp -d <hostname>                    delete entry from cache.\n"));
    fprintf(stderr, _("       rarp [<HW>] -s <hostname> <hwaddr>    add entry to cache.\n"));
    fprintf(stderr, _("       rarp -f                               add entries from /etc/ethers.\n"));
    fprintf(stderr, _("       rarp -V                               display program version.\n\n"));

    fprintf(stderr, _("  <HW>=Use '-H <hw>' to specify hardware address type. Default: %s\n"), DFLT_HW);
    fprintf(stderr, _("  List of possible hardware types (which support ARP):\n"));
    print_hwlist(1); /* 1 = ARPable */
    exit(E_USAGE);
}

#define MODE_DISPLAY   1
#define MODE_DELETE    2
#define MODE_SET       3
#define MODE_ETHERS    4

static struct option longopts[] =
{
    {"version", 0, NULL, 'V'},
    {"verbose", 0, NULL, 'v'},
    {"list", 0, NULL, 'a'},
    {"set", 0, NULL, 's'},
    {"delete", 0, NULL, 'd'},
    {"help", 0, NULL, 'h'},
    {NULL, 0, NULL, 0}
};

int main(int argc, char **argv)
{
    int result = 0, mode = 0, c, nargs = 0, verbose = 0;
    char *args[3];
    struct hostent *hp;
    int fd;

#if I18N
    setlocale (LC_ALL, "");
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif

    /* Get a default hardware type.  */
    hardware = get_hwtype(DFLT_HW);

    do {
	c = getopt_long(argc, argv, "-ht:aHdsVvf", longopts, NULL);
	switch (c) {
	case EOF:
	    break;
	case 'h':
	    usage();
	case 'V':
	    fprintf(stderr, version_string);
	    exit(E_VERSION);
	    break;
	case 'v':
	    verbose++;
	    break;
	case 'a':
	case 's':
	case 'd':
	    if (mode) {
		fprintf(stderr, _("%s: illegal option mix.\n"), argv[0]);
		usage();
	    } else {
		mode = (c == 'a' ? MODE_DISPLAY : (c == 'd' ? MODE_DELETE : MODE_SET));
	    }
	    break;
	case 'f':
	    mode = MODE_ETHERS;
	    break;
        case 'H':
	case 't':
	    if (optarg) {
		hardware = get_hwtype(optarg);
	    } else {
		usage();
	    }
	    break;
	case 1:
	    if (nargs == 2) {
		usage();
		exit(1);
	    } else {
		args[nargs++] = optarg;
	    }
	    break;
	default:
	    usage();
	}
    } while (c != EOF);

    if (hardware == NULL) {
	fprintf(stderr, _("rarp: %s: unknown hardware type.\n"), optarg);
	exit(1);
    }
    switch (mode) {
    case 0:
	usage();

    case MODE_DISPLAY:
	if (nargs != (mode - 1)) {
	    usage();
	}
	result = display_cache();
	break;

    case MODE_DELETE:
    case MODE_SET:
	if (nargs != (mode - 1)) {
	    usage();
	}
	if ((hp = gethostbyname(args[0])) == NULL) {
	    fprintf(stderr, _("rarp: %s: unknown host\n"), args[0]);
	    exit(1);
	}
	if (fd = socket(PF_INET, SOCK_DGRAM, 0), fd < 0) {
	    perror("socket");
	    exit(1);
	}
	result = (mode == MODE_DELETE) ? rarp_delete(fd, hp) : rarp_set(fd, hp, args[1]);
	close(fd);
	break;

    case MODE_ETHERS:
	if (nargs != 0 && nargs != 1)
	    usage();
	if (fd = socket(PF_INET, SOCK_DGRAM, 0), fd < 0) {
	    perror("socket");
	    exit(1);
	}
	result = rarp_file(fd, nargs ? args[0] : _PATH_ETHERS);
	close(fd);

    }
    exit(result);
}

--- NEW FILE: README ---
                                README

                Information about the net-tools package

NET-TOOLS	A collection of programs that form the base set of the
		NET-3 networking distribution for the Linux operating
		system.

This package includes the important tools for controlling the network
subsystem of the Linux kernel.  This includes arp, hostname, ifconfig,
netstat, rarp and route.  Additionally, this package contains
utilities relating to particular network hardware types (plipconfig,
slattach) and advanced aspects of IP configuration (iptunnel,
ipmaddr).

Please include the output of "program --version" when reporting bugs.


Contents:
  
   README		This file.

   README.ipv6		Notes for people hacking IPv6.

   INSTALLING		Installation instructions.

   COPYING		Your free copy of the GNU Public License.

   TODO			Some things that need to be done.


                          Notes
                          -----

This is net-tools 1.60.

You need kernel 2.0 or later to use these programs.  These programs
should compile cleanly with both glibc (version 2.0 or 2.1) and libc5,
though support for libc5 is not well tested.

The NLS support was changed from catgets to GNU gettext by Arnaldo
Carvalho de Melo <acme at conectiva.com.br> in June, 1998, to make the
source more readable. Translations to brazilian portuguese (pt_BR),
German (de), Estonian (ee), Czech (cz) and French (fr) are available.
Others are welcome!

route/netstat -r do not yet support different address families
cleanly.  IPX/DDP/AX25 people, please feel free to add the code.

ifconfig now supports changing media types for interfaces.  This requires
a version 2.2 kernel, and many devices do not support it yet.

The tools now support the layout of the 2.2 kernel /proc files (Bernd
Eckenfels).

Some configuration options require kernel version 2.2 and/or
particular versions of the C library.  The defaults should be safe for
all common environments but some of the more esoteric hardware and
protocol families may be more touchy.  Feel free to send patches if
you have problems.

Phil Blundell
philb at gnu.org

Bernd Eckenfels
net-tools at lina.inka.de

--- NEW FILE: nameif.c ---
/* 
 * Name Interfaces based on MAC address.
 * Writen 2000 by Andi Kleen.
 * Subject to the Gnu Public License, version 2.  
 * TODO: make it support token ring etc.
 * $Id: nameif.c,v 1.2 2006-08-31 09:32:16 dslinux_amadeus Exp $
 */ 
#ifndef _GNU_SOURCE 
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <getopt.h>
#include <sys/syslog.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <errno.h>
#include "intl.h" 

const char default_conf[] = "/etc/mactab"; 
const char *fname = default_conf; 
int use_syslog; 
int ctl_sk = -1; 

void err(char *msg) 
{ 
	if (use_syslog) { 
		syslog(LOG_ERR,"%s: %m", msg); 
	} else { 
		perror(msg); 
	} 
	exit(1); 
}

void complain(char *fmt, ...) 
{ 
	va_list ap;
	va_start(ap,fmt);
	if (use_syslog) { 
		vsyslog(LOG_ERR,fmt,ap);
	} else {
		vfprintf(stderr,fmt,ap);
		fputc('\n',stderr); 
	}
	va_end(ap); 
	exit(1);
} 

void warning(char *fmt, ...) 
{ 
	va_list ap;
	va_start(ap,fmt);
	if (use_syslog) { 
		vsyslog(LOG_ERR,fmt,ap);
	} else {
		vfprintf(stderr,fmt,ap);
		fputc('\n',stderr); 
	}
	va_end(ap); 
} 

int parsemac(char *str, unsigned char *mac)
{ 
	char *s; 
	while ((s = strsep(&str, ":")) != NULL) { 
		unsigned byte;
		if (sscanf(s,"%x", &byte)!=1 || byte > 0xff) 
			return -1;
		*mac++ = byte; 
	}  
	return 0;
} 

void *xmalloc(unsigned sz)
{ 
	void *p = calloc(sz,1);
	if (!p) errno=ENOMEM, err("xmalloc"); 
	return p; 
} 

void opensock(void)
{
	if (ctl_sk < 0) 
		ctl_sk = socket(PF_INET,SOCK_DGRAM,0); 
}

#ifndef ifr_newname
#define ifr_newname ifr_ifru.ifru_slave
#endif

int  setname(char *oldname, char *newname)
{
	struct ifreq ifr;
	opensock(); 
	memset(&ifr,0,sizeof(struct ifreq));
	strcpy(ifr.ifr_name, oldname); 
	strcpy(ifr.ifr_newname, newname); 
	return ioctl(ctl_sk, SIOCSIFNAME, &ifr);
}

int getmac(char *name, unsigned char *mac)
{
	int r;
	struct ifreq ifr;
	opensock(); 
	memset(&ifr,0,sizeof(struct ifreq));
	strcpy(ifr.ifr_name, name); 
	r = ioctl(ctl_sk, SIOCGIFHWADDR, &ifr);
	memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); 
	return r; 
}

struct change { 
	struct change *next,**pprev;
	char ifname[IFNAMSIZ+1];
	unsigned char mac[6];
}; 
struct change *clist;

struct change *lookupmac(unsigned char *mac) 
{ 
	struct change *ch;
	for (ch = clist;ch;ch = ch->next) 
		if (!memcmp(ch->mac, mac, 6))
			return ch;
	return NULL; 
} 

int addchange(char *p, struct change *ch, char *pos)
{
	if (strchr(ch->ifname, ':'))
		warning(_("alias device %s at %s probably has no mac"), 
			ch->ifname, pos); 
	if (parsemac(p,ch->mac) < 0) 
		complain(_("cannot parse MAC `%s' at %s"), p, pos); 
	if (clist) 
		clist->pprev = &ch->next;
	ch->next = clist;
	ch->pprev = &clist;
	clist = ch;
	return 0; 
}

void readconf(void)
{
	char *line; 
	size_t linel; 
	int linenum; 
	FILE *ifh;
	char *p;
	int n;

	ifh = fopen(fname, "r");
	if (!ifh) 
		complain(_("opening configuration file %s: %s"),fname,strerror(errno)); 

	line = NULL; 
	linel = 0;
	linenum = 1; 
	while (getdelim(&line, &linel, '\n', ifh) > 0) {
		struct change *ch = xmalloc(sizeof(struct change)); 
		char pos[20]; 

		sprintf(pos, _("line %d"), linenum); 

		if ((p = strchr(line,'#')) != NULL)
			*p = '\0';
		p = line; 
		while (isspace(*p))
			++p; 
		if (*p == '\0')
			continue; 
		n = strcspn(p, " \t"); 
		if (n > IFNAMSIZ) 
			complain(_("interface name too long at line %d"), line);  
		memcpy(ch->ifname, p, n); 
		ch->ifname[n] = 0; 
		p += n; 
		p += strspn(p, " \t"); 
		n = strspn(p, "0123456789ABCDEFabcdef:"); 
		p[n] = 0; 
		addchange(p, ch, pos);
		linenum++;
	}   
	fclose(ifh); 
}

struct option lopt[] = { 
	{"syslog", 0, NULL, 's' },
	{"config-file", 1, NULL, 'c' },
	{"help", 0, NULL, '?' }, 
	{NULL}, 
}; 

void usage(void)
{
	fprintf(stderr, _("usage: nameif [-c configurationfile] [-s] {ifname macaddress}")); 
	exit(1); 
}

int main(int ac, char **av) 
{ 
	FILE *ifh; 
	char *p;
	int n;
	int linenum; 
	char *line = NULL;
	size_t linel = 0;

	for (;;) {
		int c = getopt_long(ac,av,"c:s",lopt,NULL);
		if (c == -1) break;
		switch (c) { 
		default:
		case '?':
			usage(); 
		case 'c':
			fname = optarg;
			break;
		case 's':
			use_syslog = 1;
			break;
		}
	}

	if (use_syslog) 
		openlog("nameif",0,LOG_LOCAL0);
		
	while (optind < ac) { 
		struct change *ch = xmalloc(sizeof(struct change)); 
		char pos[30];

		if ((ac-optind) & 1) 
			usage();
		if (strlen(av[optind])+1>IFNAMSIZ) 
			complain(_("interface name `%s' too long"), av[optind]);
		strcpy(ch->ifname, av[optind]); 
		optind++; 
		sprintf(pos,_("argument %d"),optind); 
		addchange(av[optind], ch, pos); 
		optind++; 
	} 

	if (!clist || fname != default_conf) 
		readconf(); 

	ifh = fopen("/proc/net/dev", "r"); 
	if (!ifh)  complain(_("open of /proc/net/dev: %s"), strerror(errno)); 


	linenum = 0;
	while (getdelim(&line, &linel, '\n', ifh) > 0) {
		struct change *ch; 
		unsigned char mac[6];

		if (linenum++ < 2) 
			continue;
			
		p = line; 
		while (isspace(*p)) 
			++p;
		n = strcspn(p, ": \t");  
		p[n] = 0; 
		
		if (n > IFNAMSIZ-1) 
			complain(_("interface name `%s' too long"), p); 
			
		if (getmac(p, mac) < 0) 
			continue;
			
		ch = lookupmac(mac); 
		if (!ch) 
			continue;
			
		*ch->pprev = ch->next;
		if (strcmp(p, ch->ifname)) { 
			if (setname(p, ch->ifname) < 0)  
				complain(_("cannot change name of %s to %s: %s"),
						p, ch->ifname, strerror(errno)); 
		} 
		free(ch);
	} 
	fclose(ifh); 
	
	while (clist) { 
		struct change *ch = clist;
		clist = clist->next;
		warning(_("interface '%s' not found"), ch->ifname); 
		free(ch); 
	}

	if (use_syslog)
		closelog();
	return 0;
} 


--- NEW FILE: hostname.c ---
/*
 * hostname   This file contains an implementation of the command
 *              that maintains the hostname and the domainname. It
 *              is also used to show the FQDN and the IP-Addresses.
 *
 * Usage:       hostname [-d|-f|-s|-a|-i|-y|-n]
 *              hostname [-h|-V]
 *              hostname {name|-F file}
 *              dnsdmoainname   
 *              nisdomainname {name|-F file}
 *
 * Version:     hostname 1.96 (1996-02-18)
 *
 * Author:      Peter Tobias <tobias at et-inf.fho-emden.de>
 *
 * Changes:
 *      {1.90}  Peter Tobias :          Added -a and -i options.
 *      {1.91}  Bernd Eckenfels :       -v,-V rewritten, long_opts 
 *                                      (major rewrite), usage.
 *960120 {1.95} Bernd Eckenfels :       -y/nisdomainname - support for get/
 *                                      setdomainname added 
 *960218 {1.96} Bernd Eckenfels :       netinet/in.h added
 *980629 {1.97} Arnaldo Carvalho de Melo : gettext instead of catgets for i18n
 *20000213 {1.99} Arnaldo Carvalho de Melo : fixed some i18n strings
 *20010404 {1.100} Arnaldo Carvalho de Melo: use setlocale
 *
 *              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.
 */
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
#include "version.h"
#include "../intl.h"

#if HAVE_AFDECnet
#include <netdnet/dn.h>
#endif

char *Release = RELEASE, *Version = "hostname 1.100 (2001-04-14)";

static char *program_name;
static int opt_v;

static void sethname(char *);
static void setdname(char *);
static void showhname(char *, int);
static void usage(void);
static void version(void);
static void setfilename(char *, int);

#define SETHOST		1
#define SETDOMAIN	2
#define SETNODE		3

#if HAVE_AFDECnet
static void setnname(char *nname)
{
    if (opt_v)
        fprintf(stderr, _("Setting nodename to `%s'\n"),
                nname);
    if (setnodename(nname, strlen(nname))) {
        switch(errno) {
        case EPERM:
            fprintf(stderr, _("%s: you must be root to change the node name\n"), program_name);
            break;
        case EINVAL:
            fprintf(stderr, _("%s: name too long\n"), program_name);
            break;
        default:
        }
	exit(1);
    }
}
#endif /* HAVE_AFDECnet */

static void sethname(char *hname)
{
    if (opt_v)
	fprintf(stderr, _("Setting hostname to `%s'\n"),
		hname);
    if (sethostname(hname, strlen(hname))) {
	switch (errno) {
	case EPERM:
	    fprintf(stderr, _("%s: you must be root to change the host name\n"), program_name);
	    break;
	case EINVAL:
	    fprintf(stderr, _("%s: name too long\n"), program_name);
	    break;
	default:
	    break;
	}
	exit(1);
    };
}

static void setdname(char *dname)
{
    if (opt_v)
	fprintf(stderr, _("Setting domainname to `%s'\n"),
		dname);
    if (setdomainname(dname, strlen(dname))) {
	switch (errno) {
	case EPERM:
	    fprintf(stderr, _("%s: you must be root to change the domain name\n"), program_name);
	    break;
	case EINVAL:
	    fprintf(stderr, _("%s: name too long\n"), program_name);
	    break;
	default:
	    break;
	}
	exit(1);
    };
}

static void showhname(char *hname, int c)
{
    struct hostent *hp;
    register char *p, **alias;
    struct in_addr **ip;

    if (opt_v)
	fprintf(stderr, _("Resolving `%s' ...\n"), hname);
    if (!(hp = gethostbyname(hname))) {
	herror(program_name);
	exit(1);
    }
    if (opt_v) {
	fprintf(stderr, _("Result: h_name=`%s'\n"),
		hp->h_name);

	alias = hp->h_aliases;
	while (alias[0])
	    fprintf(stderr, _("Result: h_aliases=`%s'\n"),
		    *alias++);

	ip = (struct in_addr **) hp->h_addr_list;
	while (ip[0])
	    fprintf(stderr, _("Result: h_addr_list=`%s'\n"),
		    inet_ntoa(**ip++));
    }
    if (!(p = strchr(hp->h_name, '.')) && (c == 'd'))
	return;

    switch (c) {
    case 'a':
	while (hp->h_aliases[0])
	    printf("%s ", *hp->h_aliases++);
	printf("\n");
	break;
    case 'i':
	while (hp->h_addr_list[0])
	    printf("%s ", inet_ntoa(*(struct in_addr *) *hp->h_addr_list++));
	printf("\n");
	break;
    case 'd':
	printf("%s\n", ++p);
	break;
    case 'f':
	printf("%s\n", hp->h_name);
	break;
    case 's':
	if (p != NULL)
	    *p = '\0';
	printf("%s\n", hp->h_name);
	break;
    default:
	break;
    }
}

static void setfilename(char *name, int what)
{
    register FILE *fd;
    register char *p;
    char fline[MAXHOSTNAMELEN];

    if ((fd = fopen(name, "r")) != NULL) {
	while (fgets(fline, sizeof(fline), fd) != NULL) {
	    if ((p = index(fline, '\n')) != NULL)
		*p = '\0';
	    if (opt_v)
		fprintf(stderr, ">> %s\n", fline);
	    if (fline[0] == '#')
		continue;
            switch(what) {
            case SETHOST:
                sethname(fline);
                break;
            case SETDOMAIN:
                setdname(fline);
                break;
#if HAVE_AFDECnet
            case SETNODE:
                setnname(fline);
                break;
#endif /* HAVE_AFDECnet */
            }
	}
	(void) fclose(fd);
    } else {
	fprintf(stderr, _("%s: can't open `%s'\n"),
		program_name, name);
	exit(1);
    }
}

static void version(void)
{
    fprintf(stderr, "%s\n%s\n", Release, Version);
    exit(5); /* E_VERSION */
}

static void usage(void)
{
    fprintf(stderr, _("Usage: hostname [-v] {hostname|-F file}      set hostname (from file)\n"));
    fprintf(stderr, _("       domainname [-v] {nisdomain|-F file}   set NIS domainname (from file)\n"));
#if HAVE_AFDECnet
    fprintf(stderr, _("       nodename [-v] {nodename|-F file}      set DECnet node name (from file)\n"));
#endif
    fprintf(stderr, _("       hostname [-v] [-d|-f|-s|-a|-i|-y|-n]  display formatted name\n"));
    fprintf(stderr, _("       hostname [-v]                         display hostname\n\n"));
    fprintf(stderr, _("       hostname -V|--version|-h|--help       print info and exit\n\n"));
    fprintf(stderr, _("    dnsdomainname=hostname -d, {yp,nis,}domainname=hostname -y\n\n"));
    fprintf(stderr, _("    -s, --short           short host name\n"));
    fprintf(stderr, _("    -a, --alias           alias names\n"));
    fprintf(stderr, _("    -i, --ip-address      addresses for the hostname\n"));
    fprintf(stderr, _("    -f, --fqdn, --long    long host name (FQDN)\n"));
    fprintf(stderr, _("    -d, --domain          DNS domain name\n"));
    fprintf(stderr, _("    -y, --yp, --nis       NIS/YP domainname\n"));
#if HAVE_AFDECnet
    fprintf(stderr, _("    -n, --node            DECnet node name\n"));
#endif /* HAVE_AFDECnet */
    fprintf(stderr, _("    -F, --file            read hostname or NIS domainname from given file\n\n"));
    fprintf(stderr, _(
"   This command can read or set the hostname or the NIS domainname. You can\n"
"   also read the DNS domain or the FQDN (fully qualified domain name).\n"
"   Unless you are using bind or NIS for host lookups you can change the\n"
"   FQDN (Fully Qualified Domain Name) and the DNS domain name (which is\n"
"   part of the FQDN) in the /etc/hosts file.\n"));

    exit(4); /* E_USAGE */
}


int main(int argc, char **argv)
{
    int c;
    char type = '\0';
    int option_index = 0;
    int what = 0;
    char myname[MAXHOSTNAMELEN + 1] =
    {0};
    char *file = NULL;

    static const struct option long_options[] =
    {
	{"domain", no_argument, 0, 'd'},
	{"file", required_argument, 0, 'F'},
	{"fqdn", no_argument, 0, 'f'},
	{"help", no_argument, 0, 'h'},
	{"long", no_argument, 0, 'f'},
	{"short", no_argument, 0, 's'},
	{"version", no_argument, 0, 'V'},
	{"verbose", no_argument, 0, 'v'},
	{"alias", no_argument, 0, 'a'},
	{"ip-address", no_argument, 0, 'i'},
	{"nis", no_argument, 0, 'y'},
	{"yp", no_argument, 0, 'y'},
#if HAVE_AFDECnet
	{"node", no_argument, 0, 'n'},
#endif /* HAVE_AFDECnet */
	{0, 0, 0, 0}
    };
#if I18N
    setlocale (LC_ALL, "");
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif
    program_name = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];

    if (!strcmp(program_name, "ypdomainname") ||
	!strcmp(program_name, "domainname") ||
	!strcmp(program_name, "nisdomainname"))
	what = 3;
    if (!strcmp(program_name, "dnsdomainname"))
	what = 2;
#if HAVE_AFDECnet
    if (!strcmp(program_name, "nodename"))
        what = 4;
#endif /* HAVE_AFDECnet */

    while ((c = getopt_long(argc, argv, "adfF:h?isVvyn", long_options, &option_index)) != EOF)
	switch (c) {
	case 'd':
	    what = 2;
	    break;
	case 'a':
	case 'f':
	case 'i':
	case 's':
	    what = 1;
	    type = c;
	    break;
	case 'y':
	    what = 3;
	    break;
#if HAVE_AFDECnet
	case 'n':
            what = 4;
            break;
#endif /* HAVE_AFDECnet */
	case 'F':
	    file = optarg;
	    break;
	case 'v':
	    opt_v++;
	    break;
	case 'V':
	    version();
	case '?':
	case 'h':
	default:
	    usage();

	};


    switch (what) {
    case 2:
	if (file || (optind < argc)) {
	    fprintf(stderr, _("%s: You can't change the DNS domain name with this command\n"), program_name);
	    fprintf(stderr, _("\nUnless you are using bind or NIS for host lookups you can change the DNS\n"));
	    fprintf(stderr, _("domain name (which is part of the FQDN) in the /etc/hosts file.\n"));
	    exit(1);
	}
	type = 'd';
	/* NOBREAK */
    case 0:
	if (file) {
	    setfilename(file, SETHOST);
	    break;
	}
	if (optind < argc) {
	    sethname(argv[optind]);
	    break;
	}
    case 1:
	gethostname(myname, sizeof(myname));
	if (opt_v)
	    fprintf(stderr, _("gethostname()=`%s'\n"), myname);
	if (!type)
	    printf("%s\n", myname);
	else
	    showhname(myname, type);
	break;
    case 3:
	if (file) {
	    setfilename(file, SETDOMAIN);
	    break;
	}
	if (optind < argc) {
	    setdname(argv[optind]);
	    break;
	}
	getdomainname(myname, sizeof(myname));
	if (opt_v)
	    fprintf(stderr, _("getdomainname()=`%s'\n"), myname);
	printf("%s\n", myname);
	break;
#if HAVE_AFDECnet
    case 4:
        if (file) {
            setfilename(file, SETNODE);
            break;
        }
        if (optind < argc) {
            setnname(argv[optind]);
            break;
        }
        getnodename(myname, sizeof(myname));
        if (opt_v)
            fprintf(stderr, _("getnodename()=`%s'\n"), myname);
        printf("%s\n", myname);
        break;
#endif /* HAVE_AFDECnet */
    }
    exit(0);
}

--- NEW FILE: ABOUT-NLS ---
Notes on the GNU Translation Project
************************************

   GNU is going international!  The GNU Translation Project is a way to
get maintainers, translators and users all together, so GNU will
gradually become able to speak many native languages.  A few packages
already provide native language translation for their messages.

   If you found this `ABOUT-NLS' file inside a GNU distribution, you
may assume that the distributed package does use GNU `gettext'
internally, itself available at your nearest GNU archive site.  But you
do not need to install GNU `gettext' prior to configuring, installing
or using this package with messages translated.

   Installers will find here some useful hints.  These notes also
explain how users should proceed for getting the programs to use the
available translations.  They tell how people wanting to contribute and
work at translations should contact the appropriate team.

   When reporting bugs in the `intl/' directory or bugs which may be
related to internationalization, you should tell about the version of
`gettext' which is used.  The information can be found in the
`intl/VERSION' file, in internationalized packages.

One advise in advance
=====================

   If you want to exploit the full power of the GNU `gettext' package
you should configure it using

             --with-gnu-gettext.

   No existing implementation at this point provides so many useful
features (such as locale alias or message inheritance).  It is also not
possible to provide this additional functionality on top of a catgets
implementation.

   Future versions of GNU `gettext' will very likely provide even more
functionality.  So it might be a good idea to change to GNU `gettext'
as soon as possible.

INSTALL Matters
===============

   Some GNU packages are "localizable" when properly installed; the
programs they contain can be made to speak your own native language.
Most such packages use GNU `gettext'.  Other packages have their own
ways to internationalization, predating GNU `gettext'.

   By default, this package will be installed to allow translation of
messages.  It will automatically detect whether the system provides
usable `catgets' or `gettext' functions.  If neither is available, the
GNU `gettext' own library will be used.  However, installers may use
special options at configuration time for changing this behaviour.  The
commands:

     ./configure --with-gnu-gettext
     ./configure --disable-nls

will respectively bypass system `catgets' or `gettext' to use GNU
`gettext', or else, totally disable translation of messages.

   When you already have GNU `gettext' installed on your system and run
configure without an option for your new package, configure will
probably detect the previously built and installed `libintl.a' file and
will decide to use this.  This might be not what is desirable.  You
should use the more recent version of the GNU `gettext' library.  I.e.
if the file `intl/VERSION' shows that the library which comes with this
package is more recent, you should use

     ./configure --with-gnu-gettext

to prevent auto-detection.

   Internationalized packages have usually many `po/LL.po' files, where
LL gives an ISO 639 two-letter code identifying the language.  Unless
translations are disabled, all those available are installed together
with the package.  However, the environment variable `LINGUAS' may be
set, prior to configuration, to limit the installed set.  `LINGUAS'
should then contain a space separated list of two-letter codes, stating
which languages are allowed.

Using This Package
==================

   As a user, if your language has been installed for this package, you
only have to set the `LANG' environment variable to the appropriate
ISO 639 `LL' two-letter code prior to using the programs in the
package.  For example, let's suppose that you speak German.  At the
shell prompt, merely execute `setenv LANG de' (in `csh') or
`export LANG; LANG=de' (in `sh').  This can be done from your `.login'
or `.profile' file, once and for all.  Packages which are not
internationalized will merely ignore the setting of this variable.

Translating Teams
=================

   The GNU `gettext' tool set contains *everything* maintainers need
for internationalizing their packages for messages.  It also contains
quite useful tools for helping translators at localizing messages to
their native language, once a package has already been
internationalized.

   To achieve the GNU Translation Project, we need many interested
people who like their own language and write it well, and who are also
able to synergize with other translators speaking the same language.
Each translating team has its own mailing list, courtesy of Linux
International.  You may reach your translating team at the address
`LL at li.org', replacing LL by the two-letter ISO 639 code for your
language.  Language codes are *not* the same as country codes given in
ISO 3166.  The following translating teams exist, as of November 1995:

     Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
     Esperanto `eo', Finnish `fi', French `fr', Irish `ga', German
     `de', Greek `el', Italian `it', Japanese `ja', Indonesian `in',
     Norwegian `no', Persian `fa', Polish `pl', Portuguese `pt',
     Russian `ru', Spanish `es', Swedish `sv', Telugu `te' and Turkish
     `tr'.

For example, you may reach the Chinese translating team by writing to
`zh at li.org'.

   If you'd like to volunteer to *work* at translating messages, you
should become a member of the translating team for your own language.
The subscribing address is *not* the same as the list itself, it has
`-request' appended.  For example, Swedish people can send a message to
`sv-request at li.org', having this message body:

     subscribe

   Keep in mind that team members should be interested in *working* at
translations, or at solving translational difficulties, rather than
merely lurking around.  If your team does not exist yet and you want to
start one, please write to `gnu-translation at prep.ai.mit.edu'; you will
then reach the GNU coordinator for all translator teams.

   The English team is special.  It works at improving and uniformizing
the terminology used in GNU.  Proven linguistic skill are praised more
than programming skill, here.  For the time being, please avoid
subscribing to the English team unless explicitely invited to do so.

Available Packages
==================

   Languages are not equally supported in all GNU packages.  The
following matrix shows the current state of GNU internationalization,
as of November 1995.  Listed are: internationalized packages, and
languages for which work is in progress, or about to start.

          See note    cs de en fr it ja nl no pt sv
                \   .-------------------------------.
     chess      (1) |    X  /                    X  |
     clisp          |    X  X  X                    |
     diffutils  (2) |       /  .                    |
     fileutils      |    .  /                       |
     flex       (3) |       /  .                    |
     m4             |    -  /  -  -  .           -  |
     gettext        |    X  /  X           X     X  |
     ptx            |    -  /  -                 -  |
     recode         |    -  /  -        -     -     |
     sh-utils       |    .  /  .                    |
     sharutils      |    X  /  X     X  X     X  X  |
     tar            |    X  /  X           -  X  X  |
     textutils      |    .  /  .                    |
     wdiff          | -  -  /  -  -                 |
                    `-------------------------------'
                      cs de en fr it ja nl no pt sv

   The interpretation legend and notes are:

`/'
     There is no PO file, this package merely defaults to this language.

`.'
     The effort of localizing this package has been undertaken by
     someone, or by a translating team, and work is, or should be in
     progress.

`-'
     A PO file for this package and this language is completed and is
     currently available in a pretest release, or is all ready for
     inclusion in the next release of this package.

`X'
     The localization of this package to this particular language is
     fully completed, and now distributed through an official release.

(1)
     This package is translated to specific languages by methods
     predating GNU `gettext'.  Translations are all kept on disk files,
     and sources contain numbers where one normally expects strings.

(2)
     This package is planned to switch to GNU `gettext'.  For the time
     being, it uses temporary means for internationalization.

(3)
     This package has its translatable strings marked, but does not use
     GNU `gettext'.  A convenience patch may be available separately.

   If November 1995 seems to be old, you may fetch a more recent copy
of this `ABOUT-NLS' file on most GNU archive sites.


--- NEW FILE: intl.h ---
/* Dummy header for libintl.h */

#if I18N
#include <locale.h>
#undef __OPTIMIZE__
#include <libintl.h>
#define _(String) gettext((String))
#define N_(String) (String)
#else
#define _(String) (String)
#define N_(String) (String)
#endif




More information about the dslinux-commit mailing list