/* ************************************************************* RWhois Software Copyright (c) 1994 Scott Williamson and Mark Kosters Copyright (c) 1996-1998 Network Solutions, Inc. See the file LICENSE for conditions of use and distribution. **************************************************************** */ #include "rwhois.h" #include "rwhois_internal.h" dl_list_type * recursive_query_rwhois(rw_query_args_struct *query_args, rw_server_struct *server, char *spec_version, char *imp_version, rw_recurse_mode_enum recurse_mode, dl_list_type *referral_group_list, dl_list_type *record_list, rw_response_struct *response) { rw_referral_group_struct *cur_ref_group; dl_list_type *cur_ref_list; rw_referral_struct *cur_ref; dl_list_type *local_referral_group_list; rw_referral_group_struct *global_ext_ref_group; rw_referral_group_struct *local_ext_ref_group; rw_server_struct new_server; char info_buffer[MAXBUFFER + 1]; int alloc_referral_group_list = FALSE; int not_done; int not_done_referrals; /* these must be true, or you are using the function incorrectly */ assert(query_args); assert(response); assert(server); if (NOT_STR_EXISTS(server->host) || NOT_STR_EXISTS(query_args->query)) { rwhois_set_response(response, RW_ERROR, "Missing critical information for the rwhois query"); return NULL; } memset(info_buffer, 0, sizeof(info_buffer)); /* connect to the server */ if (rwhois_connect(server, spec_version, imp_version, info_buffer, sizeof(info_buffer), response) < RW_OK) { /* return the info block as a record */ if (STR_EXISTS(info_buffer)) { rw_record_struct *record; record = (rw_record_struct *) CALLOC(1, sizeof(*record)); record->text = STRDUP(info_buffer); rwhois_set_record_source_by_server(record, server); if (!record_list) { record_list = dl_list_create(destroy_rw_record_struct); } dl_list_append(record_list, record); return record_list; } return NULL; } /* set the limit */ if (query_args->limit_changed_flag && (rwhois_limit(server, query_args->limit, response) != RW_OK)) { return NULL; } /* issue the query */ if (rwhois_query(server, query_args->query, response) != RW_OK) { return NULL; } if (!record_list) { record_list = dl_list_create(destroy_rw_record_struct); } if (! referral_group_list) { referral_group_list = dl_list_create(destroy_rw_referral_group_struct); alloc_referral_group_list = TRUE; } /* get all of the results */ rwhois_fetch_all_records(server, record_list, response); if (response->status <= 0) { if (alloc_referral_group_list) dl_list_destroy(referral_group_list); return NULL; } /* we are now done with this server connection */ rwhois_close(server); /* get all of the referrals */ referral_group_list = rwhois_get_all_referrals(record_list, referral_group_list); /* if we aren't recursing, or there are no referrals, we are done now */ if (recurse_mode == RW_NO_RECURSE || !referral_group_list) { if (alloc_referral_group_list) dl_list_destroy(referral_group_list); return record_list; } /* otherwise, recurse, trying referrals serially in each group */ not_done = dl_list_first(referral_group_list); while (not_done) { cur_ref_group = (rw_referral_group_struct *) dl_list_value(referral_group_list); /* skip if bad or the external group */ if (!cur_ref_group || NOT_STR_EXISTS(cur_ref_group->group_name) || STR_EQ(cur_ref_group->group_name, EXT_REFERRALS_GROUP_NAME)) { not_done = dl_list_next(referral_group_list); continue; } cur_ref_list = cur_ref_group->referrals; not_done_referrals = dl_list_first(cur_ref_list); while (not_done_referrals) { cur_ref = (rw_referral_struct *) dl_list_value(cur_ref_list); /* skip if bad */ if (!cur_ref || NOT_STR_EXISTS(cur_ref->host)) { not_done_referrals = dl_list_next(cur_ref_list); continue; } local_referral_group_list = dl_list_create(destroy_rw_referral_group_struct); /* point new query to the referral server */ new_server.host = cur_ref->host; new_server.port = cur_ref->port; new_server.debug_level = server->debug_level; /* follow the referral */ record_list = recursive_query_rwhois(query_args, &new_server, spec_version, imp_version, recurse_mode, local_referral_group_list, record_list, response); if (response->status != RW_OK) { dl_list_destroy(local_referral_group_list); not_done_referrals = dl_list_next(cur_ref_list); continue; } /* we successfully followed the referral, so the new records have already been appended. All of the resultant rwhois referrals should have already been chased, so all we need to do is collect the external referrals */ local_ext_ref_group = rwhois_find_referral_group(local_referral_group_list, EXT_REFERRALS_GROUP_NAME); global_ext_ref_group = rwhois_find_referral_group(referral_group_list, EXT_REFERRALS_GROUP_NAME); if (local_ext_ref_group && global_ext_ref_group) { rwhois_merge_referral_groups(global_ext_ref_group, local_ext_ref_group); } dl_list_destroy(local_referral_group_list); break; } /* while not_done_referrals */ /* whether or not we successfully followed referrals in that group, we are done with it, so we will remove it from the group list */ if (dl_list_at_tail(referral_group_list)) { not_done = FALSE; } else { not_done = TRUE; } dl_list_delete(referral_group_list); } return record_list; }