⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clilib.c

📁 关于Linux下DHCP支持IPv6的版本实现
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "stdhead.h"#include "clilib.h"#include "parse.h"void write_to_log (char * str, int time_flag){    extern int event_log_fd;    time_t curr_time;    int time_length;    char *str_curr_time;        if (time_flag)    {	curr_time = time (&curr_time);	str_curr_time = ctime (&curr_time);	write (event_log_fd, str_curr_time, strlen(str_curr_time));	write (event_log_fd, "\t", 1);    }    if ((write (event_log_fd, str, strlen (str))) == -1)	printf ("Failed to log event.\n");    if (time_flag)	write (event_log_fd, "\n", 1);}// Build message linked-list from character buffervoid build_linked_list (char *m, int len, struct DHCP_MESSAGE *dhcp_message){    int index = 0, i;    struct OPTIONS *opt;        dhcp_message -> u_msg_type.buffer[0] = m[index++];    for (i = 2; i >= 0; i--)	dhcp_message -> u_trans_id.buffer[i] = m[index++];	    dhcp_message -> u_trans_id.buffer[3] = 0;    opt = (struct OPTIONS *) malloc (sizeof (struct OPTIONS));    read_option (m, index, len, opt);    dhcp_message -> opt = opt;}void print_linked_list_contents (struct DHCP_MESSAGE *dhcp_message){    struct OPTIONS *q;    struct DUID *d;    struct DUID1 *d1;    struct DUID2 *d2;    struct DUID3 *d3;    struct IA *ia;    struct IA_ADDRESS *ia_addr;    struct PREFERENCE *preference;    struct STATUS_CODE *sc_ptr;    int i;    char name[64];        printf ("Message type = %d\n", dhcp_message -> u_msg_type.msg_type);    printf ("Transaction ID = %d\n\n", dhcp_message -> u_trans_id.trans_id);    q = dhcp_message -> opt;    if (!q)    {	printf ("No options defined!\n");	return;    }	    do    {	switch (q -> u_opt_code.opt_code)	{	    case OPTION_CLIENTID :	    case OPTION_SERVERID :		//printf ("Option type = %d\n", q -> u_opt_code.opt_code);		//printf ("DUID length = %d\n", q -> u_opt_len.opt_len);		d = q -> opt_data;		//printf ("DUID type = %d\n", d -> u_duid_type.duid_type);				if (d -> u_duid_type.duid_type == 1)		{		    d1 = d -> duid_type;		    		    //printf ("Time = %d\n", d1 -> u_time.time);		    //printf ("Hardware type = %d\nHardware address = ", d1 -> u_haddr_type.haddr_type);		    for (i = 0; i < 6; i++)		    {			printf ("%x", d1 -> link_layer_address[i]);			if (i != 5)			    printf (":");		    }		    //printf ("\n\n");		}		else if (d -> u_duid_type.duid_type == 2)		{		    d2 = d -> duid_type;		    		    //printf ("Identifier length = %d\nIdentifier = ", d2 -> u_identifier_length.identifier_length);		    //for (i = 0; i < d2 -> u_identifier_length.identifier_length; i++)		//	printf ("%d", d2 -> identifier[i]);	//	    printf ("\nDomain name = ");		    //for (i = 0; i < d2 -> domain_name_len; i++)		//	printf ("%c", d2 -> domain_name[i]);		}		else if (d -> u_duid_type.duid_type == 3)		{		    d3 = d -> duid_type;		    		//    printf ("Hardware type = %d\nHardware address = ", d3 -> u_haddr_type.haddr_type);		    for (i = 0; i < 6; i++)		    {			printf ("%x", d3 -> link_layer_address[i]);			if (i != 5)			    printf (":");		    }		    printf ("\n\n");		}    				q = d -> opt;		break;			    case OPTION_IA :	//	printf ("Option type = IA option\n");	//	printf ("option length = %d\n", q -> u_opt_len.opt_len);		ia = q -> opt_data;	//	printf ("IAID = %x\n", ia -> u_iaid.iaid);	//	printf ("T1 = %d\n", ia -> u_t1.t1);	//	printf ("T2 = %d\n", ia -> u_t2.t2);	//	printf ("Status code for IA = %d\n\n", ia -> status);		q = ia -> opt;		break;			    case OPTION_IAADDR :	//	printf ("Option type = IA address option\n");	//	printf ("option length = %d\n", q -> u_opt_len.opt_len);		ia_addr = q -> opt_data;	//	printf ("Temporary address bit = %d\n", ia_addr -> t_bit);	//	printf ("Address status = %d\n", ia_addr -> addr_status);	//	printf ("Prefix length of the address = %d\n", ia_addr -> prefix_length);		printf ("IPv6 Address = %s\n", inet_ntop (AF_INET6, ia_addr -> addr, name, 64));		printf ("Preferred lifetime = %d\n" , ia_addr -> u_pref_lifetime.pref_lifetime);		printf ("Valid lifetime = %d\n", ia_addr -> u_valid_lifetime.valid_lifetime);		q = ia_addr -> opt;		break;			    case OPTION_PREFERENCE :	//	printf ("Option type = Preference Option\n");	//	printf ("Option length = %d\n", q -> u_opt_len.opt_len);		preference = q -> opt_data;			//	printf ("Preference value = %d\n\n", preference -> preference_value);		q = preference -> opt;		break;	    	    case OPTION_STATUS_CODE :	//	printf ("Option type = Status code\n");	//	printf("Option length = %d\n",q->u_opt_len.opt_len);		sc_ptr = q->opt_data;			//	printf( "Status code = %d\nStatus message =",sc_ptr->u_status_code.status_code);                //for(i=0; i < q->u_opt_len.opt_len -2; i++) 			//	   printf("%c", sc_ptr->message[i]);	//	printf("\n\n");		q=sc_ptr->opt;		break;		    	    default :		printf ("Invalid option type\n\n");		q = 0;		return;	}    }    while (q);}// This function returns the generated random number in between -0.1 and +0.1float generate_rand (){    time_t t1;    // call srand with the current time as the seed    srand (time (&t1));    // Return a random vakue between -0.1 and +0.1    return ((float)((rand()%200)-100)/1000.0);}// This function returns a random number in between the defined constants.int calculate_initial_delay (){    time_t t1;    int random;    // call srand with the current time as the seed    srand (time (&t1));        // Calculate and return a random number between MAX_SOL_DELAY and MIN_SOL_DELAY    random = rand () % (MAX_SOL_DELAY);    if (random < (MIN_SOL_DELAY))	random += (MIN_SOL_DELAY);    return random;}/* This function calculates the timeout upon the expiry of which theretransmission is to be done. */float calculate_retransmission_timeout (float RTprev, float mrt){    float rt = ((2.0 * RTprev) + (generate_rand () * RTprev));    if (mrt != 0)	while (rt > mrt)	    rt = mrt + generate_rand () * mrt;    return rt;}/* This function checks whether that particular option exists in the linked list. It returns 1on success and 0 on failure. */int check_for_option (int option, struct DHCP_MESSAGE *dhcp_msg_ptr){    struct OPTIONS * opt;    struct DUID *duid_ptr;    struct IA *ia_ptr;    struct IA_ADDRESS * iaaddr_ptr;    struct STATUS_CODE * status_ptr;    struct PREFERENCE * preference;        // Move to the first option node    opt= dhcp_msg_ptr->opt;        // Until there are no moer options in the message    while ( opt !=0)    {	// If the required option is found then return 1	if (opt->u_opt_code.opt_code == option)	    return 1;		// Depending on the option code    	switch(opt->u_opt_code.opt_code)	{	    case OPTION_CLIENTID :	    case OPTION_SERVERID :		// Move to the next node		duid_ptr = (struct DUID *) opt -> opt_data;		opt = duid_ptr->opt;		break;			    case OPTION_IA : 		// Move to the next node		ia_ptr= (struct IA *) opt -> opt_data;		opt= ia_ptr->opt;		break;			    case OPTION_IAADDR :		// Move to the next node	        iaaddr_ptr=(struct IA_ADDRESS *) opt -> opt_data;		opt=iaaddr_ptr->opt;		break;			    case OPTION_STATUS_CODE :		// Move to the next node	        status_ptr=(struct STATUS_CODE *) opt -> opt_data;		opt=status_ptr->opt;		break;			    case OPTION_PREFERENCE :		// Move to the next node		preference = (struct PREFERENCE *) opt -> opt_data;		opt = preference -> opt;		break;			    default :		opt = 0;		break;	}	    }    return 0;}   int check_for_status (struct DHCP_MESSAGE *dhcp_msg_ptr){    struct OPTIONS *options_ptr;    struct DUID *duid_ptr;    struct IA *ia_ptr;    struct IA_ADDRESS * iaaddr_ptr;    struct STATUS_CODE * status_ptr;    struct PREFERENCE * preference_ptr;        // Move to the first option node    options_ptr= dhcp_msg_ptr->opt;        // Until there are no moer options in the message    while (options_ptr !=0)    {	// Depending on the option code    	switch(options_ptr -> u_opt_code.opt_code)	{	    case OPTION_CLIENTID :	    case OPTION_SERVERID :		// Move to the next node		duid_ptr = (struct DUID *) options_ptr -> opt_data;		options_ptr = duid_ptr->opt;		break;			    case OPTION_IA : 		// Move to the next node		ia_ptr= (struct IA *) options_ptr -> opt_data;		options_ptr = ia_ptr->opt;		break;			    case OPTION_IAADDR :		// Move to the next node	        iaaddr_ptr=(struct IA_ADDRESS *) options_ptr -> opt_data;		options_ptr = iaaddr_ptr->opt;		break;			    case OPTION_STATUS_CODE :		// Move to the next node	        status_ptr=(struct STATUS_CODE *) options_ptr -> opt_data;		return (status_ptr -> u_status_code.status_code);			    case OPTION_PREFERENCE :		// Move to the next node		preference_ptr = (struct PREFERENCE *) options_ptr -> opt_data;		options_ptr = preference_ptr -> opt;		break;	    default :		options_ptr = 0;		break;	}	    }    return -1;}/* This function checks the validity of the message being passed to it.It return 1 on success and 0 on failure */int check_message (struct DHCP_MESSAGE *dhcp_message_ptr, int recv_type, int sent_type){    struct OPTIONS *options_ptr;    extern int g_trans_id;    int status;    // Check whether the received message is of the right type    if (dhcp_message_ptr->u_msg_type.msg_type != recv_type)	return 0;    // Checks whether the transaction id of the received message has the same    // transaction is as that sent to same server before a reply is obtained    // from the server    if (dhcp_message_ptr->u_trans_id.trans_id != g_trans_id)       return 0;	           switch (dhcp_message_ptr->u_msg_type.msg_type)    {	case ADVERTISE :	    if ((status = check_for_status (dhcp_message_ptr)) != -1)		if (status != Success)		    return 0;	    if (!check_for_option (OPTION_SERVERID, dhcp_message_ptr))		return 0;	    if (!check_for_option (OPTION_IA, dhcp_message_ptr))		return 0;	    if (!check_for_option (OPTION_IAADDR, dhcp_message_ptr))		return 0;	    break;	    	case REPLY :	    if ((status = check_reply_message (dhcp_message_ptr, sent_type)) == 0)		return 0;	    break;    }    return 1;}// This function waits for a response from the server after the initial transmission// of a message has been done. The function struct DHCP_MESSAGE ** wait_until_response (int sfd, int cfd, float irt, float mrt, int mrc, int sent_type, int recv_type, char *buff, int size, int *msg_count){    char name [64];    // Stores the client state    extern int g_state;    // Server and Client socket structures    extern struct sockaddr_in6 sa, ca;        extern struct DHCP_MESSAGE * reply_for_request;    // count keeps track of message retransmissions    // valid is used for checking message validity    int count = 0, n, message_valid;    // variable for storing message received from the server    struct DHCP_MESSAGE **msg_arr_ptr = 0, **p; // pointer to the message array    // Calculate the initial retransmission time    float rt = calculate_retransmission_timeout (SOL_IRT, mrt);    // Used for detecting activity on a socket    fd_set readfds, testfds;    // Used to set the retransmission timeout    struct timeval timeout;    // Used to receive the response from the server    char reply[MIN_MESSAGE_SIZE];    // pointer to a DHCP_MESSAGE    struct DHCP_MESSAGE *dhcp_message_ptr;        u_int32_t renewal_timer, rebind_timer, valid_lifetime_timer;    time_t start, end;    // Set the length of the server and client socket structures    socklen_t sl = sizeof (sa);    socklen_t cl = sizeof (ca);    // Set the server response message count to zero        *msg_count = 0;    // Clear the file descriptor set variables    FD_ZERO (&readfds);    // Set the client socket in the file descriptor set    FD_SET (cfd, &readfds);    // If Maximum retransmission count is zero then set mrc to infinity.    if (!mrc)	mrc = INFINITY;    // Set the retransmission time    timeout.tv_sec = 0;    timeout.tv_usec = rt * MEGA;	    if (g_state == RENEWING || g_state == REBINDING)    {	get_timers (reply_for_request, &renewal_timer, &rebind_timer, &valid_lifetime_timer);	time (&start);    }        while (count < mrc)    {	// Initialize the file descriptor set        testfds = readfds;	   	// Start the retransmission timeout and wait for activity on the scokets	write_to_log ("Waiting for server response", 1);        select (cfd+1, &testfds, 0, 0, &timeout);	   	// If it is time to retrasmit           if (timeout.tv_sec == 0 && timeout.tv_usec == 0)        {	    if (g_state == RENEWING)	    {		time (&end);		if (end-start >= rebind_timer-renewal_timer)		    return 0;	    }	    else if (g_state == REBINDING)	    {		time (&end);		if (end-start >= valid_lifetime_timer-rebind_timer)		    return 0;	    }			    // If there are no replies from the server then break out and return a null pointer	    write_to_log ("Wait for server response timed out.", 1);	    if (*msg_count > 0)	    {		write_to_log ("\tResponse messages have been received. Exiting retransmission scheme.", 0);		break;	    }	    write_to_log ("\tNo response messages have been received. Continuing in the retransmission scheme...", 0);	    // Increment the retransmission count	    count++;	    printf ("Sending %d %d time\n", sent_type, count);	    // Retransmit the client message	    write_to_log ("Retransmitting message...", 1);	    sendto (sfd, buff, size, 0, (struct sockaddr *) &sa, sl);	    // Calculate the new Retransmission timeout	    rt = calculate_retransmission_timeout (rt, mrt);	    // Set the new retransmission timeout	    timeout.tv_sec = 0;	    timeout.tv_usec = rt * MEGA;	    printf ("The new retransmission timeout is %f\n", rt);	}	// If activity is detected on the client receiving scoket	else if (FD_ISSET (cfd, &testfds))	{	    // Receive the server message into the reply buffer	    n = recvfrom (cfd, reply, MIN_MESSAGE_SIZE, 0, (struct sockaddr *) &ca, &cl);	    write_to_log ("Server response received from ", 1);	    write_to_log ((char *) inet_ntop (AF_INET6, &ca.sin6_addr, name, 64), 0);	    // Allocate memory for a DHCP_MESSAGE	    dhcp_message_ptr = (struct DHCP_MESSAGE *) malloc (sizeof (struct DHCP_MESSAGE));	    // Build the linked list for the server response message	    build_linked_list (reply, n, dhcp_message_ptr);	    // Check for validity of the server response message	    write_to_log ("Checking message validity ....", 1);	    message_valid = check_message (dhcp_message_ptr, recv_type, sent_type);	    // Announce arrival of server response message	    printf ("%d message received.\n", recv_type);	    // Check for message validity            if (message_valid)   		    {		// Allocate an array of pointers for the dhcp message.		(*msg_count)++;

⌨️ 快捷键说明

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