char pidftemplate[256]; /**< template to be used for the filename of the PID file */
char default_authname[] = SYSCONFDIR "/nbd-server/allow"; /**< default name of allow file */
+#define NEG_INIT (1 << 0)
+#define NEG_OLD (1 << 1)
+#define NEG_MODERN (1 << 2)
+
int modernsock=0; /**< Socket for the modern handler. Not used
if a client was only specified on the
command line; only port used if
oldstyle is set to false (and then the
command-line client isn't used, gna gna) */
char* modern_listen; /**< listenaddr value for modernsock */
+char* modernport=NBD_DEFAULT_PORT; /**< Port number on which to listen for
+ new-style nbd-client connections */
/**
* Types of virtuatlization
"\t-p|--pid-file\t\tspecify a filename to write our PID to\n"
"\t-o|--output-config\toutput a config file section for what you\n\t\t\t\tspecified on the command line, with the\n\t\t\t\tspecified section name\n"
"\t-M|--max-connections\tspecify the maximum number of opened connections\n\n"
- "\tif port is set to 0, stdin is used (for running from inetd)\n"
+ "\tif port is set to 0, stdin is used (for running from inetd).\n"
"\tif file_to_export contains '%%s', it is substituted with the IP\n"
"\t\taddress of the machine trying to connect\n"
"\tif ip is set, it contains the local IP address on which we're listening.\n\tif not, the server will listen on all local IP addresses\n");
{ "group", FALSE, PARAM_STRING, &rungroup, 0 },
{ "oldstyle", FALSE, PARAM_BOOL, &do_oldstyle, 1 },
{ "listenaddr", FALSE, PARAM_STRING, &modern_listen, 0 },
+ { "port", FALSE, PARAM_STRING, &modernport, 0 },
};
PARAM* p=gp;
int p_size=sizeof(gp)/sizeof(PARAM);
}
break;
}
- if(!strcmp(p[j].paramname, "port") && !strcmp(p[j].target, NBD_DEFAULT_PORT)) {
- g_set_error(e, errdomain, CFILE_INCORRECT_PORT, "Config file specifies default port for oldstyle export");
+ if(!strcmp(p[j].paramname, "port") && !strcmp(p[j].target, modernport)) {
+ g_set_error(e, errdomain, CFILE_INCORRECT_PORT, "Config file specifies new-style port for oldstyle export");
g_key_file_free(cfile);
return NULL;
}
*
* @param client The client we're negotiating with.
**/
-CLIENT* negotiate(int net, CLIENT *client, GArray* servers) {
+CLIENT* negotiate(int net, CLIENT *client, GArray* servers, int phase) {
char zeros[128];
uint64_t size_host;
uint32_t flags = NBD_FLAG_HAS_FLAGS;
uint64_t magic;
memset(zeros, '\0', sizeof(zeros));
- if(!client || !client->modern) {
+ if(phase & NEG_INIT) {
/* common */
if (write(net, INIT_PASSWD, 8) < 0) {
err_nonfatal("Negotiation failed: %m");
if(client)
exit(EXIT_FAILURE);
}
- if(!client || client->modern) {
+ if(phase & NEG_MODERN) {
/* modern */
magic = htonll(opts_magic);
} else {
exit(EXIT_FAILURE);
}
}
- if(!client) {
+ if(phase & NEG_MODERN) {
/* modern */
uint32_t reserved;
uint32_t opt;
flags |= NBD_FLAG_SEND_FUA;
if (client->server->flags & F_ROTATIONAL)
flags |= NBD_FLAG_ROTATIONAL;
- if (!client->modern) {
+ if (phase & NEG_OLD) {
/* oldstyle */
flags = htonl(flags);
if (write(client->net, &flags, 4) < 0)
#ifdef DODBG
int i = 0;
#endif
- negotiate(client->net, client, NULL);
+ negotiate(client->net, client, NULL, client->modern ? NEG_MODERN : (NEG_OLD | NEG_INIT));
DEBUG("Entering request loop!\n");
reply.magic = htonl(NBD_REPLY_MAGIC);
reply.error = 0;
consume(client->net, buf, len-currlen, BUFSIZE);
continue;
}
- if (expwrite(request.from, buf, len, client,
+ if (expwrite(request.from, buf, currlen, client,
request.type & NBD_CMD_FLAG_FUA)) {
DEBUG("Write failed: %m" );
ERROR(client, reply, errno);
continue;
}
len -= currlen;
+ request.from += currlen;
currlen = (len < BUFSIZE) ? len : BUFSIZE;
}
SEND(client->net, reply);
if(FD_ISSET(modernsock, &rset)) {
if((net=accept(modernsock, (struct sockaddr *) &addrin, &addrinlen)) < 0)
err("accept: %m");
- client = negotiate(net, NULL, servers);
+ client = negotiate(net, NULL, servers, NEG_INIT | NEG_MODERN);
if(!client) {
err_nonfatal("negotiation failed");
close(net);
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
hints.ai_protocol = IPPROTO_TCP;
- e = getaddrinfo(modern_listen, NBD_DEFAULT_PORT, &hints, &ai);
+ e = getaddrinfo(modern_listen, modernport, &hints, &ai);
if(e != 0) {
fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(e));
exit(EXIT_FAILURE);