#include "querydb.h" static char const rcsid[] = "$Id: asquery.c,v 1.4 2004/03/10 18:04:33 wilhelm Exp $"; int compress_aspath(char *input, char *output) { /* compress IP level path of ASes to a path in AS space - replace sequence of duplicates by one - replace a sequence where after a 0 (no info available) previous AS reoccurs by one entry (no looping in AS space) return number of AS hops in compressed path */ char *current; char previous[32]; char lastseen[32]; int len = 0; output[0] = '\0'; /* start with zero length paths */ lastseen[0] = '\0'; previous[0] = '\0'; /* fprintf(stderr, "In: %s ", input); */ if ((current = strtok(input, " ")) == NULL) { /* single hop or zero length AS path */ strcpy(output, input); return(1); } /* normal case, start by copying first valid AS to output */ if (strcmp(current, "0") != 0) { len++; strcpy(output, current); strcat(output, " "); } strcpy(previous, current); while ((current = strtok(NULL, " ")) != NULL) { if (strcmp(current, previous) != 0) { /* different from previous hop */ if (strcmp(previous, "0") != 0) { if (strcmp(current, "0") != 0) { /* valid, add to aspath */ strcat(output, current); strcat(output, " "); strcpy(lastseen, current); len++; } /* if current eq 0 we wait with output until we have info from the next hop */ } else { /* couldn't find AS for previous IPhop(s) if AS differs from lastseen, ouptut 0 for unknown AShop plus current AS. If they are the same, unresolved IP must be in AS, can't have AS loops! */ if (strcmp(current, lastseen) != 0) { /* current differs from last valid unknown hop in between */ strcat(output, "0 "); strcat(output, current); strcat(output, " "); len += 2; /* 0 + current */ strcpy(lastseen, current); } } strcpy(previous, current); } } if (strcmp(previous,"0") == 0) { /* last AShop unknown. Note that this has to be outside above loop, to capture the case where several hops at the end don't have AS */ strcat(output, "0 "); len++; } /* fprintf(stderr, " Out: %s\n ", output); */ return(len); } int match_aspath_by_time(MYSQL *mysql, char *srcbox, char *dstbox, time_t t_start, time_t t_end, struct querystruct *data) { char query [1024]; MYSQL_RES *result; MYSQL_ROW row; struct querystruct *current; struct querystruct *index, *next; struct querystruct *limit_record; unsigned int src; unsigned int dst; unsigned int counter; GHashTable *ranges; unsigned int *pz; unsigned int flag; data = NULL; counter = 0; flag = 0; limit_record = malloc(sizeof(struct querystruct)); limit_record->tend = 0; ranges = g_hash_table_new (g_str_hash,g_str_equal); get_ranges_by_boxname (ranges, PATHBOXES); pz = g_hash_table_lookup (ranges,srcbox); if (pz == NULL) { fprintf (stderr,"Box %s does not exist.\n",srcbox); return (0); }; src = *(int *)pz; pz = g_hash_table_lookup (ranges,dstbox); if (pz == NULL) { fprintf (stderr,"Box %s does not exist.\n",dstbox); return (0); }; dst = *(int *)pz; /*Query the DB*/ sprintf (query,"SELECT Records.aspathid, Records.tstart, Records.tend, Records.numrec, ASpaths.len, ASpaths.path FROM Records, ASpaths WHERE Records.src=%u AND Records.dst=%u AND Records.aspathid=ASpaths.id AND ((Records.tstart BETWEEN %u AND %u) OR (%u BETWEEN Records.tstart AND Records.tend+%u)) ORDER BY Records.tstart", src,dst,(unsigned int)(t_start),(unsigned int)(t_end),(unsigned int)(t_start),TIME_LIMIT); // printf ("%s\n",query); // tt01.ripe.net tt47.ripe.net 960900000 961000000 if (mysql_query(mysql,query)) { fprintf(stderr, "MySQL query error: %s\n", mysql_error(mysql)); return (0); }; if (!(result = mysql_use_result(mysql))) { fprintf(stderr, "MySQL Result error: %s\n", mysql_error(mysql)); mysql_free_result(result); return (0); }; /* Set return params - add new element to Buffers */ while ((row = mysql_fetch_row(result))) { if ((atoi(row[1]) < (unsigned int)(t_start)) && ((atoi(row[2]) + TIME_LIMIT) > (unsigned int)(t_start)) && (atoi(row[2]) > (unsigned int)(limit_record->tend))) { limit_record->aspathid = atoi(row[0]); limit_record->tstart = atoi(row[1]); limit_record->tend = atoi(row[2]); limit_record->numrec = atoi(row[3]); limit_record->next = NULL; limit_record->ashops = compress_aspath(row[5], limit_record->aspath); continue; }; if ((atoi(row[1]) < (unsigned int)(t_start)) || (atoi(row[1]) > (unsigned int)(t_end))) { continue; }; current = malloc(sizeof(struct querystruct)); current->aspathid = atoi(row[0]); current->tstart = atoi(row[1]); current->tend = atoi(row[2]); current->numrec = atoi(row[3]); current->next = NULL; current->ashops = compress_aspath(row[5], current->aspath); if (data == NULL) { data = current; } else { index = data; while (index->next != NULL) { index = index->next; }; index->next = current; }; if (++counter > 10 * MAX_QUERY_LINES) /* we compress to ASpaths, be generous on query lines */ { flag = 1; break; }; }; /* limit_record was not used ? */ if (limit_record->tend == 0) { free(limit_record); } else { /* Append limit_record at the beginning of data */ limit_record->next = data; data = limit_record; }; index = data; if (index != NULL) { /* merge records with identical compressed ASpath */ while ((next = index->next) != NULL) { if ( (strcmp(index->aspath, next->aspath) == 0) && (next->tstart < index->tend + TIME_LIMIT) ) { /* combine the two records */ index->numrec += next->numrec; index->tend = next->tend; index->next = next->next; free(next); } else { index = index->next; } } } index = data; while (index != NULL) { printf ("%s %s %d %d %d %d %d %s\n",srcbox,dstbox,index->tstart,index->tend,index->aspathid,index->ashops,index->numrec,index->aspath); index = index->next; }; if (flag) { printf (".%u\n",MAX_QUERY_LINES); } else { printf (".\n"); }; mysql_free_result(result); return (1); }; int main (int argc, char *argv[]) { MYSQL mysql; struct querystruct *data; char *src, *dst, *host; unsigned int tstart, tend; int ip6flag = 0; data = NULL; /* Parse arguments */ if ((argc < 5) || (argc > 7)) { fprintf (stderr,"Usage: %s [-6] [MySQL host]\n",argv[0]); exit (1); }; if (strcmp(argv[1], "-6") == 0) { ip6flag = 1; argv++; argc--; } src = argv[1]; dst = argv[2]; tstart = atoi(argv[3]); tend = atoi(argv[4]); if (argc == 6) { /* we should check if the argument makes sense as a hostname */ /* future version ... */ host = argv[5]; } else { host = MYSQL_HOST; } /* process request */ if (!ip6flag) { open_user_connection (&mysql, host); } else { open_user_connection_ip6 (&mysql, host); } if (!match_aspath_by_time(&mysql,src,dst,tstart,tend,data)) { fprintf (stderr,"match_aspath_by_time: Cannot send query.\n"); exit (1); }; mysql_close(&mysql); return (0); };