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

📄 server.c

📁 关于Linux下DHCP支持IPv6的版本实现
💻 C
字号:
#include "stdhead.h"#include "lib.h"#include "advertise.h"#include "reply.h"#include "parse.h"#include "leases.h"// Global state of the serverstruct config_head **subnet_conf;		// Configuration for each subnetstruct lease_details *partial_lease;	// Partial lease data structurestruct lease_details *lease;			// Lease data structureint subnet_count;					// Number of subnetsstruct DUID *server_duid;			// Server's duidvoid quit (int signo){   exit (1);}int main (int argc, char **argv){    int listening_socket;			// Listening socket for server    int sending_socket;				// Socket to send replies to clients    struct sockaddr_in6 server_address; 	// Server socket address    struct sockaddr_in6 client_address; 	// Client socket address    char udp_message[MIN_MESSAGE_SIZE]; 	// UDP message buffer    socklen_t cl = sizeof (client_address);// Client address's length        // Local variables    int i, result, message_len;    char name[64];    fd_set testfds, readfds;    struct timeval timeout;    struct DHCP_MESSAGE *message, *sending_message;    struct OPTIONS *opt_ptr;    struct IA *ia_ptr;    struct addr_details available_addr;        // Setup a signal handler for Ctrl-C (quit)    signal (SIGINT, quit);        // Initialize listening socket    write_to_log ("Initializing listening socket ...", 1);    listening_socket = socket (PF_INET6, SOCK_DGRAM, 0);    INITIALIZE_SOCKADDR (server_address);    server_address.sin6_port = htons (AGENT_PORT);    server_address.sin6_addr = in6addr_any;    // Initialize sending socket    write_to_log ("Initializing sending socket ...", 1);    sending_socket = socket (PF_INET6, SOCK_DGRAM, 0);    // Join dhcpv6 multicast groups    write_to_log ("Joining multicast group ... ", 1);    result = mcast_join (listening_socket, "eth0", ALL_DHCP_AGENTS);    if (result == -1)    {	printf ("Server could not join ALL_DHCP_AGENTS multicast group\n");	exit (1);    }    result = mcast_join (listening_socket, "eth0", ALL_DHCP_SERVERS);    if (result == -1)    {	printf ("Server could not join ALL_DHCP_SERVERS multicast group\n");	exit (1);    }        // Bind the listening socket to the server address    write_to_log ("Binding listening socket to server address ...", 1);    result = bind (listening_socket, (struct sockaddr *) &server_address, sizeof (server_address));    if (result == -1)    {	printf ("Server could not bind to agent port\n");	exit (1);    }        // Read server configuration file    // check getopt(3) manual page for parsing command line options/*    for (i = 0; i < argc; i++)	if (!strcmp (argv[i], "--conf"))	    break;    if (i < argc)*/    write_to_log ("Reading server configuration file ...", 1);	subnet_conf = parse_and_assign (NULL, &subnet_count, 0);    #if DEBUG == 1    printf ("Server configuration file was parsed\n");#elif DEBUG == 2    print_config_list_contents (subnet_conf[0]);    print_server_duid();#endif    // Open leases files    write_to_log ("Reading leases and partial leases ...", 1);    lease = read_leases_file (LEASES_FILE);    partial_lease = read_leases_file (PARTIAL_LEASES_FILE);    // Check for expired nodes in partial lease structure    write_to_log ("Checking for and discarding expired nodes in partial leases ...", 1);    remove_expired_nodes_from_partial_lease();    // Check for expired nodes in lease structure    write_to_log ("Checking for expired nodes in leases ...", 1);    check_leases_for_expiry();    // Dump leases structures to files    write_to_log ("Dumping back leases and partial leases ...", 1);    write_leases_file (LEASES_FILE, lease);    write_leases_file (PARTIAL_LEASES_FILE, partial_lease);#if DEBUG == 1    printf ("Server about to enter select function\n");#endif    // Add the listening socket to the select function's file descriptor set    FD_ZERO (&readfds);    FD_SET (listening_socket, &readfds);    write_to_log ("\n\n\n-------------------------------------------------\n\n\n", 0);    while (1)    {	testfds = readfds;	// Set timeout to check expiry of leases	timeout.tv_sec = FIVE_MINUTES;	// Check for expired nodes in partial lease structure	write_to_log ("Checking for and discarding expired nodes in partial leases ...", 1);	remove_expired_nodes_from_partial_lease();	// Check for expired nodes in lease structure	write_to_log ("Checking for expired nodes in leases ...", 1);	check_leases_for_expiry();		// Dump leases structures to files	write_to_log ("Dumping back leases and partial leases ...", 1);	write_leases_file (LEASES_FILE, lease);	write_leases_file (PARTIAL_LEASES_FILE, partial_lease);		// Wait for activity on the socket	select (listening_socket + 1, &testfds, 0, 0, &timeout);	if (FD_ISSET (listening_socket, &testfds))	{	    // Receive message from client	    message_len = recvfrom (listening_socket, udp_message, MIN_MESSAGE_SIZE, 0, (struct sockaddr *) &client_address, &cl);	    // Change client address port for the purpose of sending back a reply	    client_address.sin6_port = htons (CLIENT_PORT);	    message = (struct DHCP_MESSAGE *) malloc (sizeof (struct DHCP_MESSAGE));	    build_linked_list (udp_message, message_len, message);	    sending_message = 0;#if DEBUG == 1	    printf ("Message type %d received from client with link - local address %s\n",	   		 message -> u_msg_type.msg_type, inet_ntop (AF_INET6, &client_address.sin6_addr.s6_addr, name, 64));#elif DEBUG == 2	    print_linked_list_contents (message);#endif	    switch (message -> u_msg_type.msg_type)	    {	      case SOLICIT :		    write_to_log ("Solicit message received from ", 1);		    write_to_log ((char *) inet_ntop (AF_INET6, &client_address.sin6_addr.s6_addr, name, 64), 0);		    		    // Check for validity of solicit message		    if (!check_message (message, SOLICIT))		    {		      write_to_log ("Solicit message received is invalid. Discarding ...", 1);			break;		    }		    write_to_log ("Solicit message received is valid.", 1);		    // Check for duplicate solicit message		    if (check_for_duplicate_packet (message))		    {		      write_to_log ("Solicit message received is duplicate. Discarding ...", 1);			break;		    }		    // Check if preferred address available or not		    if (get_pref_address (&available_addr, partial_lease, lease,		   				subnet_conf[0], client_address, get_options_ptr (message, OPTION_IAADDR)))		    {			// send advertise message			write_to_log ("Constructing advertise message with preferred IPv6 address...", 1);			sending_message = create_advertise_message (message, &available_addr);			// Add to partial lease structure			write_to_log ("Adding node to partial leases ...", 1);			add_node_to_partial_lease_structure (sending_message, &available_addr);		    }   		    // Obtain the next available address		    else if (get_available_address (&available_addr, partial_lease, 					lease, subnet_conf[0], client_address))		    {			// send advertise message			write_to_log ("Constructing advertise message with next available IPv6 address...", 1);			sending_message = create_advertise_message (message, &available_addr);			// Add to partial lease structure			write_to_log ("Adding node to partial leases ...", 1);			add_node_to_partial_lease_structure (sending_message, &available_addr);		    }		    else		    {			// send advertise message with status code option as AddrUnavailable			write_to_log ("Constructing advertise message with Address Unavailable status code...", 1);			sending_message = create_message_with_status_code (message, ADVERTISE, Success, "Address Unavailable");		    }		    break;		    		case REQUEST :		    write_to_log ("Request message received.", 1);		    // Check for validity of request message		    if (!check_message (message, REQUEST))		    {		      write_to_log ("Request message received is invalid. Discarding ...", 1);		    			break;		    }		    // Check for duplicate request message		    if (check_for_duplicate_packet (message))		    {		      write_to_log ("Request message received is duplicate. Discarding ...", 1);		      break;		    }		    // Create reply message		    write_to_log ("Constructing Reply (for Request) message ...", 1);		    sending_message = create_reply_message (message);		    // Move lease node from partial leases structure to leases structure		    write_to_log ("Moving node from partial lease to lease ...", 1);		    move_node_from_partial_to_lease (message);		    break;	    		case RENEW :		case REBIND :		    if (message -> u_msg_type.msg_type == RENEW)		      write_to_log ("Renew message received.", 1);		   else		   	write_to_log ("Rebind message received.", 1);		    // Check for validity of renew/rebind message		   if (!check_message (message, message -> u_msg_type.msg_type))		   {			if (message -> u_msg_type.msg_type == RENEW)		   	   write_to_log ("Renew message received is invalid. Discarding ...", 1);			else		   	   write_to_log ("Rebind message received is invalid. Discarding ...", 1);			break;		   }		   if (message -> u_msg_type.msg_type == RENEW)		   {			// Check for server duid			if (!check_duid (OPTION_SERVERID, message, lease))			{			    write_to_log ("Failed to find client duid in leases for Renewal of lease.", 1);			    break;			}			write_to_log ("Client duid has been matched in leases for Renewal of lease.", 1);		   }		    // Check for client binding		   if (!check_duid (OPTION_CLIENTID, message, lease))		   {			sending_message = create_dummy_reply_message (message);			opt_ptr = get_options_ptr (sending_message, OPTION_IA);			ia_ptr = (struct IA *) opt_ptr -> opt_data;			// Set IA status to indicate no record of client binding						ia_ptr -> status = NoBinding;			break;		   }		    // Check all values of the binding for exact match		    if (!check_for_match (message, lease))		    {			sending_message = create_dummy_reply_message (message);			opt_ptr = get_options_ptr (sending_message, OPTION_IA);			ia_ptr = (struct IA *) opt_ptr -> opt_data;			if (message -> u_msg_type.msg_type == RENEW)			{			   // Set IA status to indicate mismatch in binding parameters for renew message			   ia_ptr -> status = RenwNoMatch;			}			else if (message -> u_msg_type.msg_type == REBIND)			{			   // Set IA status to indicate mismatch in binding parameters for rebind message			   ia_ptr -> status = RebdNoMatch;			}			break;		    }		    // Check renewal policy (if number of renewals has exceeded the max allowable number)		    if (!check_renewal_policy (message, lease))		    {			// Valid reply message sent			sending_message = create_reply_message (message);		    }		    else		    {			// Address unavailable			sending_message = create_dummy_reply_message (message);			opt_ptr = get_options_ptr (sending_message, OPTION_IA);			ia_ptr = (struct IA *) opt_ptr -> opt_data;			// Set IA status to indicate unavailabilty of address			ia_ptr -> status = AddrUnavail;		      // Move lease node from leases structure to partial leases structure		      // Anticipating a request message		      move_node_from_lease_to_partial (message);		    }		    break;		    		case DECLINE :		case RELEASE :		    // Check for validity of message		    if (!check_message (message, message -> u_msg_type.msg_type))			break;		    // Check for duplicate decline/release message		    if (check_for_duplicate_packet (message))		      break;		    // Create appropriate reply message 		    if (message -> u_msg_type.msg_type == DECLINE)			sending_message = create_reply_message_for_decline (message);		    else if (message -> u_msg_type.msg_type == RELEASE)		      sending_message = create_reply_message_for_release (message);		    // Delete node from leases structure		    del_node_from_lease (message, lease);		    break;	    		default :#if DEBUG == 2		    printf ("\nInvalid message type received\n");#endif		    sending_message = 0;		    break;	    }	    	    if (sending_message)	    {#if DEBUG == 2	      print_linked_list_contents (sending_message);#endif	      message_len = store_in_buffer (sending_message, udp_message);	      sendto (sending_socket, udp_message, message_len, 0, (struct sockaddr *) &client_address, cl);		// Free message linked list   		free_message_mem (sending_message);	   }	   // Free message linked list   	   free_message_mem (message);	}    }}

⌨️ 快捷键说明

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