rarpd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,357 行 · 第 1/3 页

C
1,357
字号
#ifndef lintstatic  char    *sccsid = "@(#)rarpd.c	4.2  (ULTRIX)        10/16/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1989 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* rarpd.c * *	This is the top level program for the RARP daemon.   *	NOTE: *		The rarpd doesn't recognize ARP packets sent *	to it. Such packets are ignored. The reason for such *	behaviour is: there should be no reason to send a ARP *	packet withing RARP as ARP is always available. *	 *	HISTORY: * *	26-OCT-89 jsd *	Allow device to be optional (use pf0, ie. first network interface) * *	Created by : Uttam Shikarpur Nadig *	Date: 20th February 1989	 * *	Usage: rarpd devicename	[-v] [-f filename] *		The device is specified as qe0, de0 etc. *//* The standard stuff */#include <stdio.h>#include <sys/types.h>#include <sys/time.h>#include <time.h>#include <sys/file.h>#include <limits.h>#include <strings.h>#include <netdb.h>#include <sys/socket.h>#ifndef CTRACE	/* signal.h gives ctrace problems */#include <signal.h>#endif CTRACE#include <sys/ioctl.h>#include <syslog.h>#include <sys/stat.h>#include <nlist.h>/* packet filter specific includes */#include <net/pfilt.h>/* Some definitions *//* #define DEBUG 1		/* The debug option - prevents forking */ #define PACK_SIZE 1000 	 	/*buffer size to receive a rarp packet */#define SEND_SIZE 100		/* The RARP packet being sent back */#define MAX_LINE 256    	/* The length of the longest line allowable			 	* in the file containing the mappings.		  	 	*/#define MAXHOSTLEN 256		/* The max. length of a host name */#define READ_INTERVAL 6000	/* Time interval for reading "ether_file"				 * -- in seconds				 */#define MSG_SIZE 1024		/* The maximum length of a syslog 				 * message.				 */#define NONRARP	0		/* A NON RARP PACKET *//* The packet type, for the filter. Everything at that * level is byte swapped */#define F_RARP	  0x3580 	/* 0x8035 - RARP packet */#define F_REQREVR 0x0300	/* 0x0003 - RARP request reverse type *//* For user level interactions */#define RARP   0x8035 int verbose = 0;		/* The verbose flag; turned on			  	 * by the -v flag			  	 */int debug = 0;			/* for debugging purpose ONLY */typedef struct _mapper {	u_char *ether;			/* The hardware address */	u_char *ip;	 		/* The logical address */	char   hostname[MAXHOSTLEN];	/* name of the host */	struct _mapper *next;		/* Ptr to next struct. */} mapper;extern mapper *enet_list;extern char *ether_file;	/* The mapping file */extern char *progname;		/* The name of the program */int valid_count;		/* # of correct entries in the /etc/ethers				 * or the equivalent file				 */char device[64];		   /* The device on which the filter is			 	    * operating. - qe0, ln0 etc. */char *ether_file = "/etc/ethers";  /* The file for mapping ethernet			 	    *  addr => internet				    */char *progname;			   /*  program name */int disable = 0;		   /* disable re-reading the ethers file */long time_mod;			   /* time when the ethers file was last				    * modified				    */char *system = "/vmunix";	   /* The kernel image being used */struct nlist nl[] = {	{ "_Pfilt_read" },	{ ""},};main (argc,argv)int argc;char **argv;{	char pack_buf[PACK_SIZE];	/* Buffer for the RARP packet */	char send_buf[SEND_SIZE];	/* Buffer to send a resp. out */	int pack_len;			/* Length of the pack. received */	int fid;			/* The file descriptor */	int res;			/* result of a call */	int i;	struct itimerval *value;	/* for timing puposes */	struct itimerval *ovalue;	/* for timing puposes */	void time_out(), read_mapping();	char log_msg[MSG_SIZE];		/* message for syslog */	int msg_len;			/* the message length */	struct stat stat_val;		/* for stat'n "ether_file" */	progname = argv[0];	if (getuid()) {		 fprintf (stderr, "%s: not super user\n", argv[0]);		 exit(1);	}	openlog(progname, LOG_PID); /* opening syslog */	syslog(LOG_INFO, "Started");	/* Complete all the sanity-checks before forking 		1) Check the command line.		2) Check if packet filter has been installed.		3) Check if the device is present.		4) Check if the /etc/ethers file is present.	*/	parse_cmdline(argc,argv);  /* read the command line arguments */	/* check if the packet filter has been configured */	nlist (system, nl);	if (nl[0].n_type == 0) {		fprintf(stderr, "%s: cannot find symbol Pfilt_read in %s\n", progname, system);		fprintf(stderr, "option PACKETFILTER does not appear to be configured in your kernel.\n");		syslog(LOG_ERR, "Packet Filter is not configured in /vmunix");		exit(1);	}	/* Check if the device is present */	if (pfopen(device, 2) < 0) {		syslog(LOG_ERR, "%m: %s", device);		perror(device);		exit(1);	}	close (device);	/* stat the ether_file */	if (stat(ether_file, &stat_val) < 0) {		syslog(LOG_ERR, "%m\(%s\)", ether_file);		perror(ether_file);		usage();	}	time_mod = stat_val.st_mtime;#ifndef DEBUG	if (fork())		exit(0);	else {		(void) open("/", O_RDONLY);		(void) dup2(0, 1);		(void) dup2(0, 2);		{ int tt = open("/dev/tty", O_RDWR);			if (tt > 0) {				(void) ioctl(tt, TIOCNOTTY, 0);				(void) close(tt);			} else {				syslog(LOG_WARNING, "%m: Cannot disassociate from controlling terminal");			}	       }	}#endif DEBUG	/* Read in the mapping file */	read_mapping();	/* All the data required is now available	 * in the list pointed to by the enet_list	 * pointer.	 * Time to activate the filter.	 */	fid = set_filter(device);	/* Set the filter */	/* flush the queue before commencing */	if (ioctl(fid, EIOCFLUSH, 0) < 0) 		syslog(LOG_WARNING, "%m: could not flush input queue");	/* set the timer, inorder to check the status of the	 * "ether_file" periodicaly at period defined by	 * READ_INTERVAL	 */	/* first allocate memory  for timers */	if ((value=(struct itimerval *)malloc(sizeof(struct itimerval)))						== NULL) {		syslog(LOG_ERR, "%m: could not malloc value itimerval struct");		exit(1);	}	if ((ovalue=(struct itimerval *)malloc(sizeof(struct itimerval)))						== NULL){		syslog(LOG_ERR, "%m: could not malloc ovalue itimerval struct");		exit(1);	}	/* load the timer */	value->it_value.tv_sec = READ_INTERVAL;	value->it_value.tv_usec = 0;	/* load the re-load field */	value->it_interval.tv_sec = READ_INTERVAL;	value->it_interval.tv_usec = 0;	while(1) {		if (!disable) {			/* start the timer */			setitimer (ITIMER_REAL, value, ovalue);			/* enable the signal */			(void) signal (SIGALRM, time_out);		}		pack_len = listen_4_rarp(fid, pack_buf, sizeof(pack_buf));		if (debug)			syslog(LOG_DEBUG, "received %d bytes; processing packet", pack_len);		res = get_ip_addr(pack_buf, send_buf, fid ); /* Get the ip mapping */		if ((res == NONRARP) && verbose) {			/* a RARP packet was not received			 * happens when filter screws up			 */			sprintf(log_msg, "Received packet from ->");			msg_len = delimit(log_msg, 0, '>') + 1;			for (i = 6; i < 12 ; i++, msg_len += 3)				sprintf(log_msg + msg_len,"%.2x:", pack_buf[32+i] & 0xFF);			continue;		}		if (res < 0) {			sprintf(log_msg, "Not in %s file->", ether_file);			/* search for the delimiter */			msg_len = delimit(log_msg, 0, '>') + 1;			for (i = 0; i < 6 ; i++,msg_len += 3)				sprintf(log_msg + msg_len , "%.2x:", pack_buf[32+i] & 0xFF);			/* log into syslog */			syslog(LOG_ERR, "%s", log_msg);			if (verbose) 				syslog(LOG_ERR, "No response sent");			continue;		}		if (verbose && res > 0 ) {			sprintf(log_msg, "Received IP address request for ->");			/* search for the delimiter */			msg_len = delimit(log_msg, 0, '>') + 1;			for (i = 0; i < 6 ; i++, msg_len += 3) 				sprintf(log_msg + msg_len,"%.2x:", pack_buf[32+i] & 0xFF);			syslog(LOG_INFO, "%s", log_msg);		}		if(verbose) {			sprintf(log_msg,"The IP address is ->");			/* search for the delimiter */			msg_len = delimit(log_msg, 0, '>') + 1;			for (i = 0; i < 4 ; i++) {				sprintf(log_msg + msg_len, "%d.", send_buf[38+i] & 0xFF);				msg_len = delimit(log_msg + msg_len, msg_len, '.') + 1;			}			syslog(LOG_INFO, "%s", log_msg);			if (debug)				syslog(LOG_DEBUG, "Going to send packet");		}		send_rarp_resp(fid, send_buf, res);		}}/********************************************************************** * Read the command line parameters. The options available * are:  *	-v		Verbose *	-f filename	The filename containing mappings * * The -v flag invokes the verbose mode of operation. The * -f option causes a file other than /etc/ethers to be * read inorder to gain knowledge of the ethernet to  * internet address mapping. Any * other option is ignored. * *********************************************************************/parse_cmdline(argc,argv)int argc;char **argv;{	int i;			/* Set up default network device */	sprintf(device, "%s", "pf0");	if (argc > 1) {	/* if more than 1 arg, check options */		for (i=1; --argc>0; i++) {			if (argv[i][0] != '-') {			/* Ethernet interface given on command line */				sprintf(device, "%s", argv[i]);				continue;			}			switch (argv[i][1]) {				case 'v':	/* turn verbose on */					verbose = 1;					break;				case 'f':	/* the file to be read */					ether_file = argv[i+1];					i++;					break;								case 'n':	/* disable the timer */					disable = 1;					break;				case 'D':	/* turn debug on */					debug = 1;					break;				default:					fprintf(stderr, "%s: unknown option, %s\n", progname, argv[i]);					syslog(LOG_ERR, "unknown option, %s\n", argv[i]);					usage();				break;			}		}  	}}/********************************************************************** * time_out is the interupt handler routine for SIGALRM * **********************************************************************/voidtime_out(){	struct stat stat_val;	(void) signal (SIGALRM, SIG_IGN);	/* First, go and stat the file in question */	if (stat(ether_file, &stat_val) < 0) {		syslog(LOG_ERR, "%m \(%s\)", ether_file);		goto enable;	}		if (time_mod < stat_val.st_mtime) {		read_mapping();		if (debug || verbose) {			syslog(LOG_INFO, "%s modified on %s",				ether_file, ctime(&stat_val.st_mtime));			syslog(LOG_INFO, "Re-read %s", ether_file);		}		time_mod = stat_val.st_mtime; /* update */	}	enable: (void) signal (SIGALRM, time_out);}usage(){	fprintf(stderr,"usage: %s [ device ] [-v] [-f filename] [-n]\n", progname);	exit(1);}/*************************************************************  *	  *	These routines are used to parse the file containing  * 	the Ethernet to Internet address mappings. The routine *	"get_ip_addr" reads the list of mappings and fills in *	appropriate IP addr. for the machine. * *	The format of the file containing mappings should be: * *	ether_addr <space or tab(s)> hostname <anything else> * *	where, * *	ether_addr is of the form : "a:b:c:d:e:f" *	and hostname is of the form "myhost" * *	NOTE: *	a, b, c, d, e and f MUST be in HEXADECIMAL * *	A "#" in the FIRST column ONLY implies a comment follows and  *	anything from that till the end of the line is ignored. *	The parser checks ONLY the first 2 fields *	of a line and reads in the data. * *	eg.  8:0:2b:2:8b:0	hishostname	#This field is not parsed *	     8:0:2b:2:8c:1 	herhostname	# comment goes here *	     8:0:2b:2:8b:0	myhostname	  ... and here	 * *	HISTORY: * *	Created by : Uttam Shikarpur Nadig *      Date: 22 February 1989 * *//****************************************************************

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?