Example #1
0
str
mnstr_socket_wastreamwrap(Stream *S, int *socket, str *name)
{
	stream *s;

	if ((s = socket_wastream(*socket, *name)) == NULL || mnstr_errnr(s)) {
		int errnr = mnstr_errnr(s);
		if (s)
			mnstr_destroy(s);
		throw(IO, "streams.open", "could not open socket: %s",
				strerror(errnr));
	} else {
		*(stream**)S = s;
	}

	return MAL_SUCCEED;
}
Example #2
0
/* Sends command for database to merovingian listening at host and port.
 * If host is a path, and port is -1, a UNIX socket connection for host
 * is opened.  The response of merovingian is returned as a malloced
 * string.  If wait is set to a non-zero value, this function will only
 * return after it has seen an EOF from the server.  This is useful with
 * multi-line responses, but can lock up for single line responses where
 * the server allows pipelining (and hence doesn't close the
 * connection).
 */
char* control_send(
		char** ret,
		char* host,
		int port,
		char* database,
		char* command,
		char wait,
		char* pass)
{
	char sbuf[8096];
	char rbuf[8096];
	char *buf;
	int sock = -1;
	ssize_t len;
	stream *fdin = NULL;
	stream *fdout = NULL;

	*ret = NULL;		/* gets overwritten in case of success */
	if (port == -1) {
		struct sockaddr_un server;
		/* UNIX socket connect */
		if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
			snprintf(sbuf, sizeof(sbuf), "cannot open connection: %s",
					strerror(errno));
			return(strdup(sbuf));
		}
		memset(&server, 0, sizeof(struct sockaddr_un));
		server.sun_family = AF_UNIX;
		strncpy(server.sun_path, host, sizeof(server.sun_path) - 1);
		if (connect(sock, (SOCKPTR) &server, sizeof(struct sockaddr_un)) == -1) {
			snprintf(sbuf, sizeof(sbuf), "cannot connect: %s", strerror(errno));
			close(sock);
			return(strdup(sbuf));
		}
	} else {
		struct sockaddr_in server;
		struct hostent *hp;
		char ver = 0;
		char *p;

		/* TCP socket connect */
		if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
			snprintf(sbuf, sizeof(sbuf), "cannot open connection: %s",
					strerror(errno));
			return(strdup(sbuf));
		}
		hp = gethostbyname(host);
		if (hp == NULL) {
			snprintf(sbuf, sizeof(sbuf), "cannot lookup hostname: %s",
					hstrerror(h_errno));
			close(sock);
			return(strdup(sbuf));
		}
		memset(&server, 0, sizeof(struct sockaddr_in));
		server.sin_family = hp->h_addrtype;
		memcpy(&server.sin_addr, hp->h_addr_list[0], hp->h_length);
		server.sin_port = htons((unsigned short) (port & 0xFFFF));
		if (connect(sock, (SOCKPTR) &server, sizeof(struct sockaddr_in)) == -1) {
			snprintf(sbuf, sizeof(sbuf), "cannot connect: %s", strerror(errno));
			close(sock);
			return(strdup(sbuf));
		}

		/* try reading length */
		len = recv(sock, rbuf, 2, 0);
		if (len == 2)
			len += recv(sock, rbuf + len, sizeof(rbuf) - len - 1, 0);
		/* perform login ritual */
		if (len <= 2) {
			snprintf(sbuf, sizeof(sbuf), "no response from monetdbd");
			close(sock);
			return(strdup(sbuf));
		}
		rbuf[len] = 0;
		/* we only understand merovingian:1 and :2 (backwards compat
		 * <=Aug2011) and mapi v9 on merovingian */
		if (strncmp(rbuf, "merovingian:1:", strlen("merovingian:1:")) == 0) {
			buf = rbuf + strlen("merovingian:1:");
			ver = 1;
		} else if (strncmp(rbuf, "merovingian:2:", strlen("merovingian:2:")) == 0) {
			buf = rbuf + strlen("merovingian:2:");
			ver = 2;
		} else if (strstr(rbuf + 2, ":merovingian:9:") != NULL) {
			buf = rbuf + 2;
			ver = 9;

			fdin = block_stream(socket_rastream(sock, "client in"));
			fdout = block_stream(socket_wastream(sock, "client out"));
		} else {
			if (len > 2 &&
					(strstr(rbuf + 2, ":BIG:") != NULL ||
					 strstr(rbuf + 2, ":LIT:") != NULL))
			{
				snprintf(sbuf, sizeof(sbuf), "cannot connect: "
						"server looks like a mapi server, "
						"are you connecting to an mserver directly "
						"instead of monetdbd?");
			} else {
				snprintf(sbuf, sizeof(sbuf), "cannot connect: "
						"unsupported monetdbd server");
			}
			close(sock);
			return(strdup(sbuf));
		}

		switch (ver) {
			case 1:
			case 2:  /* we never really used the mode specifier of v2 */
				p = strchr(buf, ':');
				if (p != NULL)
					*p = '\0';
				p = control_hash(pass, buf);
				len = snprintf(sbuf, sizeof(sbuf), "%s%s\n",
						p, ver == 2 ? ":control" : "");
				len = send(sock, sbuf, len, 0);
				free(p);
				if (len == -1) {
					close(sock);
					return(strdup("cannot send challenge response to server"));
				}
				break;
			case 9:
			{
				char *chal = NULL;
				char *algos = NULL;
				char *shash = NULL;
				char *phash = NULL;
				char *algsv[] = {
					"RIPEMD160",
					"SHA256",
					"SHA1",
					"MD5",
					NULL
				};
				char **algs = algsv;

				/* buf at this point looks like
				 * "challenge:servertype:protover:algos:endian:hash:" */
				chal = buf; /* chal */
				p = strchr(chal, ':');
				if (p == NULL) {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"invalid challenge from monetdbd server");
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
				*p++ = '\0'; /* servertype */
				p = strchr(p, ':');
				if (p == NULL) {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"invalid challenge from monetdbd server");
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
				*p++ = '\0'; /* protover */
				p = strchr(p, ':');
				if (p == NULL) {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"invalid challenge from monetdbd server");
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
				*p++ = '\0'; /* algos */
				algos = p;
				p = strchr(p, ':');
				if (p == NULL) {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"invalid challenge from monetdbd server");
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
				*p++ = '\0'; /* endian */
				p = strchr(p, ':');
				if (p == NULL) {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"invalid challenge from monetdbd server");
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
				*p++ = '\0'; /* hash */
				shash = p;
				p = strchr(p, ':');
				if (p == NULL) {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"invalid challenge from monetdbd server");
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
				*p = '\0';

				/* we first need to hash our password in the form the
				 * server stores it too */
				if (strcmp(shash, "RIPEMD160") == 0) {
					phash = mcrypt_RIPEMD160Sum(pass, strlen(pass));
				} else if (strcmp(shash, "SHA512") == 0) {
					phash = mcrypt_SHA512Sum(pass, strlen(pass));
				} else if (strcmp(shash, "SHA384") == 0) {
					phash = mcrypt_SHA384Sum(pass, strlen(pass));
				} else if (strcmp(shash, "SHA256") == 0) {
					phash = mcrypt_SHA256Sum(pass, strlen(pass));
				} else if (strcmp(shash, "SHA224") == 0) {
					phash = mcrypt_SHA224Sum(pass, strlen(pass));
				} else if (strcmp(shash, "SHA1") == 0) {
					phash = mcrypt_SHA1Sum(pass, strlen(pass));
				} else if (strcmp(shash, "MD5") == 0) {
					phash = mcrypt_MD5Sum(pass, strlen(pass));
				} else {
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"monetdbd server requires unknown hash: %s", shash);
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}

				/* now hash the password hash with the provided
				 * challenge */
				for (; *algs != NULL; algs++) {
					/* TODO: make this actually obey the separation by
					 * commas, and only allow full matches */
					if (strstr(algos, *algs) != NULL) {
						p = mcrypt_hashPassword(*algs, phash, chal);
						if (p == NULL)
							continue;
						mnstr_printf(fdout,
								"BIG:monetdb:{%s}%s:control:merovingian:\n",
								*algs, p);
						mnstr_flush(fdout);
						free(p);
						break;
					}
				}
				free(phash);
				if (p == NULL) {
					/* the server doesn't support what we can */
					snprintf(sbuf, sizeof(sbuf), "cannot connect: "
							"unsupported hash algoritms: %s", algos);
					close_stream(fdout);
					close_stream(fdin);
					return(strdup(sbuf));
				}
			}
		}

		if (fdin != NULL) {
			/* stream.h is sooo broken :( */
			memset(rbuf, '\0', sizeof(rbuf));
			if ((len = mnstr_read_block(fdin, rbuf, sizeof(rbuf) - 1, 1)) < 0) {
				close_stream(fdout);
				close_stream(fdin);
				return(strdup("no response from monetdbd after login"));
			}
			rbuf[len - 1] = '\0';
		} else {
			if ((len = recv(sock, rbuf, sizeof(rbuf), 0)) <= 0) {
				close(sock);
				return(strdup("no response from monetdbd after login"));
			}
			rbuf[len - 1] = '\0';
		}

		if (strcmp(rbuf, "=OK") != 0 && strcmp(rbuf, "OK") != 0) {
			buf = rbuf;
			if (*buf == '!')
				buf++;
			if (fdin != NULL) {
				close_stream(fdout);
				close_stream(fdin);
			} else {
				close(sock);
			}
			return(strdup(buf));
		}
	}

	if (fdout != NULL) {
		mnstr_printf(fdout, "%s %s\n", database, command);
		mnstr_flush(fdout);
	} else {
		len = snprintf(sbuf, sizeof(sbuf), "%s %s\n", database, command);
		if (send(sock, sbuf, len, 0) == -1) {
			close(sock);
			return(strdup("failed to send control command to server"));
		}
	}
	if (wait != 0) {
		size_t buflen = sizeof(sbuf);
		size_t bufpos = 0;
		char *bufp;
		bufp = buf = malloc(sizeof(char) * buflen);
		if (buf == NULL) {
			if (fdin != NULL) {
				close_stream(fdin);
				close_stream(fdout);
			} else {
				close(sock);
			}
			return(strdup("failed to allocate memory"));
		}
		while (1) {
			if (fdin != NULL) {
				/* stream.h is sooo broken :( */
				memset(buf + bufpos, '\0', buflen - bufpos);
				len = mnstr_read_block(fdin, buf + bufpos, buflen - bufpos - 1, 1);
				if (len >= 0)
					len = strlen(buf + bufpos);
			} else {
				len = recv(sock, buf + bufpos, buflen - bufpos, 0);
			}
			if (len <= 0)
				break;
			if ((size_t)len == buflen - bufpos) {
				buflen *= 2;
				bufp = realloc(buf, sizeof(char) * buflen);
				if (bufp == NULL) {
					free(buf);
					if (fdin != NULL) {
						close_stream(fdin);
						close_stream(fdout);
					} else {
						close(sock);
					}
					return(strdup("failed to allocate more memory"));
				}
				buf = bufp;
			}
			bufpos += (size_t)len;
		}
		if (bufpos == 0) {
			if (fdin != NULL) {
				close_stream(fdin);
				close_stream(fdout);
			} else {
				close(sock);
			}
			free(buf);
			return(strdup("incomplete response from monetdbd"));
		}
		buf[bufpos - 1] = '\0';

		if (fdin) {
			/* strip out protocol = */
			memmove(bufp, bufp + 1, strlen(bufp + 1) + 1);
			while ((bufp = strstr(bufp, "\n=")) != NULL)
				memmove(bufp + 1, bufp + 2, strlen(bufp + 2) + 1);
		}
		*ret = buf;
	} else {
		if (fdin != NULL) {
			if (mnstr_read_block(fdin, rbuf, sizeof(rbuf) - 1, 1) < 0) {
				close_stream(fdin);
				close_stream(fdout);
				return(strdup("incomplete response from monetdbd"));
			}
			rbuf[strlen(rbuf) - 1] = '\0';
			*ret = strdup(rbuf + 1);
		} else {
			if ((len = recv(sock, rbuf, sizeof(rbuf), 0)) <= 0) {
				close(sock);
				return(strdup("incomplete response from monetdbd"));
			}
			rbuf[len - 1] = '\0';
			*ret = strdup(rbuf);
		}
	}

	if (fdin != NULL) {
		close_stream(fdin);
		close_stream(fdout);
	} else {
		close(sock);
	}

	return(NULL);
}
Example #3
0
int main(int argc, char **argv)
{
	MT_Id pid;
	int i, j = 0;
	char *err = NULL;
	char name[MYBUFSIZ + 1];
	char hostname[1024];
	Sensor se = NULL;
	static SOCKET sockfd;
	static struct option long_options[18] = {
		{ "increment", 0, 0, 'i' },
		{ "batch", 1, 0, 'b' },
		{ "columns", 1, 0, 'c' },
		{ "client", 0, 0, 'c' },
		{ "port", 1, 0, 'p' },
		{ "protocol", 1, 0, 'p' },
		{ "timestamp", 0, 0, 't' },
		{ "time", 1, 0, 't' },
		{ "events", 1, 0, 'e' },
		{ "sensor", 1, 0, 's' },
		{ "server", 0, 0, 's' },
		{ "replay", 0, 0, 'r' },
		{ "delay", 1, 0, 'd' },
		{ "file", 1, 0, 'f' },
		{ "host", 1, 0, 'h' },
		{ "trace", 0, 0, 't' },
		{ "help", 1, 0, '?' },
		{ 0, 0, 0, 0 }
	};
	THRdata[0] = (void *) file_wastream(stdout, "stdout");
	THRdata[1] = (void *) file_rastream(stdin, "stdin");
	for (i = 0; i < THREADS; i++) {
		GDKthreads[i].tid = i + 1;
	}
	for (;;) {
		int option_index = 0;
		int c = getopt_long(argc, argv, "i:b:c:c:p:p:t:t:e:s:s:r:d:f:h:t:?:0",
				long_options, &option_index);
		if (c == -1)
			break;

		switch (c) {
		case 'b':
			batchsize = optarg ? atol(optarg) : -1;
			if (batchsize <= 0) {
				mnstr_printf(SEout, "Illegal batch %d\n", batchsize);
				exit(0);
			}
			break;
		case 'c':
			if (strcmp(long_options[option_index].name, "client") == 0) {
				server = 0;
				break;
			}
			columns = optarg ? atol(optarg) : -1;
			if (columns <= 0) {
				mnstr_printf(SEout, "Illegal columns %d\n", columns);
				exit(0);
			}
			break;
		case 'd':
			delay = optarg ? atol(optarg) : -1;
			if (delay < 0) {
				mnstr_printf(SEout, "Illegal delay %d\n", delay);
				exit(0);
			}
			break;
		case 'i':
			autoincrement = optarg ? atol(optarg) : 0;
			if (autoincrement < 0) {
				mnstr_printf(SEout, "Illegal increment %d\n", autoincrement);
				exit(0);
			}
			break;
		case 't':
			if (strcmp(long_options[option_index].name, "timestamp") == 0) {
				timestamp = 1;
				break;
			}
			if (strcmp(long_options[option_index].name, "time") == 0) {
				timecolumn = optarg ? atol(optarg) : 0;
				break;
			}
			if (strcmp(long_options[option_index].name, "trace") == 0) {
				trace = optarg ? atol(optarg) : 1;
			} else {
				usage();
				exit(0);
			}
			break;
		case 'f':
			datafile = optarg && *optarg? optarg:0;
			break;
		case 'e':
			if (strcmp(long_options[option_index].name, "events") == 0) {
				events = optarg ? atol(optarg) : -1;
				if (events < -1) {
					mnstr_printf(SEout, "illegal events value, reset to -1\n");
					events = -1;
				} else if (events == 0) {
					mnstr_printf(SEout, "Illegal events value %d\n", events);
					exit(0);
				}
				break;
			} else {
				usage();
				exit(0);
			}
			break;
		case 'r':
			replay= 1;
			break;
		case 's':
			if (strcmp(long_options[option_index].name, "sensor") == 0) {
				sensor = optarg;
				break;
			}
			if (strcmp(long_options[option_index].name, "server") == 0) {
				server = 1;
				break;
			} else {
				usage();
				exit(0);
			}
			break;
		case 'p':
			if (strcmp(long_options[option_index].name, "protocol") == 0) {
				char *name= optarg? optarg: "xyz";
				if (strcmp(name, "TCP") == 0 || strcmp(name, "tcp") == 0) {
					protocol = TCP;
					break;
				}
				if (strcmp(name, "UDP") == 0 || strcmp(name, "udp") == 0) {
					protocol = UDP;
					break;
				}
				if (strcmp(name, "CSV") == 0 || strcmp(name, "csv") == 0) {
					protocol = CSV;
					break;
				}
				if (strcmp(name, "debug") == 0) {
					protocol = DEB;
					break;
				}
			}
			if (strcmp(long_options[option_index].name, "port") == 0) {
				port = optarg ? atol(optarg) : -1;
#ifdef SENSOR_DEBUG
				mnstr_printf(SEout, "#PORT : %d\n", port);
#endif
				break;
			} else {
				usage();
				exit(0);
			}
			break;
		case 'h':
			host = optarg;
			break;
		case '?':
		default:
			usage();
			exit(0);
		}
	}


	signal(SIGABRT, stopSend);
#ifdef SIGPIPE
	signal(SIGPIPE, stopSend);
#endif
#ifdef SIGHUP
	signal(SIGHUP, stopSend);
#endif
	signal(SIGTERM, stopSend);
	signal(SIGINT, stopSend);

	/* display properties */
	if (trace) {
		mnstr_printf(SEout, "--host=%s\n", host);
		mnstr_printf(SEout, "--port=%d\n", port);
		mnstr_printf(SEout, "--sensor=%s\n", sensor);
		mnstr_printf(SEout, "--columns=%d\n", columns);
		mnstr_printf(SEout, "--autoincrement=%d\n", autoincrement);
		mnstr_printf(SEout, "--timestamp=%d\n", timestamp);
		mnstr_printf(SEout, "--time=%d\n", timecolumn);
		mnstr_printf(SEout, "--events=%d\n", events);
		mnstr_printf(SEout, "--batch=%d\n", batchsize);
		mnstr_printf(SEout, "--replay=%d\n", replay);
		mnstr_printf(SEout, "--delay=%d\n", delay);
		mnstr_printf(SEout, "--protocol %s\n", protocolname[protocol]);
		mnstr_printf(SEout, "--trace=%d\n", trace);
		mnstr_printf(SEout, "--server=%d\n", server);
		mnstr_printf(SEout, "--client=%d\n", server);
		if (datafile)
			mnstr_printf(SEout, "--input=%s\n", datafile);
	}
	estimateOverhead();
	strncpy(hostname, host, 1024);
	if (strcmp(host, "localhost") == 0)
		gethostname(hostname, 1024);
	host = hostname;

	/*
	 * We limit the protocols for the time being to what can be
	 * considered a safe method.
	 */
	if (protocol == DEB) {
		/* save event stream in a file */
		Sensor se = SEnew(sensor);
		if (events == -1 || batchsize != 1) {
			printf("Provide an event limit using --events=<nr> and --batch=1\n");
			return 0;
		}
		if (datafile)
			se->toServer = open_wastream(datafile);
		else
			se->toServer = file_wastream(stdout, "stdout");
		produceStream(se);
	}
	if (protocol == UDP) {
		Sensor se = SEnew(sensor);
		se->toServer = udp_wastream(host, port, sensor);
		if (se->toServer == NULL) {
			perror("Sensor: Could not open stream");
			mnstr_printf(SEout, "#stream %s.%d.%s\n", host, port, sensor);
			return 0;
		}
		produceStream(se);
	}
	if (protocol == TCP) {
		if (server && (err = socket_server_connect(&sockfd, port))) {
			mnstr_printf(SEout, "#SENSOR:start server:%s\n", err);
			return 0;
		}
		do {
			int createThread = 0;
			snprintf(name, MYBUFSIZ - (strlen(sensor) + sizeof(j)), "%s%d", sensor, j++);

			se = SEnew(name);
			name[0] = 0;
			err = NULL;
			if (server) {
#ifdef SENSOR_DEBUG
				mnstr_printf(SEout, "#listen %s as server is %d \n", se->name, server);
#endif
				err = socket_server_listen(sockfd, &(se->newsockfd));
				if (err) {
					mnstr_printf(SEout, "#SENSOR:server listen:%s\n", err);
					break;
				}
			} else {
#ifdef SENSOR_DEBUG
				mnstr_printf(SEout, "#%s is client \n", se->name);
#endif
				err = socket_client_connect(&(se->newsockfd), host, port);
				if (err) {
					mnstr_printf(SEout, "#SENSOR:client start:%s\n", err);
					break;
				}
			}
			se->toServer = socket_wastream(se->newsockfd, se->name);
			if (se->toServer == NULL) {
				perror("Sensor: Could not open stream");
				mnstr_printf(SEout, "#stream %s.%d.%s\n", host, port, sensor);
				socket_close(se->newsockfd);
				return 0;
			}
			if (server) {
				createThread = MT_create_thread(&pid, (void (*)(void *))produceServerStream, se, MT_THR_DETACHED);
#ifdef SENSOR_DEBUG
				if (createThread)
					mnstr_printf(SEout, "#Create thread is : %d \n", createThread);
#else
				(void) createThread;
#endif
			} else { /* client part */
				produceServerStream(se);
			}
		} while (server);
		if (server)
			socket_close(sockfd);

		if (se)
			shutdown(se->newsockfd, SHUT_RDWR);
	}
	return 0;
}