rarpd.c

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

C
1,357
字号
 *	read_mapping reads the file "file" and creates a * mapping of Ethernet to Internet address in the mapper structure. * ***************************************************************/mapper *enet_list = NULL; 	/* structure that contains the mappings */voidread_mapping(){	FILE *fileid;		/* The data base file */	char buff[MAX_LINE];	/* Buffer to read a line */	int line_count;		/* # of lines in the file */	int parse_result;	/* The result of the parse */	int i;	mapper *current;	/* The current positon in the list */	mapper *previous;	/* The one but last positon in the list */	mapper *tmp;		/* a temporary pointer */	char log_msg[MSG_SIZE];	/* for logging in messages */	int msg_len;		/* the current length */	int mapsiz=0; 		/* Size of the mapper struct */	if (debug)		syslog(LOG_DEBUG, "Entered read_mapping");	/* ignore SIGHUP for now */	signal(SIGHUP, SIG_IGN);	/* Ok, time to open the database for reading */	fileid = fopen(ether_file, "r");	if (fileid == NULL) {		syslog(LOG_ERR, "%m\(%s\)", ether_file);		exit(1);	}	if (debug)		syslog(LOG_DEBUG, "Opened %s file", ether_file);	/* 	 * First read in the total number of lines.	 */	for (line_count = 1; fgets(buff, sizeof(buff), fileid) != NULL; ++line_count)		; /* nop */	rewind(fileid);	if (debug)		syslog(LOG_DEBUG, "%d lines in file", line_count);	/* Allocate space for the table. If this is the second time this	 * is being done deallocate the memory already allocated	 */	 tmp = current = enet_list;	 if (enet_list != NULL) { /* free memory already allocated */		do {			free(current);			current = tmp->next;			tmp = current;		} while (current != NULL);		if (debug)			syslog(LOG_DEBUG, "Freed up memory");	 }	/* Now allocate memory as required */	if (( current = enet_list = (mapper *)malloc(sizeof(mapper) * line_count)) == NULL) {		syslog(LOG_ERR, "%m: could not malloc mapper structure");		exit(1);	}	current->next = NULL; 	line_count = 0;  /* initialize */	valid_count = 0; /* initialize */	/* Read in the data from the file */	while (fgets (buff, sizeof (buff), fileid) != NULL) {		line_count++;		if ((parse_result = parse_line(buff, current)) < 0) {			syslog(LOG_ERR, "error in %s at line %d",					ether_file, line_count);			continue;	/* Read the next line */		}		if (parse_result > 0) {			caddr_t tmp2 = 0;	/* temporary */			valid_count++;	/* the line read in was valid */			if (debug) {				syslog(LOG_DEBUG,"Parse result is : %d", parse_result);				sprintf(log_msg, "mapper->ether : ");				/* find the de-limiter */				for (msg_len = 0; log_msg[msg_len] != ':';msg_len++)					; /* nop */				for (i = 0; i < 6; i++, msg_len++)					sprintf(log_msg + msg_len + i +1,							"%.2x", current->ether[i]);				syslog(LOG_DEBUG, "%s", log_msg);						sprintf(log_msg, "mapper->ip : ");						/* find the de-limiter */				msg_len = delimit(log_msg, 0, ':') + 1;						for (i = 0; i < 4; i++) {					sprintf(log_msg + msg_len, "%d.", current->ip[i] & 0xFF);					msg_len = delimit(log_msg + msg_len, msg_len, '.') + 1;				}				syslog(LOG_DEBUG, "%s", log_msg);				/* lastly, the host name */				sprintf(log_msg, "mapper->hostname : %s",								current->hostname);				/* put it into the syslog */				syslog(LOG_DEBUG, "%s", log_msg);			}			mapsiz = sizeof(mapper);			tmp2 = (caddr_t) current;			tmp2 += mapsiz;			current->next = (mapper*)tmp2;			current = current->next;			current->next = NULL;		}	}	/* First, check for the number of valid lines read in */	if (valid_count == 0){ /* Either the file was empty or none			        *  of the entries were correct			        */		fprintf(stderr, "%s : Warning : no valid entries in %s\n",					progname, ether_file);		syslog(LOG_ERR, "no valid entries in %s", ether_file);	} else { /* atleast one valid entry was found */		previous = (current - sizeof(mapper));/*Allocated one too many*/		previous->next = NULL;	}	rewind(fileid);		/* rewind */	close(fileid);		/* close the file */	/* reset SIGHUP signal */	signal(SIGHUP, read_mapping);}/**************************************************************** * *	Parses an input line read from the RARP database. The * expected format of the entry is : *	a:b:c:d:e:f <sp or tab(s)> hostname *	Anything after a "#" till the end of that line is ignored. * ****************************************************************/parse_line(line, pointer)char *line;	 /* The entry read from the RARP database */mapper *pointer; /* the mapper structure that needs to filled up */{	 int count;			/* The numb. of fields scanned */	 char hostname[MAXHOSTLEN];	/* The host name */	 u_char enet[20];		/* The ether net address */	 if ((line[0] == '#'))		return(0);	/* It is a comment line */	 if ((count = sscanf(line, "%s%s", enet, hostname)) < 2)		return(0); /* ignore the line as a comment as it has			    * less than 2 fields			    */	 /* time to do some conversions */	 if (conv_enet(enet, pointer) < 0 ) /* convert the ethernet address */	 	return(-1);	 if (conv_ip(hostname, pointer) < 0 ) /* convert the ip address */	 	return(-1);	 return(1);}/**************************************************************** *	 *	conv_enet scans the the string to see if it of the type * a:b:c:d:e:f. If so, the ":" from the string are removed and * and stored into the list pointed to by "pointer." * ***************************************************************/ conv_enet(enet, pointer) u_char *enet; mapper *pointer;{	unsigned int numb[6];		/* for temp. storage */	int i;	if (debug)		syslog(LOG_DEBUG, "Entered conv_enet ...");	if (sscanf(enet, "%x%*c%x%*c%x%*c%x%*c%x%*c%x", &numb[0], &numb[1],			&numb[2], &numb[3], &numb[4], &numb[5] ) != 6) {		syslog(LOG_ERR, "syntax error while parsing Ethernet addr");		return(-1);	/* Six fields were not present */	}	if ((pointer->ether = (u_char *)malloc (sizeof (u_char) * 7)) == NULL){		syslog(LOG_ERR, "Cannot allocate memory in conv_enet.");		exit(1);	}	for (i = 0; i < 6; i++) 		pointer->ether[i] = numb[i] & 0xFF;	pointer->ether[6] = '\0'; /* null terminate */	if (debug)		syslog(LOG_DEBUG,"Finished conv_ether successfully ...");	return(0);	/* ALL is clear on the conv_enet front */} /******************************************************************  *  conv_ip address takes the hostname given and converts that  * to the ip format and stores it in the ip field.  ******************************************************************/conv_ip (hostname, pointer)char *hostname;mapper *pointer;{	struct hostent *host_info;		/* get the "hostname" characteristics */		host_info = gethostbyname(hostname);	if (host_info == NULL) {		syslog(LOG_ERR, "Host not found: %s", hostname);		fprintf(stderr, "%s: unknown host: %s\n", progname, hostname);		return(-1); /* not a host name */	}	/* Allocate memory */	if (( pointer->ip = (u_char *)malloc (sizeof (u_char) * 4)) == NULL ) {		syslog(LOG_ERR, "malloc failed in conv_ip");		exit(1);	}	bcopy (host_info->h_addr, pointer->ip, 4);	bcopy (hostname, pointer->hostname, strlen(hostname));	if (debug)		syslog(LOG_DEBUG, "Finished conv_ip successfully ... ");	return(0);}/*************************************************************** *	 *	This routine does a linear search on the list pointed * to by enet_list and finds the appropriate internet address * for the given ethernet hardware address. In case the address * is not found an error is returned * * *	A RARP message consists of the following bytes of * data. The format being: * *	 ------------------------------------------------------------- *	|destination addr(6) | source addr (6) | Packet type-RARP(2)  | *	 ------------------------------------------------------------- *	|addr. space(2)| protocol(2) | hardware addr length(1) 	      | *	 ------------------------------------------------------------- *	|logical addr length(1) | RARP type(1) | src hardware addr(n) | *	 ------------------------------------------------------------- *	|src IP addr (m) | target hardware addr (n)		      | *	 ------------------------------------------------------------- *	|	target IP addr (m) - THE DESIRED IP ADDRESS	      | *	 ------------------------------------------------------------- * *	Where 'n' and 'm' are the values in the hardware addr. length * field and logical addr. length field respectively. * *	A valid assumption made is that ethernet address are 6 bytes * long and all IP addresses are 4 bytes long. * **********************************************************************/get_ip_addr(recv_pack, send_pack, fid)u_char *recv_pack;		/* The packet received */u_char *send_pack;		/* The packet to be sent */int fid;			/* The device file descriptor */{	mapper *list_ptr;	u_char ether_buff[7];	struct endevp devparams;	/* to fetch the device params. */	char lhostname[MAXHOSTLEN];	/* The name of the local host */	struct hostent *lhost;		/* local host characteristics */	int i,result;	char log_msg[MSG_SIZE];	/* the syslog message buffer */	int msg_len = 0;		/* the pointer to current location */	if (debug) {	/* Print the entire packet received */		syslog(LOG_DEBUG, "THE CONTENTS OF THE PACKET RECEIVED ARE: ");		sprintf(log_msg,"Destination(6) : "); 		/* search for the delimiter */	 	msg_len = delimit(log_msg, msg_len, ':') + 1;		for (i = 0; i < 6; i++,msg_len += 3)			sprintf(log_msg + msg_len, "%.2x:", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg , "Source(6) : "); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, ':') + 1;		for (i = 6; i < 12; i++,msg_len += 3)			sprintf(log_msg + msg_len, "%.2x:", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg , "Packet type(2): 0x"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, 'x') + 1;		for (i = 12; i < 14; i++, msg_len += 2)			sprintf(log_msg + msg_len , "%.2x", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		/* check if the packet was of RARP type		 * if not don't print the rest		 */		if (recv_pack[12] != 0x80 || recv_pack[13] != 0x35)			return(NONRARP); /* received a NON-RARP packet */		sprintf(log_msg , "Hardware addr. space type(2): 0x"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, 'x') + 1;		for (i = 14; i < 16; i++, msg_len += 2)			sprintf(log_msg + msg_len, "%.2x", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "Protocol addr. space type(2): 0x"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, 'x') + 1;		for (i = 16; i < 18; i++,msg_len += 2)			sprintf(log_msg + msg_len, "%.2x", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "Hardware addr. length(1): 0x"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, 'x');		sprintf(log_msg + msg_len + 1, "%.2x", recv_pack[18] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "IP addr. length(1): 0x"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, 'x') + 1;		sprintf(log_msg + msg_len, "%.2x", recv_pack[19] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "RARP type(2): 0x");		/* search for the delimiter */		msg_len = delimit(log_msg, 0, 'x') + 1;		for (i = 20; i < 22; i++,msg_len += 2)			sprintf(log_msg + msg_len, "%.2x", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "Source hardware addr.(6):"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, ':') + 1;		for (i = 22; i < 28; i++,msg_len += 3)			sprintf(log_msg + msg_len, "%.2x:", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "Source IP addr.(4): "); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, ':') + 1;		for (i = 28; i < 32; i++, msg_len += 2)		sprintf(log_msg + msg_len, "%d.", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "Target hardware addr.(6):"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, ':') + 1;		for (i = 32; i < 38; i++, msg_len += 3)			sprintf(log_msg + msg_len, "%.2x:", recv_pack[i] & 0xFF); 		syslog(LOG_DEBUG, "%s", log_msg);		sprintf(log_msg, "Target IP addr.(4):"); 		/* search for the delimiter */		msg_len = delimit(log_msg, 0, ':') + 1;		for (i = 38; i < 42; i++, msg_len += 2)		sprintf(log_msg + msg_len, "%d.", recv_pack[i] & 0xFF); 		/* Put this information into the syslog */		syslog(LOG_DEBUG, "%s", log_msg);	}	/* check if the packet was of RARP type	 * if not don't print the rest 	 * This was tracked to not clearing the buffer	 * before using the filter. (Left here for reference.)	 */	if (recv_pack[12] != 0x80 || recv_pack[13] != 0x35)		return(-1);		/* get the ether_net address which needs to be mapped */	ether_buff[0] = recv_pack[32];		ether_buff[1] = recv_pack[33];		ether_buff[2] = recv_pack[34];		ether_buff[3] = recv_pack[35];		ether_buff[4] = recv_pack[36];		ether_buff[5] = recv_pack[37];		ether_buff[6] = '\0';		/* NULL terminate */	/* Time to string compare and fetch out the right logical address 	 * But, first find out if we have any valid entries by checking	 * the variable valid count.	 */	if (valid_count == 0)		return (-1);	list_ptr = enet_list;	while(1) {	/* not an infinite loop; returns */		if ((result = bcmp(ether_buff, list_ptr->ether, 6)) == 0) {			/* We have the mapping; */			/* Build the packet to be sent */			/* The destination address */ 			send_pack[0] = recv_pack[6];			send_pack[1] = recv_pack[7];			send_pack[2] = recv_pack[8];			send_pack[3] = recv_pack[9];			send_pack[4] = recv_pack[10];			send_pack[5] = recv_pack[11];			/* The Source address; added by the driver */			send_pack[6] = 0x00;			send_pack[7] = 0x00;			send_pack[8] = 0x00;			send_pack[9] = 0x00;			send_pack[10] = 0x00;			send_pack[11] = 0x00;			/* The Ethernet packet type - RARP */			send_pack[12] = recv_pack[12];			send_pack[13] = recv_pack[13];					/* The Hardware addr. space - ar$hrd */			send_pack[14] = recv_pack[14];			send_pack[15] = recv_pack[15];			/* The logical address space - ar$pro */			send_pack[16] = recv_pack[16];			send_pack[17] = recv_pack[17];			/* The Hardware address length - ar$hln */			send_pack[18] = recv_pack[18];			/* The logical address length - ar$pln */			send_pack[19] = recv_pack[19];			/* RARP reply type - ar$op; 4 */			send_pack[20] = 0x00;			send_pack[21] = 0x04;

⌨️ 快捷键说明

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