static int ovs_global_post(struct netns_entry *root) { char *str; int fd, len; int err; str = construct_query(); len = strlen(str); fd = connect_ovs(); if (fd < 0) return 0; if (write(fd, str, len) < len) { close(fd); return 0; } free(str); str = read_all(fd); br_list = parse(str); free(str); close(fd); if (!br_list) return 0; if ((err = link_ifaces(root))) return err; return 0; }
char* resolve(char* potentials, char* current, char* querying) { if(!current) { // if there's no current server for some reason, pick one randomly int i = randStart(potentials); int j = 0; char server[256]; memset(&server, 0, sizeof(server)); while(potentials[i] != '\n') { server[j] = potentials[i]; i++, j++; } server[j] = '\0'; // null terminate the server string current = server; } /* Initial debug statement */ if(debug) { printf("How about nameserver %s?\n", current); int count = ncounter(potentials); printf("\nResolving %s using server %s out of %d.\n", querying, current, count); } // Create a socket int sock = socket(AF_INET, SOCK_DGRAM, 0); if(sock < 0) { perror("Creating socket failed: "); exit(1); } //int optval = 1; // set socket to time out on recv //setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&optval, sizeof optval); struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout)); /* Send the query */ in_addr_t nameserver_addr = inet_addr(current); // construct the query message uint8_t query[1500]; int query_len=construct_query(query,1500,querying); struct sockaddr_in addr; // internet socket address data structure addr.sin_family = AF_INET; addr.sin_port = htons(53); // port 53 for DNS addr.sin_addr.s_addr = nameserver_addr; // destination address (any local for now) int send_count = sendto(sock, query, query_len, 0, (struct sockaddr*)&addr,sizeof(addr)); if(send_count<0) { perror("Send failed"); exit(1); } // await the response uint8_t answerbuf[1500]; int rec_count = recv(sock,answerbuf,1500,0); if (rec_count < 1) { // this is not properly resolving a time out; just blocks forever if((errno == EAGAIN) || (errno == EWOULDBLOCK)) return resolve(root_servers, NULL, querying); // if we timed out, call the function again w/ a NULL server, pick random. } // parse the response to get our answer struct dns_hdr *ans_hdr=(struct dns_hdr*)answerbuf; uint8_t *answer_ptr = answerbuf + sizeof(struct dns_hdr); // now answer_ptr points at the first question. int question_count = ntohs(ans_hdr->q_count); int answer_count = ntohs(ans_hdr->a_count); int auth_count = ntohs(ans_hdr->auth_count); int other_count = ntohs(ans_hdr->other_count); int total = answer_count + auth_count + other_count; if(debug) { printf("Got %d+%d+%d=%d resource records total.\n", answer_count, auth_count, other_count, total); } // skip past all questions int q; for(q=0;q<question_count;q++) { char string_name[255]; memset(string_name,0,255); int size=from_dns_style(answerbuf,answer_ptr,string_name); answer_ptr+=size; answer_ptr+=4; //2 for type, 2 for class } // ANSWER AND AUTHORITY SECTIONS int a; char *nsrecords[512]; int nsCount = 0; for(a=0;a<answer_count+auth_count;a++) { // first the name this answer is referring to char string_name[255]; int dnsnamelen=from_dns_style(answerbuf,answer_ptr,string_name); answer_ptr += dnsnamelen; // then fixed part of the RR record struct dns_rr* rr = (struct dns_rr*)answer_ptr; answer_ptr+=sizeof(struct dns_rr); // A record in answer section - we're done, return the name if(htons(rr->type)==RECTYPE_A) { if(debug) printf("The name %s resolves to IP addr: %s\n", string_name, inet_ntoa(*((struct in_addr *)answer_ptr))); return inet_ntoa(*((struct in_addr *)answer_ptr)); } // CNAME record else if(htons(rr->type)==RECTYPE_CNAME) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The name %s is also known as %s.\n", string_name, ns_string); querying = ns_string; /* If we just queried with the basic nameserver, populate the list w/ root servers and reset the nameserver_flag so we don't do this again */ if(nameserver_flag) { potentials = root_servers; nameserver_flag = 0; } // pick a random server to query next, from the list int i = randStart(potentials); int j = 0; char server[256]; memset(&server, 0, sizeof(server)); while(potentials[i] != '\n') { server[j] = potentials[i]; i++, j++; } server[j] = '\0'; return resolve(potentials, server, querying); // recursively continue to query! } // NS record else if(htons(rr->type)==RECTYPE_NS) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The name %s can be resolved by NS: %s\n", string_name, ns_string); // Put these in an array to use if there's nothing else. nsrecords[nsCount] = malloc(25*sizeof(char)); nsrecords[nsCount] = strdup(ns_string); nsCount++; } // PTR record (reverse lookup, ip to domain name -- if we were looking for this, also done) else if(htons(rr->type)==RECTYPE_PTR) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The host at %s is also known as %s.\n", string_name, ns_string); if(reverse_flag) return strdup(ns_string); // if this was a reverse lookup, we're done! otherwise whatever } // SOA record (ignore) else if(htons(rr->type)==RECTYPE_SOA) { if(debug) printf("Ignoring SOA record\n"); } // AAAA record (ignore) else if(htons(rr->type)==RECTYPE_AAAA) { if(debug) printf("Ignoring IPv6 record\n"); } else { if(debug) printf("got unknown record type %hu\n",htons(rr->type)); return NULL; } answer_ptr+=htons(rr->datalen); } // if nothing in additional section, preemptively check the NS records if(other_count == 0) { char *nsips = malloc(BUFLEN); int counter = 0; int k; if(nsCount==0) return NULL; for(k=0; k<nsCount; k++) { char *tempStr = resolve(root_servers, NULL, nsrecords[k]); int i=0; while(tempStr[i] != '\0') { nsips[counter] = tempStr[i]; counter++, i++; } nsips[counter] = '\n'; // newline termination counter++; } return resolve(nsips, NULL, querying); // now try to resolve the query using these IPs } // ADDITIONAL SECTION (if there wasn't an answer or a PTR) char *returnArray = malloc(BUFLEN); for(a=answer_count+auth_count;a<answer_count+auth_count+other_count;a++){ char string_name[255]; int dnsnamelen=from_dns_style(answerbuf,answer_ptr,string_name); answer_ptr += dnsnamelen; // then fixed part of the RR record struct dns_rr* rr = (struct dns_rr*)answer_ptr; answer_ptr+=sizeof(struct dns_rr); // take these and query these next create an array of ptrs to push into the resolve query if(htons(rr->type)==RECTYPE_A) { char ipaddr[256]; memset(&ipaddr, 0, sizeof(ipaddr)); char *temp = inet_ntoa(*((struct in_addr *)answer_ptr)); int i = 0; while(temp[i] != '\0') { ipaddr[i] = temp [i]; i++; } ipaddr[i] = '\n'; strcat(returnArray, ipaddr); if(debug) printf("The name %s resolves to IP addr: %s\n", string_name, inet_ntoa(*((struct in_addr *)answer_ptr))); } // NS record else if(htons(rr->type)==RECTYPE_NS) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The name %s can be resolved by NS: %s\n", string_name, ns_string); } // CNAME record else if(htons(rr->type)==RECTYPE_CNAME) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The name %s is also known as %s.\n", string_name, ns_string); } // PTR record (reverse lookup, ip to domain name -- if we were looking for this, also done) else if(htons(rr->type)==RECTYPE_PTR) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The host at %s is also known as %s.\n", string_name, ns_string); } // SOA record (ignore) else if(htons(rr->type)==RECTYPE_SOA) { if(debug) printf("Ignoring SOA record\n"); } // AAAA record (ignore) else if(htons(rr->type)==RECTYPE_AAAA) { if(debug) printf("Ignoring IPv6 record\n"); } else { if(debug) printf("got unknown record type %hu\n",htons(rr->type)); } answer_ptr+=htons(rr->datalen); } // Iterate through all possible servers. int k; int i = 0; for(k=0; k < ncounter(potentials); k++) { int j = 0; char server[256]; memset(&server, 0, sizeof(server)); while(potentials[i] != '\n') { server[j] = potentials[i]; i++, j++; } server[j] = '\0'; i++; // so it starts at the next character char *retStr; if((retStr = resolve(returnArray, server, querying)) != NULL) // if we got a response, give it! return retStr; } shutdown(sock,SHUT_RDWR); close(sock); return NULL; // if nothing else worked }
char *resolve_address(char *hostname, nameserver **nameservers, int ns_count) { // The hostname we'll be looking up in any recursive call char *newhostname = hostname; // Stuff we'll use after getting ahold of a nameserver uint8_t answerbuf[1500]; // Build a socket with a timeout int sock = socket(AF_INET, SOCK_DGRAM, 0); if(sock < 0) { perror("Creating socket failed: "); exit(1); } struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); // Loop to contact a nameserver int chosen_server = rand()%ns_count; // The nameserver we'll be using to do the query nameserver *active_ns; // Number of times left to try contacting a nameserver int attempts_left = MAX_ATTEMPTS * ns_count; while ( attempts_left-- > 0 ) { // Try a nameserver active_ns = nameservers[chosen_server]; in_addr_t nameserver_addr=inet_addr(active_ns->server_addr); // construct the query message uint8_t query[1500]; int query_len=construct_query(query,1500,hostname); struct sockaddr_in addr; // internet socket address data structure addr.sin_family = AF_INET; addr.sin_port = htons(53); // port 53 for DNS addr.sin_addr.s_addr = nameserver_addr; // destination address (any local for now) if (debug) { printf("How about nameserver %s?\n", active_ns->server_addr); } int send_count = sendto(sock, query, query_len, 0, (struct sockaddr*)&addr,sizeof(addr)); if(send_count<0) { perror("Send failed"); exit(1); } // Await the response int rec_count = recv(sock,answerbuf,1500,0); // Check for errors while receiving if ((rec_count < 1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) { if (debug) { printf("Timed out while waiting for nameserver %s.\n", active_ns->server_addr); } // Try choosing another nameserver randomly chosen_server = rand()%ns_count; } else { break; } } if ( attempts_left <= 0 ) { fprintf(stderr, "Could not contact any nameservers.\n"); exit(1); } if (debug) { printf("Resolving %s using server %s out of %d\n", hostname, active_ns->server_addr, ns_count); } // parse the response to get our answer struct dns_hdr *ans_hdr=(struct dns_hdr*)answerbuf; uint8_t *answer_ptr = answerbuf + sizeof(struct dns_hdr); // now answer_ptr points at the first question. int question_count = ntohs(ans_hdr->q_count); int answer_count = ntohs(ans_hdr->a_count); int auth_count = ntohs(ans_hdr->auth_count); int other_count = ntohs(ans_hdr->other_count); if (debug) { int resource_count = question_count + answer_count + auth_count + other_count; printf("%d questions, %d answers, %d authoritative records, and %d others = %d resource records total\n", question_count, answer_count, auth_count, other_count, resource_count); } // skip past all questions int q; for(q=0;q<question_count;q++) { char string_name[255]; memset(string_name,0,255); int size=from_dns_style(answerbuf,answer_ptr,string_name); answer_ptr+=size; answer_ptr+=4; //2 for type, 2 for class } int a; int got_answer=0; // now answer_ptr points at the first answer. loop through // all answers in all sections nameserver *new_nameservers[100]; int ns_index = 0; for(a=0;a<answer_count+auth_count+other_count;a++) { // first the name this answer is referring to char string_name[255]; int dnsnamelen=from_dns_style(answerbuf,answer_ptr,string_name); answer_ptr += dnsnamelen; // then fixed part of the RR record struct dns_rr* rr = (struct dns_rr*)answer_ptr; answer_ptr+=sizeof(struct dns_rr); const uint8_t RECTYPE_A=1; const uint8_t RECTYPE_NS=2; const uint8_t RECTYPE_CNAME=5; const uint8_t RECTYPE_SOA=6; const uint8_t RECTYPE_PTR=12; const uint8_t RECTYPE_AAAA=28; if(htons(rr->type)==RECTYPE_A) { char *ip_addr = inet_ntoa(*((struct in_addr *)answer_ptr)); if (debug) printf("The name %s resolves to IP addr: %s\n", string_name, ip_addr); got_answer=1; // Are we done? if ( !strcasecmp(string_name, newhostname) ) { delete_nameservers(new_nameservers, ns_index); if (newhostname != hostname) free(newhostname); return strdup(ip_addr); } // Try to match some IPs up with symbolic hostnames for nameservers int i; for ( i=0; i<ns_index; i++ ) { nameserver *new_ns = new_nameservers[i]; if ( !strcasecmp(string_name,new_ns->server) ) { new_ns->server_addr = strdup(ip_addr); break; } } } // NS record else if(htons(rr->type)==RECTYPE_NS) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) printf("The name %s can be resolved by NS: %s\n", string_name, ns_string); // Keep maximum number of nameservers if ( ns_index < MAX_NAMESERVERS ) { nameserver *new_ns = nameserver_create(ns_string, NULL); new_nameservers[ns_index++] = new_ns; } got_answer=1; } // CNAME record else if(htons(rr->type)==RECTYPE_CNAME) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if(debug) { printf("The name %s is also known as %s.\n", string_name, ns_string); } if ( !strcasecmp(string_name,newhostname) ) { if ( newhostname != hostname ) free(newhostname); newhostname = strdup(ns_string); } got_answer=1; } // PTR record else if(htons(rr->type)==RECTYPE_PTR) { char ns_string[255]; int ns_len=from_dns_style(answerbuf,answer_ptr,ns_string); if (debug) { printf("The host at %s is also known as %s.\n", string_name, ns_string); } got_answer=1; delete_nameservers(new_nameservers, ns_index); if (newhostname != hostname) free(newhostname); return strdup(ns_string); } // SOA record else if(htons(rr->type)==RECTYPE_SOA) { if(debug) { printf("Ignoring SOA record\n"); } } // AAAA record else if(htons(rr->type)==RECTYPE_AAAA) { if(debug) { printf("Ignoring IPv6 record\n"); } } else { if(debug) { printf("got unknown record type %hu\n",htons(rr->type)); } } answer_ptr+=htons(rr->datalen); } shutdown(sock,SHUT_RDWR); close(sock); if ( ns_index > 0 ) { int i; for ( i=0; i<ns_index; i++ ) { nameserver *ns = new_nameservers[i]; // Make sure we have the IP address of this nameserver if ( !ns->server_addr ) { if (debug) { printf("Need to resolve IP address of nameserver %s\n", ns->server); } ns->server_addr = resolve_address(ns->server, root_servers, num_root_servers); if ( !ns->server_addr && debug ) { printf("Failed to retrieve IP address for %s.\n", ns->server); } } } if (debug) { printf("now resolving the hostname %s...\n", newhostname); } // Free old nameservers array char *result = resolve_address(newhostname, new_nameservers, ns_index); if (newhostname != hostname) free(newhostname); delete_nameservers(new_nameservers, ns_index); return result; } if (newhostname != hostname) free(newhostname); delete_nameservers(new_nameservers, ns_index); return NULL; }