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