try to load the included C file into glimmer, and it crashes. I've tried to send mail to the glimmer author, but the mail hung in my queue unable to resolve the domain name. How-To-Repeat: try to load the following as netmaster.c: /*--------------------------------------------------- commands: HELO USERID PW identifies who is making requests USERID is the PostgreSQL username for the user using the socket PW is the PostgreSQL password for the user using the socket. This command can ONLY be issued as the first command of a session. If you need to change USERID's, you need to QUIT and start a new session. responses: 200 HELO OK %s\r\n the %s substitution is the username from the HELO command. 500 Can't get DB connection (most likely invalid ID/PW) '%s'\r\n The PostgreSQL database rejected the connection. The %s substitution is the database error message. NOTE: this error can be generated at ANY time, if the database is cycled/crashed/etc. The wording may be slightly different, but means the same thing. -------------------------------------------- CUSTID REFERENCE="xxxxxxxxx" asks if DB knows about a customer, returns unique ID REFERENCE field is 256 bytes of CHARACTER VARYING data. responses: 250 CUSTID ID %s %s\r\n the first %s substitution is the unique ID for the REFERENCE number xxxxxx. the 2nd %s substitution is (new) or (existing). 500 no arguments given\r\n obvious error 500 CUSTID command not followed by REFERENCE=\r\n obvious error 590 DB ERROR: Report %s-%d-%d to networking\r\n The database returned an error. The subsitution is a code to correlate to syslog information on the host where netmaster runs. will *ALWAYS* be followed by The 595 message is at the moment #ifdef'd out 595 Details Follow and a dump of the query, with \r\n.\r\n after it. there is *NO* HTML escaping in these messages, HOWEVER they *ARE* written to syslog on the host where netmaster is running. -------------------------------------------- CUSTINFO id NAME="xxxxxxxxxxxxxxxxxxx" adds/changes HUMAN name to xxxxxxxxxxxxxxx for unique id name is a 256 byte character varying field. responses: 200 OK custinfo %s\r\n", means we've updated the table. The %s substitution is the id as supplied by you. 500 no arguments given\r\n Obvious error message 500 Invalid Character in id field, 0-9 ONLY are accepted\r\n Obvious error message NB: 590/595 as described for CUSTID is ALWAYS possible. -------------------------------------------- CUSTINFO id ADDR="xxxxxxxxxxxxxxxxxxx" adds/changes address to xxxxxxxxxxxxxxx for unique id address is a 256 byte character varying field. responses: 200 OK custinfo %s\r\n", means we've updated the table. The %s substitution is the id as supplied by you. 500 no arguments given\r\n Obvious error message 500 Invalid Character in id field, 0-9 ONLY are accepted\r\n Obvious error message NB: 590/595 as described for CUSTID is ALWAYS possible. -------------------------------------------- CUSTINFO id ADDR2="xxxxxxxxxxxxxxxxxxx" addr2 is a 256 byte character varying field. CUSTINFO id CITY="xxxxxxxxxxxxxxxxxxx" city is a 256 byte character varying field. CUSTINFO id STATE="xxxxxxxxxxxxxxxxxxx" State is a 256 byte character varying field. CUSTINFO id ZIP="xxxxxxxxxxxxxxxxxxx" Zip is a 256 byte character varying field. CUSTINFO id TEL="xxxxxxxxxxxxxxxxxxx" Zip is a 256 byte character varying field. CUSTINFO id COMPANY="xxxxxxxxxxxxxxxxxxx" Company is a 256 byte character varying field. CUSTINFO id COMMENT="xxxxxxxxxxxxxxxxxxx" comment is a 256 byte character varying field. CUSTINFO id EMAIL="xxxxxxxxxxxxxxxxxxx" email is a 256 byte character varying field. CUSTINFO id CORPORATE="Y|N|T|F" corporate is a 1 byte character field. T or Y means it *IS* a corporate account. F or N means it *IS NOT* a corporate account. same idea as previous 2. NOTE: all KEYWORD="value" options may be spec'd in same command. -------------------------------------------- PROVASSIGN product id ASN SIZE ROUTERIP finds a block of SIZE in ASN for ROUTERIP and product and returns it, provisonally assigning it to CUSTID ID. responses: 250 PROVASSIGN OK %s %s %s %s\r\n where the first %s substitution is the netblock in CIDR notation. the 2nd %s substitution is the base address of the netblock. the 3rd %s substitution is the mask length (/nn, without the /) the 4th %s substitution is the netmask in dotted-decimal form (255.255.255.0 for example for a /24). 500 CUSTID NOT PROVIDED\r\n 500 ASN NOT PROVIDED\r\n 500 SIZE NOT PROVIDED\r\n 500 ROUTERIP NOT PROVIDED\r\n the above 4 messages are obvious. 500 Impossible size /%d\r\n for whatever reason, we can't deliver the %d substitution size. 500 NO SUCH CUSTOMER ID (%s)\r\n Obvious. The %s substitution is the id as supplied. 500 IA doesn't issue /31's\r\n obvious 500 IMPOSSIBLE NETBLOCK SIZE! /0\r\n obvious 500 can't split to more than /17\r\n You asked for something in length, and there was none available and the split logic doesn't handle shorter than /17's. 500 Invalid Routerip: %s\r\n The RouterIP isn't a valid IP address. 500 No such product 400 No Netblock available for request. Contact Networking.\r\n 590 inet_aton on '%s' failed!!!!!\r\n", the system returned a netblock that the system inet_aton function failed. SHOULD NOT OCCUR. REPORT THIS TO THE AUTHOR or current CODE owner. THIS IS A BUG! NB: 590/595 as described in CUSTID is ALWAYS POSSIBLE. PROVASSIGN runs inside a DB transaction. If you get a 590, the database is rolled back to the state it had before PROVASSIGN started. -------------------------------------------- ASSIGN id block JUSTNOW="x" JUST1YR="x" [FORCE="Y"|"N"] checks that block is assigned to CUSTID ID (unless FORCE=Y) sets the justification fields for BLOCK the justnow and just1yr fields are an integer and must pass the validation in the DB for an integer. responses: 200 OK 450 BLOCK ASSIGNED TO %s (%s) NOT UPDATED\r\n the 1st %s substitution is the UNIQUE id of who this block belongs to. the 2nd %s substitution is the billing reference number. 500 CUSTID NOT PROVIDED\r\n 500 Invalid characters in custid 0 through 9 only accepted\r\n 500 BLOCK NOT PROVIDED\r\n NB: 590/595 as described in CUSTID is ALWAYS POSSIBLE. -------------------------------------------- ASSIGN id block CUST_ASN="xxxx" [FORCE="Y"|"N"] the cust_asn field is an integer. The RFC spec is a short unsigned integer. The system does NOT enforce the values at the present time. If the system was to enforce it, a violation would cause an UPDATE FAILED message. ASSIGN id block MISTOKEN="xxxx" [FORCE="Y"|"N"] the MISTOKEN field is a 16 byte field of characters. The format is owned by MIS. This is for future use. ASSIGN id block DESTIP="xxxx" [FORCE="Y"|"N"] The destip field is an INET field, and must be acceptable to the INET input routines of PostgreSQL. When we pass the value to the database we strip leading and trailing spaces. If the format is not acceptable, an UPDATE FAILED message will be generated. ASSIGN id block PURPOSE="xxx" [FORCE="Y"|"N"] The purpose field is a 256 Byte CHARACTER VARYING field. It to a number from another table. If you specify a name that is NOT in the purpose_table, you will get an SQL NULL in the field and it will display as blanks. This *MAY* be changed later to force a pupose, and if so, an UPDATE FAILED message will be generated. ASSIGN id block INTERFACE="xxx" [FORCE="Y"|"N"] The INTERFACE field is a 256 Byte Character varying field. It is for documentation at present. same ideas as JUSTxxx fields. same responses as above. -------------------------------------------- RETURN id block [STATUS="xxxxx"] [FORCE="Y"|"N"] returns netblock to available (or other status) status defaults to pending_available, which means the block can be recovered in case of screwups. a block will stay in this state for 7 calendar days. The status field is a 256 byte character varying field that is turned into a number internally. You must give a valid value. the default is pending_available. If you give a NON valid value you will get an UPDATE FAILED message about NULL in NON-NULL. additional status' can be added at any time. responses: 200 RETURN OK block 450 BLOCK ASSIGNED TO %s (%s) NOT UPDATED\r\n the 1st %s substitution is the UNIQUE id of who this block belongs to. the 2nd %s substitution is the billing reference number. 500 CUSTID NOT PROVIDED\r\n 500 BLOCK NOT PROVIDED\r\n NB: 590/595 as described in CUSTID is ALWAYS POSSIBLE. -------------------------------------------- EXAMINE netblock data is netblock in CIDR notation. Missing /nn is NOT fatal. Responses: 215 EXAMINE DATA FOLLOWS:\r\n keyword='value' keyword=SQL_NULL . This will dump known information about a netblock/IP and all netblocks that contain that netblock. It will also dump information about the customers as well that are referenced from that netblock. NB: 590/595 as described in CUSTID is ALWAYS POSSIBLE. keyword=SQL_NULL means there is NO data in that field. -------------------------------------------- MOVEBLOCK id1 block routerip1 id2 routerip2 will move the netblock (in CIDR notation) from customer id1 on routerip1 to customer id2 on routerip2. NOTE: if you say the block is with one customer but it is NOT, the command will be rejected, same goes for routerip. 500 CUSTID1 NOT PROVIDED\r\n 500 CUSTID2 NOT PROVIDED\r\n 500 BLOCK NOT PROVIDED\r\n 500 ROUTERIP NOT PROVIDED\r\n 500 ROUTERIP2 NOT PROVIDED\r\n 500 no matching block found to move\r\n NB: 590/595 as described in CUSTID is ALWAYS POSSIBLE. and in this case means you probably gave bogus information on the setting side. -------------------------------------------- POOLCREATE sizeblock sizepoolentries routerip name creates a pool of IP's of size sizeblock (/24,/25,/26,/27,/28) of sizepoolentries(/32,/30) taking into account the network and broadcast addresses of the requested pool for routerip and named name. -------------------------------------------- POOLASSIGN custid size routerip name assigns a /size block out of pool name for routerip to custid. -------------------------------------------- POOLRETURN custid block routerip name returns block to routerip's pool name -------------------------------------------- QUIT ends session. 200 QUIT OK\r\n -------------------------------------------- NB: All FORCE="Y"|"N" options are parsed but are NO-OPS. ---------------------------------------------------*/ /* $Id: netmaster.c,v 1.43 2001/10/10 21:30:06 ler Exp $ */ #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <string.h> #include <unistd.h> #include <time.h> #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <syslog.h> #include <ctype.h> #include "libpq-fe.h" #define IA_NETDB_NAME "netmaster" #define IA_NETDB_HOST "localhost" #define IA_NETDB_PORT 5432 #define NETMASTER_SYSLOG_FAC LOG_LOCAL0 static PGconn *pgconn = NULL; static char db_error_message_buffer[32768]; typedef struct current_state { char userid[32]; char pw[32]; int hello; int quit; char command[32]; char response[512]; char name[256]; char company[256]; char addr[256]; char addr2[256]; char city[256]; char state[256]; char zip[256]; char tel[256]; char comment[256]; char justnow[256]; char just1yr[256]; char cust_asn[256]; char mistoken[256]; char destip[256]; char status[256]; char force[256]; char id_char[256]; char id_char2[256]; char reference[256]; char asn[256]; char size[256]; char routerip[256]; char routerip2[256]; char block[256]; char purpose[256]; char email[256]; char interface[256]; char splitting_block[256]; char corporate[256]; char product[256]; } CURRENT_STATE; char * myPQerrorMessage(PGconn * pgconn) { static char error_buffer[32768]; memset(error_buffer, '\0', sizeof(error_buffer)); strcpy(error_buffer, PQerrorMessage(pgconn)); error_buffer[strlen(error_buffer) - 1] = '\0'; /* nuke the linefeed */ return error_buffer; } #ifndef NM_SYSLOG_LIMIT #define NM_SYSLOG_LIMIT 128 #endif /* * Write a message line to syslog if the syslog option is set. * * Our problem here is that many syslog implementations don't handle long * messages in an acceptable manner. While this function doesn't help that * fact, it does work around by splitting up messages into smaller pieces. */ static void write_syslog(const char *line) { static int openlog_done = 0; static unsigned long seq = 0; static int syslog_fac = NETMASTER_SYSLOG_FAC; int len = strlen(line); if (!openlog_done) { openlog("NETMASTER", LOG_PID | LOG_NDELAY, syslog_fac); openlog_done = 1; } /* * We add a sequence number to each log message to suppress "same" * messages. */ seq++; /* divide into multiple syslog() calls if message is too long */ /* or if the message contains embedded NewLine(s) '\n' */ if (len > NM_SYSLOG_LIMIT || strchr(line, '\n') != NULL) { int chunk_nr = 0; while (len > 0) { char buf[NM_SYSLOG_LIMIT + 1]; int buflen; int l; int i; /* if we start at a newline, move ahead one char */ if (line[0] == '\n') { line++; len--; continue; } strncpy(buf, line, NM_SYSLOG_LIMIT); buf[NM_SYSLOG_LIMIT] = '\0'; if (strchr(buf, '\n') != NULL) *strchr(buf, '\n') = '\0'; l = strlen(buf); /* already word boundary? */ if (isspace((unsigned char)line[l]) || line[l] == '\0') buflen = l; else { /* try to divide at word boundary */ i = l - 1; while (i > 0 && !isspace((unsigned char)buf[i])) i--; if (i <= 0) /* couldn't divide word * boundary */ buflen = l; else { buflen = i; buf[i] = '\0'; } } chunk_nr++; syslog(LOG_DEBUG, "[%lu-%d] %s", seq, chunk_nr, buf); #if 0 fprintf(stdout, "%s\r\n", buf); #endif line += buflen; len -= buflen; } } else { /* message short enough */ syslog(LOG_DEBUG, "[%lu] %s", seq, line); #if 0 fprintf(stdout, "%s\r\n", line); #endif } } void prepare_error_message(const char *query_string, const char *db_error_message) { snprintf(db_error_message_buffer, sizeof(db_error_message_buffer), "%s-%d-%d\nQuery='%s'\nDBerror='%s'", IA_NETDB_HOST, (int)getpid(), (int)time(NULL), query_string, db_error_message); #if 0 fprintf(stdout, "595 Details Follow:\r\n"); fflush(stdout); #endif write_syslog(db_error_message_buffer); #if 0 fprintf(stdout, "\r\n.\r\n"); fflush(stdout); #endif } char * cleanse_field(char *string) { int i; static char buffer[32768]; char *char_ptr = &(buffer[0]); char *char_ptr2 = &(string[0]); memset(buffer, '\0', sizeof(buffer)); for (i = 0; i < strlen(string); i++) { if (*char_ptr2 == '\'') { *char_ptr++ = '\''; } *char_ptr++ = *char_ptr2++; } return buffer; } /* * make a new set of blocks of size from a /24 (or split something larger) */ int split_block(CURRENT_STATE * cur_state, char *resp_buffer, int size, int asn) { char query_string[8192]; char result_string[8192]; struct in_addr work_addr1; #ifdef NON_VLSM_ALLOWED int i; #endif int vlsm = 0; /* =0 means break up /24's into equal * sizes, =1 means find size one * bigger, and break in half */ int numaddr = 0; PGresult *pgres; query_string[0] = '\0'; switch (size) { case 32: numaddr = 1; sprintf(resp_buffer, "500 Splitting to /32 should be done in " "address pool logic\r\n"); return 1; break; case 31: sprintf(resp_buffer, "500 IA doesn't issue /31's\r\n"); return 1; case 30: numaddr = 4; break; case 29: numaddr = 8; break; case 28: numaddr = 16; break; case 27: numaddr = 32; break; case 26: numaddr = 64; break; case 25: numaddr = 128; break; case 24: numaddr = 256; break; #ifdef HANDLE_SHORTER_THAN_24 case 23: numaddr = 512; break; case 22: numaddr = 1024; break; case 21: numaddr = 2048; break; case 20: numaddr = 4096; break; case 19: numaddr = 8192; break; case 18: numaddr = 16384; break; case 17: numaddr = 32768; break; #endif case 0: sprintf(resp_buffer, "500 IMPOSSIBLE NETBLOCK SIZE! /0\r\n"); return 0; default: sprintf(resp_buffer, "500 request for a netblock less than /24 in length " "needs NETWORKING action\r\n"); return 2; } #ifdef DALLAS_NON_VLSM if (asn != 4278) #endif vlsm = 1; retry_block_split: snprintf(query_string, sizeof(query_string), "SELECT host(netblock), masklen(netblock), netblock, " "broadcast(netblock) " "FROM networks " "WHERE parent_asn=%d AND " "status=get_status_code('available') AND " "masklen(netblock) = %d " "FOR UPDATE " "LIMIT 1", asn, ((vlsm == 0) && (size > 24) ? 24 : size - 1)); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) != 1) { /* need to recurse in the vlsm case */ if ((size - 1) < 24) { sprintf(resp_buffer, "400 No Netblock available for request. Contact Networking.\r\n"); PQexec(pgconn, "ROLLBACK TRANSACTION"); return 1; } if (split_block(cur_state, resp_buffer, size - 1, asn) != 0) { return 1; } goto retry_block_split; } strcpy(result_string, PQgetvalue(pgres, 0, 0)); if (inet_aton(result_string, &work_addr1) != 1) { sprintf(resp_buffer, "590 inet_aton on '%s' failed!!!!!\r\n", result_string); PQclear(pgres); PQexec(pgconn, "ROLLBACK TRANSACTION"); return 1; } #ifdef NON_VLSM_ALLOWED /* * deal with /32 on net/bcast *//* also, nothing < /24 w/o networking approval */ for (i = 0; i < (size > 24 ? 256 : 32768); i += numaddr) { snprintf(query_string, sizeof(query_string), "INSERT INTO networks(netblock,status, " "last_update_by,last_update_at, " "parent_asn) VALUES('%s/%d', " "get_status_code('available'), " "'SPLIT_NETBLOCK',now(),%d) ", inet_ntoa(work_addr1), size, asn); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); fprintf(stdout, resp_buffer); prepare_error_message(query_string, myPQerrorMessage(pgconn)); fflush(stdout); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 1; } work_addr1.s_addr = htonl(ntohl(work_addr1.s_addr) + numaddr); PQclear(pgres); } #endif #ifndef NON_VLSM_ALLOWED /* break in half */ snprintf(query_string, sizeof(query_string), "INSERT INTO networks(netblock,status, " "last_update_by,last_update_at, " "parent_asn) VALUES('%s/%d', " "get_status_code('available'), " "'SPLIT_NETBLOCK', now(), %d)", inet_ntoa(work_addr1), size, asn); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 1; } work_addr1.s_addr = htonl(ntohl(work_addr1.s_addr) + numaddr); PQclear(pgres); snprintf(query_string, sizeof(query_string), "INSERT INTO networks(netblock,status, " "last_update_by,last_update_at, " "parent_asn) VALUES('%s/%d', " "get_status_code('available'), " "'SPLIT_NETBLOCK',now(), %d)", inet_ntoa(work_addr1), size, asn); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 1; } work_addr1.s_addr = htonl(ntohl(work_addr1.s_addr) + numaddr); PQclear(pgres); #endif snprintf(query_string, sizeof(query_string), "UPDATE networks " "SET status=get_status_code('subdivided'), " "last_update_by='SPLIT_NETBLOCK',last_update_at=now() " "WHERE netblock='%s/%d'", result_string, ((vlsm == 0) && (size > 24) ? 24 : size - 1)); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 1; } PQclear(pgres); return 0; } int get_netblock_provisionally(CURRENT_STATE * cur_state, char *resp_buffer, int size, int asn, char *block) { char query_string[8192]; char result_netblock_cidr[8192]; char result_netblock[8192]; char result_masklen[8192]; char result_netmask[8192]; PGresult *pgres; if (size == 0 || size == 31 || size < 17 || size > 32 || size < 0) { sprintf(resp_buffer, "500 Impossible size /%d\r\n", size); return 1; } query_string[0] = '\0'; if (PQstatus(pgconn) == CONNECTION_BAD) { snprintf(query_string, sizeof(query_string), "dbname=%s user=%s password=%s host=%s port=%d", IA_NETDB_NAME, cur_state->userid, cur_state->pw, IA_NETDB_HOST, IA_NETDB_PORT); pgconn = PQconnectdb(query_string); if (PQstatus(pgconn) == CONNECTION_BAD) { sprintf(resp_buffer, "500 Can't get DB connection '%s'\r\n", myPQerrorMessage(pgconn)); cur_state->quit = 1; return 0; } } pgres = PQexec(pgconn, "BEGIN TRANSACTION"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("BEGIN TRANSACTION", myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 0; PQclear(pgres); return 0; } snprintf(query_string, sizeof(query_string), "SELECT id FROM customer " "WHERE id=%s", cur_state->id_char); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) == 0) { sprintf(resp_buffer, "500 NO SUCH CUSTOMER ID (%s)\r\n", cur_state->id_char); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 1; } snprintf(query_string," retry_block: snprintf(query_string, sizeof(query_string), "SELECT host(netblock),masklen(netblock),netblock," "netmask(netblock) " "FROM networks " "WHERE parent_asn=%d AND " "status=get_status_code('available') AND " "masklen(netblock) = %d FOR UPDATE LIMIT 1", asn, size); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) == 0) { if (split_block(cur_state, resp_buffer, size, asn) != 0) { return 2; } goto retry_block; } if (PQntuples(pgres) != 1) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 0; } /* get NetBlock in CIDR notation */ strcpy(result_netblock_cidr, PQgetvalue(pgres, 0, 2)); /* get NetBlock */ strcpy(result_netblock, PQgetvalue(pgres, 0, 0)); /* get MaskLen */ strcpy(result_masklen, PQgetvalue(pgres, 0, 1)); strcpy(result_netmask, PQgetvalue(pgres, 0, 3)); PQclear(pgres); snprintf(query_string, sizeof(query_string), "UPDATE networks " "SET status=get_status_code('provisionally_assigned'), " "last_update_by='%s',last_update_at=now(), " "assigned_date=now(),assigned_by='%s', " "router=get_router_id('%s'::inet), " "customer_reference=%s " "WHERE netblock='%s'", cur_state->userid, cur_state->userid, cur_state->routerip, cur_state->id_char, result_netblock_cidr); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 0; } pgres = PQexec(pgconn, "COMMIT TRANSACTION"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("COMMIT TRANSACTION", myPQerrorMessage(pgconn)); PQexec(pgconn, "ROLLBACK TRANSACTION"); PQclear(pgres); return 0; /* bad PG, commit failed */ } sprintf(resp_buffer, "250 PROVASSIGN OK %s %s %s %s\r\n", result_netblock_cidr, result_netblock, result_masklen, result_netmask); strcpy(block, result_netblock_cidr); PQclear(pgres); return 0; } void reset_state(CURRENT_STATE * cur_state) { cur_state->command[0] = '\0'; cur_state->response[0] = '\0'; cur_state->name[0] = '\0'; cur_state->company[0] = '\0'; cur_state->addr[0] = '\0'; cur_state->addr2[0] = '\0'; cur_state->city[0] = '\0'; cur_state->state[0] = '\0'; cur_state->zip[0] = '\0'; cur_state->tel[0] = '\0'; cur_state->comment[0] = '\0'; cur_state->justnow[0] = '\0'; cur_state->just1yr[0] = '\0'; cur_state->cust_asn[0] = '\0'; cur_state->mistoken[0] = '\0'; cur_state->destip[0] = '\0'; cur_state->status[0] = '\0'; cur_state->force[0] = '\0'; cur_state->id_char[0] = '\0'; cur_state->id_char2[0] = '\0'; cur_state->reference[0] = '\0'; cur_state->asn[0] = '\0'; cur_state->size[0] = '\0'; cur_state->routerip[0] = '\0'; cur_state->routerip2[0] = '\0'; cur_state->block[0] = '\0'; cur_state->purpose[0] = '\0'; cur_state->email[0] = '\0'; cur_state->interface[0] = '\0'; } int process_helo(CURRENT_STATE * cur_state, char *resp_buffer) { char query_string[8192]; query_string[0] = '\0'; if (PQstatus(pgconn) == CONNECTION_BAD) { snprintf(query_string, sizeof(query_string), "dbname=%s user=%s password=%s host=%s port=%d", IA_NETDB_NAME, cur_state->userid, cur_state->pw, IA_NETDB_HOST, IA_NETDB_PORT); pgconn = PQconnectdb(query_string); if (PQstatus(pgconn) == CONNECTION_BAD) { sprintf(resp_buffer, "500 Can't get DB connection" " (most likely invalid ID/PW) '%s'\r\n", myPQerrorMessage(pgconn)); cur_state->quit = 1; return 0; } } sprintf(resp_buffer, "200 HELO OK %s\r\n", cur_state->userid); return 0; } int process_custid(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char token[8192]; char query_string[8192]; char *tkn; int made_new_id = 0; PGresult *pgres; query_string[0] = '\0'; tkn = strtok(NULL, "="); if (tkn == NULL) { strcpy(resp_buffer, "500 no arguments given\r\n"); return 0; } strcpy(token, tkn); if (strcasecmp(token, "REFERENCE") != 0) { sprintf(resp_buffer, "500 CUSTID command not followed by REFERENCE=\r\n"); cur_state->quit = 1; return 0; } strcpy(cur_state->reference, strtok(NULL, "\"")); if (PQstatus(pgconn) == CONNECTION_BAD) { snprintf(query_string, sizeof(query_string), "dbname=%s user=%s password=%s host=%s port=%d", IA_NETDB_NAME, cur_state->userid, cur_state->pw, IA_NETDB_HOST, IA_NETDB_PORT); pgconn = PQconnectdb(query_string); if (PQstatus(pgconn) == CONNECTION_BAD) { sprintf(resp_buffer, "500 Can't get DB connection '%s'\r\n", myPQerrorMessage(pgconn)); cur_state->quit = 1; return 0; } } retry_id_custid: snprintf(query_string, sizeof(query_string), "SELECT get_customer_id('%s')", cur_state->reference); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) == 0 || PQgetisnull(pgres, 0, 0) == 1) { /* assign new id */ PQclear(pgres); snprintf(query_string, sizeof(query_string), "INSERT INTO customer(reference_number) " "VALUES('%s')", cur_state->reference); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); cur_state->quit = 1; return 0; } PQclear(pgres); made_new_id = 1; goto retry_id_custid; } sprintf(resp_buffer, "250 CUSTID %s %s\r\n", PQgetvalue(pgres, 0, 0), made_new_id ? "(new)" : "(existing)"); return 0; } int process_custinfo(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char token[8192]; char value[8192]; int done = 0; char *tkn; PGresult *pgres; char query_string[8192]; char fields[8192]; query_string[0] = '\0'; tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 no arguments given\r\n"); return 0; } strcpy(cur_state->id_char, tkn); if (strspn(cur_state->id_char, "0123456789") != strlen(cur_state->id_char)) { strcpy(resp_buffer, "500 Invalid Character in id field, 0-9 ONLY are accepted\r\n"); return 0; } fields[0] = '\0'; while (!done) { tkn = strtok(NULL, "= \r\n"); if (tkn == NULL) { done = 1; continue; } strcpy(token, tkn); tkn = strtok(NULL, "\""); if (tkn == NULL) { done = 1; continue; } strcpy(value, tkn); strcpy(value, cleanse_field(value)); if (strcasecmp(token, "NAME") == 0) { strncpy(cur_state->name, value, sizeof(cur_state->name)); } if (strcasecmp(token, "ADDR") == 0) { strncpy(cur_state->addr, value, sizeof(cur_state->addr)); } if (strcasecmp(token, "ADDR2") == 0) strncpy(cur_state->addr2, value, sizeof(cur_state->addr2)); if (strcasecmp(token, "CITY") == 0) strncpy(cur_state->city, value, sizeof(cur_state->city)); if (strcasecmp(token, "STATE") == 0) strncpy(cur_state->state, value, sizeof(cur_state->state)); if (strcasecmp(token, "ZIP") == 0) strncpy(cur_state->zip, value, sizeof(cur_state->zip)); if (strcasecmp(token, "TEL") == 0) strncpy(cur_state->tel, value, sizeof(cur_state->tel)); if (strcasecmp(token, "COMPANY") == 0) strncpy(cur_state->company, value, sizeof(cur_state->company)); if (strcasecmp(token, "COMMENT") == 0) strncpy(cur_state->comment, value, sizeof(cur_state->comment)); if (strcasecmp(token, "EMAIL") == 0) strncpy(cur_state->email, value, sizeof(cur_state->email)); if (strcasecmp(token, "CORPORATE") == 0) { value[1] = '\0'; if (value[0] == 'Y' || value[0] == 'T' || value[0] == 'y' || value[0] == 't') { value[0] = 't'; } if (value[0] == 'N' || value[0] == 'n' || value[0] == 'F' || value[0] == 'f') { value[0] = 'f'; } strncpy(cur_state->corporate, value, sizeof(cur_state->corporate)); } } if (PQstatus(pgconn) == CONNECTION_BAD) { snprintf(query_string, sizeof(query_string), "dbname=%s user=%s password=%s host=%s port=%d", IA_NETDB_NAME, cur_state->userid, cur_state->pw, IA_NETDB_HOST, IA_NETDB_PORT); pgconn = PQconnectdb(query_string); if (PQstatus(pgconn) == CONNECTION_BAD) { sprintf(resp_buffer, "500 Can't get DB connection '%s'\r\n", myPQerrorMessage(pgconn)); cur_state->quit = 1; return 0; } } if (strlen(cur_state->name) != 0) { snprintf(value, sizeof(value), "name='%s'", cur_state->name); strcat(fields, value); } if (strlen(cur_state->addr) != 0) { snprintf(value, sizeof(value), "%saddress='%s'", strlen(fields) ? "," : "", cur_state->addr); strcat(fields, value); } if (strlen(cur_state->addr2) != 0) { snprintf(value, sizeof(value), "%saddress2='%s'", strlen(fields) ? "," : "", cur_state->addr2); strcat(fields, value); } if (strlen(cur_state->city) != 0) { snprintf(value, sizeof(value), "%scity='%s'", strlen(fields) ? "," : "", cur_state->city); strcat(fields, value); } if (strlen(cur_state->state) != 0) { snprintf(value, sizeof(value), "%sstate='%s'", strlen(fields) ? "," : "", cur_state->state); strcat(fields, value); } if (strlen(cur_state->zip) != 0) { snprintf(value, sizeof(value), "%szip='%s'", strlen(fields) ? "," : "", cur_state->zip); strcat(fields, value); } if (strlen(cur_state->email) != 0) { snprintf(value, sizeof(value), "%semail='%s'", strlen(fields) ? "," : "", cur_state->email); strcat(fields, value); } if (strlen(cur_state->tel) != 0) { snprintf(value, sizeof(value), "%stelephone='%s'", strlen(fields) ? "," : "", cur_state->tel); strcat(fields, value); } if (strlen(cur_state->comment) != 0) { snprintf(value, sizeof(value), "%scomment='%s'", strlen(fields) ? "," : "", cur_state->comment); strcat(fields, value); } if (strlen(cur_state->company) != 0) { snprintf(value, sizeof(value), "%scompany='%s'", strlen(fields) ? "," : "", cur_state->company); strcat(fields, value); } if (strlen(cur_state->corporate) != 0) { snprintf(value, sizeof(value), "%scorporate='%s'", strlen(fields) ? "," : "", cur_state->corporate); strcat(fields, value); } snprintf(query_string, sizeof(query_string), "UPDATE customer SET %s " "WHERE id=%s", fields, cur_state->id_char); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } sprintf(resp_buffer, "200 OK custinfo %s\r\n", cur_state->id_char); return 0; } int process_moveblock(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char *tkn; char query_string[8192]; PGresult *pgres; tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 CUSTID1 NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->id_char, tkn, sizeof(cur_state->id_char)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 BLOCK NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->block, tkn, sizeof(cur_state->block)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 ROUTERIP1 NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->routerip, tkn, sizeof(cur_state->routerip)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 CUSTID2 NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->id_char2, tkn, sizeof(cur_state->id_char2)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 ROUTERIP2 NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->routerip2, tkn, sizeof(cur_state->routerip2)); pgres = PQexec(pgconn, "BEGIN WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("BEGIN WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } snprintf(query_string, sizeof(query_string), "SELECT netblock FROM networks " "WHERE netblock='%s' AND customer_reference=%s " "AND router=get_router_id('%s'::inet) " "FOR UPDATE LIMIT 1", cur_state->block, cur_state->id_char, cur_state->routerip); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) != 1) { strcpy(resp_buffer, "500 no matching block found to move\r\n"); PQclear(pgres); pgres = PQexec(pgconn, "ROLLBACK WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("ROLLBACK WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } snprintf(query_string, sizeof(query_string), "UPDATE networks " "SET customer_reference=%s,router=get_router_id('%s'::inet)," "other_reference=get_customer_reference(%s)," "last_update_at=now(),last_update_by='%s' " "WHERE netblock='%s' AND customer_reference=%s " "AND router=get_router_id('%s'::inet) ", cur_state->id_char2, cur_state->routerip2, cur_state->id_char2,cur_state->userid, cur_state->block, cur_state->id_char, cur_state->routerip); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); PQexec(pgconn, "ROLLBACK WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("ROLLBACK WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } strcpy(resp_buffer, "200 MOVEBLOCK OK\r\n"); PQexec(pgconn, "COMMIT WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("COMMIT WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } int process_provassign(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char *tkn; int asn, size; struct in_addr work_addr1; tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 CUSTID NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->id_char, tkn, sizeof(cur_state->id_char)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 ASN NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->asn, tkn, sizeof(cur_state->asn)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 SIZE NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->size, tkn, sizeof(cur_state->size)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 ROUTERIP NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->routerip, tkn, sizeof(cur_state->routerip)); if (inet_aton(cur_state->routerip, &work_addr1) != 1) { sprintf(resp_buffer, "500 Invalid Routerip: %s\r\n", cur_state->routerip); return 0; } asn = strtol(cur_state->asn, NULL, 10); size = strtol(cur_state->size, NULL, 10); return get_netblock_provisionally(cur_state, resp_buffer, size, asn, work_buffer); } int process_assign(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char token[8192]; char value[8192]; char fields[8192]; char *ptr; char query_string[8192]; PGresult *pgres; int done = 0; char *tkn; query_string[0] = '\0'; fields[0] = '\0'; tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 CUSTID NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->id_char, tkn, sizeof(cur_state->id_char)); if (strspn(cur_state->id_char, "0123456789") != strlen(cur_state->id_char)) { sprintf(resp_buffer, "500 Invalid characters in custid 0 through 9 only accepted\r\n"); return 0; } tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 BLOCK NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->block, tkn, sizeof(cur_state->block)); while (!done) { tkn = strtok(NULL, "= \r\n"); if (tkn == NULL) { done = 1; continue; } strcpy(token, tkn); if (strcasecmp(token, "") == 0) { done = 1; continue; } strcpy(value, strtok(NULL, "\"")); strcpy(value, cleanse_field(value)); if (strcasecmp(value, "") == 0) { done = 1; continue; } if (strcasecmp(token, "CUST_ASN") == 0) strncpy(cur_state->cust_asn, value, sizeof(cur_state->cust_asn)); if (strcasecmp(token, "MISTOKEN") == 0) strncpy(cur_state->mistoken, value, sizeof(cur_state->mistoken)); if (strcasecmp(token, "DESTIP") == 0) { strncpy(cur_state->destip, value, sizeof(cur_state->destip)); ptr = strchr(cur_state->destip, ' '); if (ptr != NULL) *ptr = '\0'; } if (strcasecmp(token, "PURPOSE") == 0) strncpy(cur_state->purpose, value, sizeof(cur_state->purpose)); if (strcasecmp(token, "FORCE") == 0) strncpy(cur_state->force, value, sizeof(cur_state->force)); if (strcasecmp(token, "JUSTNOW") == 0) strncpy(cur_state->justnow, value, sizeof(cur_state->justnow)); if (strcasecmp(token, "JUST1YR") == 0) strncpy(cur_state->just1yr, value, sizeof(cur_state->just1yr)); if (strcasecmp(token, "INTERFACE") == 0) strncpy(cur_state->interface, value, sizeof(cur_state->interface)); } if (PQstatus(pgconn) == CONNECTION_BAD) { snprintf(query_string, sizeof(query_string), "dbname=%s user=%s password=%s host=%s port=%d", IA_NETDB_NAME, cur_state->userid, cur_state->pw, IA_NETDB_HOST, IA_NETDB_PORT); pgconn = PQconnectdb(query_string); if (PQstatus(pgconn) == CONNECTION_BAD) { sprintf(resp_buffer, "500 Can't get DB connection '%s'\r\n", myPQerrorMessage(pgconn)); cur_state->quit = 1; return 0; } } pgres = PQexec(pgconn, "BEGIN WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("BEGIN WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } snprintf(query_string, sizeof(query_string), "SELECT netblock,customer_reference," "get_customer_reference(customer_reference) " "FROM networks " "WHERE netblock='%s' FOR UPDATE ", cur_state->block); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) != 1) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); pgres = PQexec(pgconn, "ROLLBACK WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("ROLLBACK WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } if (strcmp(cur_state->id_char, PQgetvalue(pgres, 0, 1)) != 0) { sprintf(resp_buffer, "450 BLOCK ASSIGNED TO %s (%s) NOT UPDATED\r\n", PQgetvalue(pgres, 0, 1), PQgetvalue(pgres, 0, 2)); pgres = PQexec(pgconn, "ROLLBACK WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("ROLLBACK WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } if (strlen(cur_state->justnow) != 0) { snprintf(value, sizeof(value), "justification_now=%s", cur_state->justnow); strcat(fields, value); } if (strlen(cur_state->just1yr) != 0) { snprintf(value, sizeof(value), "%sjustification_1yr=%s", strlen(fields) ? "," : "", cur_state->just1yr); strcat(fields, value); } if (strlen(cur_state->cust_asn) != 0) { snprintf(value, sizeof(value), "%scust_asn=%s", strlen(fields) ? "," : "", cur_state->cust_asn); strcat(fields, value); } if (strlen(cur_state->mistoken) != 0) { snprintf(value, sizeof(value), "%smistoken='%s'", strlen(fields) ? "," : "", cur_state->mistoken); strcat(fields, value); } if (strlen(cur_state->destip) != 0) { snprintf(value, sizeof(value), "%sdest_ip='%s'", strlen(fields) ? "," : "", cur_state->destip); strcat(fields, value); } if (strlen(cur_state->interface) != 0) { snprintf(value, sizeof(value), "%sinterface='%s'", strlen(fields) ? "," : "", cur_state->interface); strcat(fields, value); } if (strlen(cur_state->purpose) != 0) { snprintf(value, sizeof(value), "%spurpose=get_purpose_code('%s')", strlen(fields) ? "," : "", cur_state->purpose); strcat(fields, value); } snprintf(value, sizeof(value), "%sstatus=get_status_code('assigned')", strlen(fields) ? "," : ""); strcat(fields, value); snprintf(value, sizeof(value), "%sother_reference=get_customer_reference(%s)", strlen(fields) ? "," : "", cur_state->id_char); strcat(fields, value); snprintf(value, sizeof(value), "%slast_update_at=now(),last_update_by='%s'", strlen(fields) ? "," : "", cur_state->userid); strcat(fields, value); snprintf(query_string, sizeof(query_string), "UPDATE networks " "SET %s " "WHERE netblock='%s'", fields, cur_state->block); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); pgres = PQexec(pgconn, "ROLLBACK WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("ROLLBACK WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } sprintf(resp_buffer, "200 ASSIGN OK\r\n"); pgres = PQexec(pgconn, "COMMIT WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("COMMIT WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } int process_examine(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char query_string[8192]; PGresult *pgres; int i = 0, j = 0; char *tkn; query_string[0] = '\0'; tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 BLOCK NOT PROVIDED\r\n"); return 0; } strcpy(cur_state->block, cleanse_field(tkn)); if (strlen(cur_state->block) > 40) { strcpy(resp_buffer, "500 Invalid Block\r\n"); return 0; } snprintf(query_string, sizeof(query_string), "SELECT netblock,get_status(status) as netblock_status, " "parent_asn as asn,cust_asn, " "get_customer_name(customer_reference) as customer_name," "get_customer_company(customer_reference) as customer_company," "get_customer_address(customer_reference) as customer_address," "get_customer_address2(customer_reference) as customer_address2," "get_customer_city(customer_reference) as customer_city," "get_customer_state(customer_reference) as customer_state," "get_customer_zip(customer_reference) as customer_zip," "get_customer_telephone(customer_reference) as customer_tel," "get_customer_email(customer_reference) as customer_email," "get_customer_reference(customer_reference) as reference," "get_customer_comments(customer_reference) as cust_comments," "justification_now as just_now," "justification_1yr as just_1yr," "get_router_name(router) as router_name," "get_router_ip(router) as router_ip," "interface as router_interface," "dest_ip as destip," "comments as net_comments " "FROM networks " "WHERE '%s' <<= netblock " "ORDER BY netblock DESC", cur_state->block); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } /* print a tuple or 2 */ fprintf(stdout, "215 EXAMINE DATA FOLLOWS:\r\n"); fflush(stdout); for (i = 0; i < PQntuples(pgres); i++) { for (j = 0; j < PQnfields(pgres); j++) { if (PQgetisnull(pgres, i, j)) { fprintf(stdout, " %s=SQL_NULL\r\n", PQfname(pgres, j)); } else fprintf(stdout, " %s='%s'\r\n", PQfname(pgres, j), PQgetvalue(pgres, i, j)); } } sprintf(resp_buffer, ".\r\n"); return 0; } int process_return(CURRENT_STATE * cur_state, char *work_buffer, char *resp_buffer) { char token[8192]; char value[8192]; char query_string[8192]; PGresult *pgres; int done = 0; char *tkn; query_string[0] = '\0'; tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 CUSTID NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->id_char, tkn, sizeof(cur_state->id_char)); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 BLOCK NOT PROVIDED\r\n"); return 0; } strncpy(cur_state->block, tkn, sizeof(cur_state->block)); while (!done) { tkn = strtok(NULL, "= \r\n"); if (tkn == NULL) { done = 1; continue; } strcpy(token, tkn); if (strcasecmp(token, "") == 0) { done = 1; continue; } strcpy(value, strtok(NULL, "\"")); strcpy(value, cleanse_field(value)); if (strcasecmp(value, "") == 0) { done = 1; continue; } if (strcasecmp(token, "STATUS") == 0) strncpy(cur_state->status, value, sizeof(cur_state->status)); if (strcasecmp(token, "FORCE") == 0) strncpy(cur_state->force, value, sizeof(cur_state->force)); } if (PQstatus(pgconn) == CONNECTION_BAD) { snprintf(query_string, sizeof(query_string), "dbname=%s user=%s password=%s host=%s port=%d", IA_NETDB_NAME, cur_state->userid, cur_state->pw, IA_NETDB_HOST, IA_NETDB_PORT); pgconn = PQconnectdb(query_string); if (PQstatus(pgconn) == CONNECTION_BAD) { sprintf(resp_buffer, "500 Can't get DB connection '%s'\r\n", myPQerrorMessage(pgconn)); cur_state->quit = 1; return 0; } } pgres = PQexec(pgconn, "BEGIN WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("BEGIN WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } snprintf(query_string, sizeof(query_string), "SELECT netblock,customer_reference," "get_customer_reference(customer_reference) " "FROM networks " "WHERE netblock='%s' FOR UPDATE ", cur_state->block); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_TUPLES_OK || PQntuples(pgres) != 1) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } if (strcmp(cur_state->id_char, PQgetvalue(pgres, 0, 1)) != 0) { sprintf(resp_buffer, "450 BLOCK ASSIGNED TO %s (%s) NOT UPDATED\r\n", PQgetvalue(pgres, 0, 1), PQgetvalue(pgres, 0, 2)); pgres = PQexec(pgconn, "ROLLBACK WORK"); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message("ROLLBACK WORK", myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } return 0; } if (strlen(cur_state->status) == 0) { strcpy(cur_state->status, "pending_available"); } snprintf(query_string, sizeof(query_string), "UPDATE networks " "SET status=get_status_code('%s'),last_update_at=now()," "last_update_by='%s' " "WHERE netblock='%s'", cur_state->status, cur_state->userid, cur_state->block); pgres = PQexec(pgconn, query_string); if (PQresultStatus(pgres) != PGRES_COMMAND_OK) { sprintf(resp_buffer, "590 DB ERROR: Report %s-%d-%d to networking\r\n", IA_NETDB_HOST, (int)getpid(), (int)time(NULL)); prepare_error_message(query_string, myPQerrorMessage(pgconn)); PQclear(pgres); return 0; } pgres = PQexec(pgconn, "COMMIT WORK"); sprintf(resp_buffer, "200 RETURN OK %s\r\n", cur_state->block); return 0; } int process_buffer(char *buffer, char *resp_buffer, CURRENT_STATE * cur_state) { char token[8192]; char work_buffer[16384]; char *tkn; strcpy(work_buffer, buffer); strcpy(token, strtok(work_buffer, " \r\n")); if (strcasecmp(token, "QUIT") == 0) { strcpy(resp_buffer, "200 QUIT OK\r\n"); cur_state->quit = 1; return 0; } if (cur_state->hello != 1) { if (strcasecmp(token, "HELO") != 0) { strcpy(resp_buffer, "500 HELO REQUIRED\r\n"); return 0; } tkn = strtok(NULL, " "); if (tkn == NULL) { strcpy(resp_buffer, "500 USERID not provided\r\n"); return 0; } strcpy(cur_state->userid, tkn); tkn = strtok(NULL, " \r\n"); if (tkn == NULL) { strcpy(resp_buffer, "500 Password not provided\r\n"); return 0; } strcpy(cur_state->pw, tkn); cur_state->hello = 1; return process_helo(cur_state, resp_buffer); } if (strcasecmp(token, "CUSTID") == 0) return process_custid(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "CUSTINFO") == 0) return process_custinfo(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "PROVASSIGN") == 0) return process_provassign(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "ASSIGN") == 0) return process_assign(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "RETURN") == 0) return process_return(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "EXAMINE") == 0) return process_examine(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "MOVEBLOCK") == 0) return process_moveblock(cur_state, work_buffer, resp_buffer); if (strcasecmp(token, "QUIT") == 0) { strcpy(resp_buffer, "200 QUIT OK\r\n"); cur_state->quit = 1; return 0; } sprintf(resp_buffer, "500 WHAT? %s\r\n", token); return 0; } int main(int argc, char **argv) { char buffer[16384]; char resp_buffer[16384]; CURRENT_STATE cur_state; memset(&cur_state, '\0', sizeof(cur_state)); memset(buffer, '\0', sizeof(buffer)); snprintf(buffer, sizeof(buffer), "250-Welcome to Netmaster ($Id: netmaster.c,v 1.43 2001/10/10 21:30:06 ler Exp $).\r\n250 READY\r\n"); fprintf(stdout, buffer); fflush(stdout); memset(buffer, '\0', sizeof(buffer)); while ((!feof(stdin)) && (cur_state.quit != 1)) { memset(buffer, '\0', sizeof(buffer)); if (fgets(buffer, sizeof(buffer), stdin) != NULL) { if (strlen(buffer) < 5) { fprintf(stdout, "500 WHAT?\r\n"); fflush(stdout); continue; } if (process_buffer(buffer, resp_buffer, &cur_state) == 0) { fprintf(stdout, resp_buffer); fflush(stdout); } else { fprintf(stdout, resp_buffer); fflush(stdout); } } reset_state(&cur_state); } return 0; }
Backtrace: 0x8079592 in file_pos_changed () (gdb) bt #0 0x8079592 in file_pos_changed () #1 0x283b0123 in gtk_marshal_NONE () from /usr/X11R6/lib/libgtk12.so.2 #2 0x283e0a2e in gtk_handlers_run () from /usr/X11R6/lib/libgtk12.so.2 #3 0x283dfe9d in gtk_signal_real_emit () from /usr/X11R6/lib/libgtk12.so.2 #4 0x283de262 in gtk_signal_emit_by_name () from /usr/X11R6/lib/libgtk12.so.2 #5 0x809e064 in text_get_text_no_replace () #6 0x809ce7e in gap_to () #7 0x80a7640 in gtk_extext_set_position () #8 0x809d0df in gap_to () #9 0x80a71de in gtk_extext_insert_text () #10 0x806db67 in open_file_full () #11 0x806bb77 in open_file_real () #12 0x8077f4c in main_finish () #13 0x8073254 in initialize_macro_language () #14 0x8077bd5 in main () #15 0x8064975 in _start () (gdb) quit The program is running. Exit anyway? (y or n) y $ -- Larry Rosenman http://www.lerctr.org/~ler Phone: +1 972-414-9812 E-Mail: ler@lerctr.org US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749
State Changed From-To: open->closed The fix has been committed to glimmer-1.2.1_1.