📄 clilib.c
字号:
} break; case OPTION_PREFERENCE : preference_ptr = (struct PREFERENCE *) malloc (sizeof (struct PREFERENCE)); opt -> opt_data = preference_ptr; preference_ptr -> preference_value = m[index++]; next_opt = (struct OPTIONS *) malloc (sizeof (struct OPTIONS)); if (index == len) preference_ptr -> opt = 0; else { read_option (m, index, len, next_opt); preference_ptr -> opt = next_opt; } break; default :#if DEBUG == 3 printf ("Invalid option type\n");#endif opt = 0; index = len; return; }}/* This function deallocates the memory space consumed by the dhcp message. It returns void.*/void free_message_mem (struct DHCP_MESSAGE *dhcp_message){ struct OPTIONS *options_ptr; struct DUID *duid_ptr; struct DUID1 *duid1_ptr; struct DUID2 *duid2_ptr; struct DUID3 *duid3_ptr; struct IA *ia_ptr; struct IA_ADDRESS *ia_addr_ptr; struct PREFERENCE *preference; struct STATUS_CODE *sc_ptr; options_ptr = dhcp_message->opt; free (dhcp_message); while (options_ptr) // loop until the end of the linked list. { switch (options_ptr->u_opt_code.opt_code) // determines the option code. { case OPTION_CLIENTID : case OPTION_SERVERID : duid_ptr = (struct DUID *) options_ptr->opt_data; free (options_ptr); switch (duid_ptr -> u_duid_type.duid_type) // determines the duid type. { case 1 : duid1_ptr = (struct DUID1 *) duid_ptr->duid_type; free (duid1_ptr -> link_layer_address); free (duid1_ptr); break; case 2 : duid2_ptr = (struct DUID2 *) duid_ptr->duid_type; free (duid2_ptr->identifier); free (duid2_ptr->domain_name); free (duid2_ptr); break; case 3 : duid3_ptr = (struct DUID3 *) duid_ptr->duid_type; free (duid3_ptr->link_layer_address); free (duid3_ptr); break; } options_ptr = duid_ptr->opt; free (duid_ptr); break; case OPTION_IA : ia_ptr = (struct IA *) options_ptr->opt_data; free (options_ptr); options_ptr = ia_ptr->opt; free (ia_ptr); break; case OPTION_IAADDR : ia_addr_ptr = (struct IA_ADDRESS *) options_ptr->opt_data; free (options_ptr); options_ptr = ia_addr_ptr->opt; free (ia_addr_ptr); break; case OPTION_PREFERENCE : preference = (struct PREFERENCE *) options_ptr -> opt_data; free (options_ptr); options_ptr = preference -> opt; free (preference); break; case OPTION_STATUS_CODE : sc_ptr = (struct STATUS_CODE *) options_ptr -> opt_data; free (options_ptr); options_ptr = sc_ptr -> opt; free (sc_ptr->message); free (sc_ptr); break; default : options_ptr = 0; break; } }}// This function returns the preference value of the message being sent as// parameter. If there is no PREFERENCE option then 0 is returnedu_int8_t get_preference_value (struct DHCP_MESSAGE *message){ struct OPTIONS * opt; struct DUID *duid_ptr; struct IA *ia_ptr; struct IA_ADDRESS * iaaddr_ptr; struct STATUS_CODE * status_ptr; struct PREFERENCE * preference; if (!message) return 0; // Move to the first option of the message opt = message->opt; // Until no options are left while (opt) { switch(opt->u_opt_code.opt_code) { case OPTION_CLIENTID : case OPTION_SERVERID : // Move onto the next node duid_ptr = (struct DUID *) opt -> opt_data; opt = duid_ptr -> opt; break; case OPTION_IA : // Move onto the next node ia_ptr= (struct IA *) opt -> opt_data; opt = ia_ptr->opt; break; case OPTION_IAADDR : // Move onto the next node iaaddr_ptr=(struct IA_ADDRESS *) opt -> opt_data; opt = iaaddr_ptr->opt; break; case OPTION_STATUS_CODE : // Move onto the next node status_ptr=(struct STATUS_CODE *) opt -> opt_data; opt = status_ptr->opt; break; case OPTION_PREFERENCE : // Return the preference value preference = (struct PREFERENCE *) opt -> opt_data; return preference->preference_value; default : opt = 0; break; } } return 0;}// This function returns the preferred IPv6 address of the message being sent as// parameter. If there is no IAADDR option then 0 is returnedu_int8_t * get_pref_ipv6_address (struct DHCP_MESSAGE *message){ struct OPTIONS * opt; struct DUID *duid_ptr; struct IA *ia_ptr; struct IA_ADDRESS * iaaddr_ptr; struct STATUS_CODE * status_ptr; struct PREFERENCE * preference; if (!message) return 0; // Move to the first option of the message opt = message->opt; // Until no options are left while (opt) { switch(opt->u_opt_code.opt_code) { case OPTION_CLIENTID : case OPTION_SERVERID : // Move onto the next node duid_ptr = (struct DUID *) opt -> opt_data; opt = duid_ptr -> opt; break; case OPTION_IA : // Move onto the next node ia_ptr= (struct IA *) opt -> opt_data; opt = ia_ptr->opt; break; case OPTION_IAADDR : // Return the preferred address iaaddr_ptr=(struct IA_ADDRESS *) opt -> opt_data; return iaaddr_ptr -> addr; //opt = iaaddr_ptr->opt; break; case OPTION_STATUS_CODE : // Move onto the next node status_ptr=(struct STATUS_CODE *) opt -> opt_data; opt = status_ptr->opt; break; case OPTION_PREFERENCE : // Move onto the next node preference = (struct PREFERENCE *) opt -> opt_data; opt = preference->opt; break; default : opt = 0; break; } } return 0;}// This function returns the prefereed lifetime of the message that has been sent// to it as parameter.It the message does not have a preferred lifetime then // the function returns 0.*/u_int32_t get_pref_lifetime (struct DHCP_MESSAGE *message){ struct OPTIONS * opt; struct DUID *duid_ptr; struct IA *ia_ptr; struct IA_ADDRESS * iaaddr_ptr; struct STATUS_CODE * status_ptr; struct PREFERENCE * preference_ptr; if (!message) return 0; // Move to the first option of the message opt = message->opt; // Until no options are left while (opt) { switch(opt->u_opt_code.opt_code) { case OPTION_CLIENTID : case OPTION_SERVERID : // Move onto the next node duid_ptr = (struct DUID *) opt -> opt_data; opt = duid_ptr -> opt; break; case OPTION_IA : // Move onto the next node ia_ptr= (struct IA *) opt -> opt_data; opt = ia_ptr -> opt; break; case OPTION_IAADDR : // Return the preferred lifetime iaaddr_ptr = (struct IA_ADDRESS *) opt->opt_data; return iaaddr_ptr -> u_pref_lifetime.pref_lifetime; break; case OPTION_PREFERENCE : // Move onto the next node preference_ptr = (struct PREFERENCE *) opt -> opt_data; opt = preference_ptr -> opt; break; default : opt = 0; break; } } return 0;} struct DHCP_MESSAGE * select_server (struct DHCP_MESSAGE ** server_reply, int msg_count, char * interface_name){ struct DHCP_MESSAGE **p; // POinters to the list of messages struct DHCP_MESSAGE *best = 0, *curr = 0; // Pointer to Interface Details struct interface * interface_details; // Pointer to IPv6 addresses u_int8_t *best_pref_ipv6_addr = 0, *curr_pref_ipv6_addr = 0; // Variables to stores the best and current nodes Prefereed lifetimes u_int32_t best_pref_lifetime = 0, curr_pref_lifetime = 0; // Message index in the array of pointers to messages int index = 0; // Best and current node values of nodes u_int8_t max_preference_value = 0, curr_preference_value; // Get the Interface details for a particular interface interface_details = get_interface_details (interface_name); // Set current pointer to the first mesage curr = *server_reply; // Until all messages have been checked or best message has been found while (index < msg_count) { // get the preference value for the current node curr_preference_value = get_preference_value (curr); // If the current preference value is equal to 255 return current pointer // as the best message if (curr_preference_value == MAX_PREFERENCE_VALUE) return curr; // If the current preference value is better than the previously best // preference value, assign the current message as the best message // and the current preference value as the maximum preference value else if (curr_preference_value > max_preference_value) { best = curr; max_preference_value = curr_preference_value; } // If the current preference value if equal to the previously best // preference value then ccompare the two message and decide which is // the best else if (curr_preference_value == max_preference_value) { if (!best) { best = curr; // Increment the message index index++; // Move to the next message p = server_reply + index; curr = *p; continue; } // get the preferered IPv6 address for the best node best_pref_ipv6_addr = get_pref_ipv6_address (best); // If the best messages preferred IPv6 address is not equal to // the preferred IPv6 address in the interface configuartion if (interface_details->pref_ipv6_addr && memcmp (best_pref_ipv6_addr, interface_details->pref_ipv6_addr->s6_addr, 16)) { // Get the prefereed IPv6 address of the current node curr_pref_ipv6_addr = get_pref_ipv6_address (curr); // If the preferred IPv6 address of the current node is equal // to the preferred IPv6 address of the particular interface, // assign the current message as the best message if (interface_details->pref_ipv6_addr && !memcmp (curr_pref_ipv6_addr, interface_details->pref_ipv6_addr->s6_addr, 16)) best = curr; else { // Get the preferred lifetime for the best node best_pref_lifetime = get_pref_lifetime (best); // Get the prefereed lifetime for the current node curr_pref_lifetime = get_pref_lifetime (curr); // if the best nodes preferred lifetime is less than the // current nodes lifetime then assgin the best node as the // current node if (best_pref_lifetime < curr_pref_lifetime ) best = curr; } } } // Increment the message index index++; // Move to the next message p = server_reply + index; curr = *p; } // Return the pointer to the best message return best;}struct DHCP_MESSAGE ** purge_message (struct DHCP_MESSAGE ** server_reply, struct DHCP_MESSAGE * target, int * msg_count){ struct DHCP_MESSAGE * curr; int i, index = 0; curr = *server_reply; while (index < *msg_count) { if (curr == target) { free_message_mem (curr); for (i = index; i < (*msg_count) - 1; i++) server_reply [i] = server_reply [i+1]; (*msg_count)--; break; } index++; } server_reply = (struct DHCP_MESSAGE ** ) realloc (server_reply, sizeof (struct DHCP_MESSAGE *) * (*msg_count)); return server_reply;}struct OPTIONS * get_options_ptr (struct DHCP_MESSAGE * dhcp_msg_ptr, int option){ struct OPTIONS * options_ptr = dhcp_msg_ptr -> opt; struct DUID * duid_ptr; struct IA * ia_ptr; struct IA_ADDRESS * iaaddr_ptr; struct PREFERENCE * preference_ptr; struct STATUS_CODE * status_ptr; while (options_ptr) { if (options_ptr -> u_opt_code.opt_code == option) return options_ptr; switch (options_ptr -> u_opt_code.opt_code) { case OPTION_CLIENTID : case OPTION_SERVERID : duid_ptr = (struct DUID *) options_ptr -> opt_data; options_ptr = duid_ptr -> opt; break; case OPTION_IA : ia_ptr = (struct IA *) options_ptr -> opt_data; options_ptr = ia_ptr -> opt; break; case OPTION_IAADDR : iaaddr_ptr = (struct IA_ADDRESS *) options_ptr -> opt_data; options_ptr = iaaddr_ptr -> opt; break; case OPTION_PREFERENCE : preference_ptr = (struct PREFERENCE *) options_ptr -> opt_data; options_ptr = preference_ptr -> opt; break; case OPTION_STATUS_CODE : status_ptr = (struct STATUS_CODE *) options_ptr -> opt_data; options_ptr = status_ptr -> opt; break; default : options_ptr = 0; break; } } return 0;}int check_address_in_use (struct OPTIONS * options_ptr){ int icmp_fd, size, n, hlen, icmp6len, msg_count = 0; char buff[1500], reply[1500]; struct sockaddr_in6 sa; char name[64]; struct icmp6_hdr * icmp6, * icmp6_reply; struct ip6_hdr * ip6; socklen_t len; struct IA_ADDRESS * iaaddr_ptr; struct timeval timeout;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -