Commit 77ead586 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Minor mods to support Chris and testing harness. Look for a DB

redirection as indicated in the tmcd_redirect table of the DB, which
says what DB name to contact for each node. That table looks like
this, as of this writing:

    CREATE TABLE tmcd_redirect (
      node_id varchar(10) NOT NULL default '',
      dbname tinytext NOT NULL default '',
      PRIMARY KEY  (node_id)
    ) TYPE=MyISAM;

On error, fall back to the main DB.
parent d7be6627
...@@ -17,15 +17,19 @@ ...@@ -17,15 +17,19 @@
#define TESTMODE #define TESTMODE
#define VERSION 2 #define VERSION 2
#define NETMASK "255.255.255.0" #define NETMASK "255.255.255.0"
#ifndef TBDBNAME
#define TBDBNAME "tbdb" /* Defined in configure */
#endif
#define DBNAME TBDBNAME
/* Defined in configure and passed in via the makefile */
#define DBNAME_SIZE 64
#define DEFAULT_DBNAME TBDBNAME
static int debug = 0;
static int portnum = TBSERVER_PORT;
static char dbname[DBNAME_SIZE];
static int nodeidtoexp(char *nodeid, char *pid, char *eid); static int nodeidtoexp(char *nodeid, char *pid, char *eid);
static int iptonodeid(struct in_addr ipaddr, char *bufp); static int iptonodeid(struct in_addr ipaddr, char *bufp);
static int nodeidtonickname(char *nodeid, char *nickname); static int nodeidtonickname(char *nodeid, char *nickname);
static int nodeidtocontrolnet(char *nodeid, int *net); static int nodeidtocontrolnet(char *nodeid, int *net);
static int checkdbredirect(struct in_addr ipaddr);
int client_writeback(int sock, void *buf, int len, int tcp); int client_writeback(int sock, void *buf, int len, int tcp);
void client_writeback_done(int sock, struct sockaddr_in *client); void client_writeback_done(int sock, struct sockaddr_in *client);
MYSQL_RES * mydb_query(char *query, int ncols, ...); MYSQL_RES * mydb_query(char *query, int ncols, ...);
...@@ -72,13 +76,45 @@ struct command { ...@@ -72,13 +76,45 @@ struct command {
}; };
static int numcommands = sizeof(command_array)/sizeof(struct command); static int numcommands = sizeof(command_array)/sizeof(struct command);
char *usagestr =
"usage: tmcd [-d] [-p #]\n"
" -d Turn on debugging. Multiple -d options increase output\n"
" -p portnum Specify a port number to listen on\n"
"\n";
void
usage()
{
fprintf(stderr, usagestr);
exit(1);
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int tcpsock, udpsock; int tcpsock, udpsock, ch;
int length, i, err = 0; int length, i, err = 0;
struct sockaddr_in name; struct sockaddr_in name;
while ((ch = getopt(argc, argv, "dp:")) != -1)
switch(ch) {
case 'p':
portnum = atoi(optarg);
break;
case 'd':
debug++;
case 'h':
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc)
usage();
openlog("tmcd", LOG_PID, LOG_USER); openlog("tmcd", LOG_PID, LOG_USER);
syslog(LOG_NOTICE, "daemon starting (version %d)", VERSION); syslog(LOG_NOTICE, "daemon starting (version %d)", VERSION);
...@@ -105,7 +141,7 @@ main(int argc, char **argv) ...@@ -105,7 +141,7 @@ main(int argc, char **argv)
/* Create name. */ /* Create name. */
name.sin_family = AF_INET; name.sin_family = AF_INET;
name.sin_addr.s_addr = INADDR_ANY; name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = htons(TBSERVER_PORT); name.sin_port = htons((u_short) portnum);
if (bind(tcpsock, (struct sockaddr *) &name, sizeof(name))) { if (bind(tcpsock, (struct sockaddr *) &name, sizeof(name))) {
syslog(LOG_ERR, "binding stream socket: %m"); syslog(LOG_ERR, "binding stream socket: %m");
exit(1); exit(1);
...@@ -141,7 +177,7 @@ main(int argc, char **argv) ...@@ -141,7 +177,7 @@ main(int argc, char **argv)
/* Create name. */ /* Create name. */
name.sin_family = AF_INET; name.sin_family = AF_INET;
name.sin_addr.s_addr = INADDR_ANY; name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = htons(TBSERVER_PORT); name.sin_port = htons((u_short) portnum);
if (bind(udpsock, (struct sockaddr *) &name, sizeof(name))) { if (bind(udpsock, (struct sockaddr *) &name, sizeof(name))) {
syslog(LOG_ERR, "binding stream socket: %m"); syslog(LOG_ERR, "binding stream socket: %m");
exit(1); exit(1);
...@@ -157,9 +193,8 @@ main(int argc, char **argv) ...@@ -157,9 +193,8 @@ main(int argc, char **argv)
while (1) { while (1) {
struct sockaddr_in client; struct sockaddr_in client;
#ifdef TESTMODE struct sockaddr_in redirect_client;
struct sockaddr_in oclient; int redirect = 0;
#endif
int clientsock, length = sizeof(client); int clientsock, length = sizeof(client);
char buf[MYBUFSIZE], *bp, *cp; char buf[MYBUFSIZE], *bp, *cp;
int cc, nfds, istcp; int cc, nfds, istcp;
...@@ -211,27 +246,62 @@ main(int argc, char **argv) ...@@ -211,27 +246,62 @@ main(int argc, char **argv)
buf[cc] = '\0'; buf[cc] = '\0';
bp = buf; bp = buf;
#ifdef TESTMODE
/* /*
* Allow remote end to be specified for testing. * Look for REDIRECT, which is a proxy request for a
* client other than the one making the request. Good
* for testing. Might become a general tmcd redirect at
* some point, so that we can test new tmcds.
*/ */
oclient = client; if (strncmp("REDIRECT=", buf, strlen("REDIRECT=")) == 0) {
if (strncmp("MYIP=", buf, strlen("MYIP=")) == 0) {
char *tp; char *tp;
bp += strlen("MYIP="); bp += strlen("REDIRECT=");
tp = bp; tp = bp;
while (! isspace(*tp)) while (! isspace(*tp))
tp++; tp++;
*tp++ = '\0'; *tp++ = '\0';
redirect_client = client;
redirect = 1;
inet_aton(bp, &client.sin_addr); inet_aton(bp, &client.sin_addr);
bp = tp; bp = tp;
} }
#endif
cp = (char *) malloc(cc + 1); cp = (char *) malloc(cc + 1);
assert(cp); assert(cp);
strcpy(cp, bp); strcpy(cp, bp);
#ifndef TESTMODE
/*
* IN TESTMODE, we allow redirect.
* Otherwise not since that would be a (minor) privacy
* risk, by allowing testbed nodes to get info for other
* nodes.
*/
if (redirect) {
char buf1[32], buf2[32];
strcpy(buf1, inet_ntoa(redirect_client.sin_addr));
strcpy(buf2, inet_ntoa(client.sin_addr));
syslog(LOG_INFO,
"%s INVALID REDIRECT: %s", buf1, buf2);
goto skipit;
}
#endif
/*
* Check for a redirect using the default DB. This allows
* for a simple redirect to a secondary DB for testing.
* Not very general. Might change to full blown tmcd
* redirection at some point, but this is a very quick and
* easy hack. Upon return, the dbname has been changed if
* redirection is in force.
*/
strcpy(dbname, DEFAULT_DBNAME);
if (checkdbredirect(client.sin_addr)) {
/* Something went wrong */
goto skipit;
}
/* /*
* Figure out what command was given. * Figure out what command was given.
*/ */
...@@ -243,9 +313,11 @@ main(int argc, char **argv) ...@@ -243,9 +313,11 @@ main(int argc, char **argv)
/* /*
* And execute it. * And execute it.
*/ */
if (i == numcommands) if (i == numcommands) {
syslog(LOG_INFO, "%s INVALID REQUEST: %.8s...", syslog(LOG_INFO, "%s INVALID REQUEST: %.8s...",
inet_ntoa(client.sin_addr), cp); inet_ntoa(client.sin_addr), cp);
goto skipit;
}
else { else {
bp = cp + strlen(command_array[i].cmdname); bp = cp + strlen(command_array[i].cmdname);
...@@ -270,10 +342,11 @@ main(int argc, char **argv) ...@@ -270,10 +342,11 @@ main(int argc, char **argv)
command_array[i].cmdname, err); command_array[i].cmdname, err);
} }
skipit:
free(cp); free(cp);
#ifdef TESTMODE if (redirect)
client = oclient; client = redirect_client;
#endif
if (istcp) if (istcp)
close(clientsock); close(clientsock);
else else
...@@ -1408,15 +1481,15 @@ mydb_query(char *query, int ncols, ...) ...@@ -1408,15 +1481,15 @@ mydb_query(char *query, int ncols, ...)
} }
mysql_init(&db); mysql_init(&db);
if (mysql_real_connect(&db, 0, 0, 0, DBNAME, 0, 0, 0) == 0) { if (mysql_real_connect(&db, 0, 0, 0, dbname, 0, 0, 0) == 0) {
syslog(LOG_ERR, "%s: connect failed: %s", syslog(LOG_ERR, "%s: connect failed: %s",
DBNAME, mysql_error(&db)); dbname, mysql_error(&db));
return (MYSQL_RES *) 0; return (MYSQL_RES *) 0;
} }
if (mysql_real_query(&db, querybuf, n) != 0) { if (mysql_real_query(&db, querybuf, n) != 0) {
syslog(LOG_ERR, "%s: query failed: %s", syslog(LOG_ERR, "%s: query failed: %s",
DBNAME, mysql_error(&db)); dbname, mysql_error(&db));
mysql_close(&db); mysql_close(&db);
return (MYSQL_RES *) 0; return (MYSQL_RES *) 0;
} }
...@@ -1424,7 +1497,7 @@ mydb_query(char *query, int ncols, ...) ...@@ -1424,7 +1497,7 @@ mydb_query(char *query, int ncols, ...)
res = mysql_store_result(&db); res = mysql_store_result(&db);
if (res == 0) { if (res == 0) {
syslog(LOG_ERR, "%s: store_result failed: %s", syslog(LOG_ERR, "%s: store_result failed: %s",
DBNAME, mysql_error(&db)); dbname, mysql_error(&db));
mysql_close(&db); mysql_close(&db);
return (MYSQL_RES *) 0; return (MYSQL_RES *) 0;
} }
...@@ -1433,7 +1506,7 @@ mydb_query(char *query, int ncols, ...) ...@@ -1433,7 +1506,7 @@ mydb_query(char *query, int ncols, ...)
if (ncols && ncols != (int)mysql_num_fields(res)) { if (ncols && ncols != (int)mysql_num_fields(res)) {
syslog(LOG_ERR, "%s: Wrong number of fields returned " syslog(LOG_ERR, "%s: Wrong number of fields returned "
"Wanted %d, Got %d", "Wanted %d, Got %d",
DBNAME, ncols, (int)mysql_num_fields(res)); dbname, ncols, (int)mysql_num_fields(res));
mysql_free_result(res); mysql_free_result(res);
return (MYSQL_RES *) 0; return (MYSQL_RES *) 0;
} }
...@@ -1456,15 +1529,15 @@ mydb_update(char *query, ...) ...@@ -1456,15 +1529,15 @@ mydb_update(char *query, ...)
} }
mysql_init(&db); mysql_init(&db);
if (mysql_real_connect(&db, 0, 0, 0, DBNAME, 0, 0, 0) == 0) { if (mysql_real_connect(&db, 0, 0, 0, dbname, 0, 0, 0) == 0) {
syslog(LOG_ERR, "%s: connect failed: %s", syslog(LOG_ERR, "%s: connect failed: %s",
DBNAME, mysql_error(&db)); dbname, mysql_error(&db));
return 1; return 1;
} }
if (mysql_real_query(&db, querybuf, n) != 0) { if (mysql_real_query(&db, querybuf, n) != 0) {
syslog(LOG_ERR, "%s: query failed: %s", syslog(LOG_ERR, "%s: query failed: %s",
DBNAME, mysql_error(&db)); dbname, mysql_error(&db));
mysql_close(&db); mysql_close(&db);
return 1; return 1;
} }
...@@ -1594,6 +1667,56 @@ nodeidtocontrolnet(char *nodeid, int *net) ...@@ -1594,6 +1667,56 @@ nodeidtocontrolnet(char *nodeid, int *net)
return 0; return 0;
} }
/*
* Check for DBname redirection.
*/
static int
checkdbredirect(struct in_addr ipaddr)
{
MYSQL_RES *res;
MYSQL_ROW row;
char nodeid[32];
char newdb[128];
/*
* Find the nodeid.
*/
if (iptonodeid(ipaddr, nodeid)) {
syslog(LOG_ERR, "CHECKDBREDIRECT: %s: No such node",
inet_ntoa(ipaddr));
return 1;
}
/*
* Look for an alternate DB name.
*/
res = mydb_query("select dbname from tmcd_redirect where node_id='%s'",
1, nodeid);
if (!res) {
syslog(LOG_ERR, "CHECKDBREDIRECT: "
"%s: DB Error getting redirect table!", nodeid);
return 1;
}
if ((int)mysql_num_rows(res)) {
row = mysql_fetch_row(res);
strcpy(dbname, row[0]);
}
/*
* Okay, lets test to make sure that DB exists. If not, fall back
* on the main DB.
*/
if (iptonodeid(ipaddr, nodeid)) {
syslog(LOG_ERR, "CHECKDBREDIRECT: %s: %s DB does not exist",
inet_ntoa(ipaddr), dbname);
strcpy(dbname, DEFAULT_DBNAME);
}
mysql_free_result(res);
return 0;
}
/* /*
* Lets hear it for global state...Yeah! * Lets hear it for global state...Yeah!
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment