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 + -
显示快捷键?