Example #1
0
static int net_socket_udp_init(NetClientState *peer,
                                 const char *model,
                                 const char *name,
                                 const char *rhost,
                                 const char *lhost)
{
    NetSocketState *s;
    int fd, val, ret;
    struct sockaddr_in laddr, raddr;

    if (parse_host_port(&laddr, lhost) < 0) {
        return -1;
    }

    if (parse_host_port(&raddr, rhost) < 0) {
        return -1;
    }

    fd = qemu_socket(PF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        perror("socket(PF_INET, SOCK_DGRAM)");
        return -1;
    }
    val = 1;
    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                   (const char *)&val, sizeof(val));
    if (ret < 0) {
        perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
        closesocket(fd);
        return -1;
    }
    ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
    if (ret < 0) {
        perror("bind");
        closesocket(fd);
        return -1;
    }

    s = net_socket_fd_init(peer, model, name, fd, 0);
    if (!s) {
        return -1;
    }

    s->dgram_dst = raddr;

    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
             "socket: udp=%s:%d",
             inet_ntoa(raddr.sin_addr), ntohs(raddr.sin_port));
    return 0;
}
int tcp_start_incoming_migration(const char *host_port)
{
    struct sockaddr_in addr;
    int val;
    int s;

    if (parse_host_port(&addr, host_port) < 0) {
        fprintf(stderr, "invalid host/port combination: %s\n", host_port);
        return -EINVAL;
    }

    s = socket(PF_INET, SOCK_STREAM, 0);
    if (s == -1)
        return -socket_error();

    val = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));

    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
        goto err;

    if (listen(s, 1) == -1)
        goto err;

    qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
                         (void *)(unsigned long)s);

    return 0;

err:
    close(s);
    return -socket_error();
}
int tcp_start_incoming_migration(const char *host_port)
{
    SockAddress addr;
    int s;

    if (parse_host_port(&addr, host_port) < 0) {
        fprintf(stderr, "invalid host/port combination: %s\n", host_port);
        return -EINVAL;
    }

    s = socket_create_inet(SOCKET_STREAM);
    if (s == -1)
        return -socket_error();

    socket_set_xreuseaddr(s);

    if (socket_bind(s, &addr) == -1)
        goto err;

    if (socket_listen(s, 1) == -1)
        goto err;

    qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
                         (void *)(unsigned long)s);

    return 0;

err:
    socket_close(s);
    return -socket_error();
}
Example #4
0
MigrationState *tcp_start_outgoing_migration(const char *host_port,
                                             int64_t bandwidth_limit,
                                             int detach,
					     int blk,
					     int inc)
{
    struct sockaddr_in addr;
    FdMigrationState *s;
    int ret;

    if (parse_host_port(&addr, host_port) < 0)
        return NULL;

    s = qemu_mallocz(sizeof(*s));

    s->get_error = socket_errno;
    s->write = socket_write;
    s->close = tcp_close;
    s->mig_state.cancel = migrate_fd_cancel;
    s->mig_state.get_status = migrate_fd_get_status;
    s->mig_state.release = migrate_fd_release;

    s->mig_state.blk = blk;
    s->mig_state.shared = inc;

    s->state = MIG_STATE_ACTIVE;
    s->mon_resume = NULL;
    s->bandwidth_limit = bandwidth_limit;
    s->fd = socket(PF_INET, SOCK_STREAM, 0);
    if (s->fd == -1) {
        qemu_free(s);
        return NULL;
    }

    socket_set_nonblock(s->fd);

    if (!detach)
        migrate_fd_monitor_suspend(s);

    do {
        ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
        if (ret == -1)
            ret = -(s->get_error(s));

        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
            qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
    } while (ret == -EINTR);

    if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
        dprintf("connect failed\n");
        close(s->fd);
        qemu_free(s);
        return NULL;
    } else if (ret >= 0)
        migrate_fd_connect(s);

    return &s->mig_state;
}
MigrationState *tcp_start_outgoing_migration(const char *host_port,
                                             int64_t bandwidth_limit,
                                             int detach)
{
    SockAddress  addr;
    FdMigrationState *s;
    int ret;

    if (parse_host_port(&addr, host_port) < 0)
        return NULL;

    s = g_malloc0(sizeof(*s));

    s->get_error = socket_errno;
    s->write = socket_write;
    s->close = tcp_close;
    s->mig_state.cancel = migrate_fd_cancel;
    s->mig_state.get_status = migrate_fd_get_status;
    s->mig_state.release = migrate_fd_release;

    s->state = MIG_STATE_ACTIVE;
    s->mon_resume = NULL;
    s->bandwidth_limit = bandwidth_limit;
    s->fd = socket_create_inet(SOCKET_STREAM);
    if (s->fd == -1) {
        g_free(s);
        return NULL;
    }

    socket_set_nonblock(s->fd);

    if (!detach)
        migrate_fd_monitor_suspend(s);

    do {
        ret = socket_connect(s->fd, &addr);
        if (ret == -1)
            ret = -(s->get_error(s));

        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK || ret == -EAGAIN)
            qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
    } while (ret == -EINTR);

    if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK && ret != -EAGAIN) {
        dprintf("connect failed\n");
        socket_close(s->fd);
        g_free(s);
        return NULL;
    } else if (ret >= 0)
        migrate_fd_connect(s);

    return &s->mig_state;
}
Example #6
0
static int net_socket_connect_init(NetClientState *peer,
                                   const char *model,
                                   const char *name,
                                   const char *host_str)
{
    NetSocketState *s;
    int fd, connected, ret, err;
    struct sockaddr_in saddr;

    if (parse_host_port(&saddr, host_str) < 0)
        return -1;

    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        return -1;
    }
    socket_set_nonblock(fd);

    connected = 0;
    for(;;) {
        ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
        if (ret < 0) {
            err = socket_error();
            if (err == EINTR || err == EWOULDBLOCK) {
            } else if (err == EINPROGRESS) {
                break;
#ifdef _WIN32
            } else if (err == WSAEALREADY || err == WSAEINVAL) {
                break;
#endif
            } else {
                perror("connect");
                closesocket(fd);
                return -1;
            }
        } else {
            connected = 1;
            break;
        }
    }
    s = net_socket_fd_init(peer, model, name, fd, connected);
    if (!s)
        return -1;
    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
             "socket: connect to %s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;
}
Example #7
0
static int net_socket_listen_init(VLANState *vlan,
                                  const char *model,
                                  const char *name,
                                  const char *host_str)
{
    NetSocketListenState *s;
    int fd, val, ret;
    struct sockaddr_in saddr;

    if (parse_host_port(&saddr, host_str) < 0)
        return -1;

    s = g_malloc0(sizeof(NetSocketListenState));

    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        g_free(s);
        return -1;
    }
    socket_set_nonblock(fd);

    /* allow fast reuse */
    val = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));

    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret < 0) {
        perror("bind");
        g_free(s);
        closesocket(fd);
        return -1;
    }
    ret = listen(fd, 0);
    if (ret < 0) {
        perror("listen");
        g_free(s);
        closesocket(fd);
        return -1;
    }
    s->vlan = vlan;
    s->model = g_strdup(model);
    s->name = name ? g_strdup(name) : NULL;
    s->fd = fd;
    qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
    return 0;
}
Example #8
0
static int net_socket_listen_init(NetClientState *peer,
                                  const char *model,
                                  const char *name,
                                  const char *host_str)
{
    NetClientState *nc;
    NetSocketState *s;
    struct sockaddr_in saddr;
    int fd, val, ret;

    if (parse_host_port(&saddr, host_str) < 0)
        return -1;

    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        return -1;
    }
    socket_set_nonblock(fd);

    /* allow fast reuse */
    val = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));

    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret < 0) {
        perror("bind");
        closesocket(fd);
        return -1;
    }
    ret = listen(fd, 0);
    if (ret < 0) {
        perror("listen");
        closesocket(fd);
        return -1;
    }

    nc = qemu_new_net_client(&net_socket_info, peer, model, name);
    s = DO_UPCAST(NetSocketState, nc, nc);
    s->fd = -1;
    s->listen_fd = fd;
    s->nc.link_down = true;

    qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
    return 0;
}
 virtual int connectclientsocket() {
   if (remoteaddr.size()) {
     addrinfo* ret = parse_host_port(remoteaddr);
     for (addrinfo* res = ret; res; res = res->ai_next) {
       int clientsock = ::socket(res->ai_family,res->ai_socktype,res->ai_protocol);
       SOCK_ERRORCHECK(clientsock,"socket");
       int rc = ::connect(clientsock,res->ai_addr,res->ai_addrlen);
       SOCK_ERRORCHECK(rc,"connect");
       freeaddrinfo(ret);
       return clientsock;
     }
     MAKESURE(false,"cannot resolve host port");
     return -1;
   } else {
     return SendPerfTest::connectclientsocket();
   }
 }
Example #10
0
parsed_url* parse_url( const char* url, void* usermem, size_t mem_size )
{
	void* mem = usermem;
	if( mem == 0x0 )
	{
		mem_size = parse_url_calc_mem_usage( url );
		mem = malloc( mem_size );
	}

	parse_url_ctx ctx = { mem, mem_size, mem_size };

	parsed_url* out = (parsed_url*)alloc_mem( &ctx, sizeof( parsed_url ) );
	URL_PARSE_FAIL_IF( out == 0x0 );

	url = parse_scheme( url, &ctx, out );    URL_PARSE_FAIL_IF( url == 0x0 );
	url = parse_user_pass( url, &ctx, out ); URL_PARSE_FAIL_IF( url == 0x0 );
	url = parse_host_port( url, &ctx, out ); URL_PARSE_FAIL_IF( url == 0x0 );
	
	return out;
}
Example #11
0
static int net_socket_mcast_init(NetClientState *peer,
                                 const char *model,
                                 const char *name,
                                 const char *host_str,
                                 const char *localaddr_str)
{
    NetSocketState *s;
    int fd;
    struct sockaddr_in saddr;
    struct in_addr localaddr, *param_localaddr;

    if (parse_host_port(&saddr, host_str) < 0)
        return -1;

    if (localaddr_str != NULL) {
        if (inet_aton(localaddr_str, &localaddr) == 0)
            return -1;
        param_localaddr = &localaddr;
    } else {
        param_localaddr = NULL;
    }

    fd = net_socket_mcast_create(&saddr, param_localaddr);
    if (fd < 0)
        return -1;

    s = net_socket_fd_init(peer, model, name, fd, 0);
    if (!s)
        return -1;

    s->dgram_dst = saddr;

    snprintf(s->nc.info_str, sizeof(s->nc.info_str),
             "socket: mcast=%s:%d",
             inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
    return 0;

}
Example #12
0
/*
 * forward_to_server - forward the http request to server
 *
 * this function is little bit long since it handles both GET and
 * non GET methods;
 *
 * it is hard to refactor since many variables need to be passed
 *
 * return -1 when all kinds of error
 * return 0 for GET method
 * return 1 when cache hit (not forward to server)
 * return 2 for non GET method
 */
int forward_to_server(int fd, int *to_server_fd, char *cache_id,
                      void *cache_content, unsigned int *cache_length) {
    char buf[MAXLINE], request_buf[MAXLINE];
    char method[MAXLINE], protocol[MAXLINE];
    char host_port[MAXLINE];
    char remote_host[MAXLINE], remote_port[MAXLINE], resource[MAXLINE];
    char version[MAXLINE];
    char origin_request_line[MAXLINE];
    char origin_host_header[MAXLINE];

    int has_user_agent_str = 0, has_accept_str = 0,
        has_accept_encoding_str = 0,
        has_connection_str = 0, has_proxy_connection_str = 0,
        has_host_str = 0;

    rio_t rio_client;

    strcpy(remote_host, "");
    strcpy(remote_port, "80");
    memset(cache_content, 0, MAX_OBJECT_SIZE);

    Rio_readinitb(&rio_client, fd);
    if (Rio_readlineb(&rio_client, buf, MAXLINE) == -1) {
        return -1;
    }
    // used incase dns lookup failed
    strcpy(origin_request_line, buf);

    if (parse_request_line(buf, method, protocol, host_port,
                           resource, version) == -1) {
        return -1;
    }
    parse_host_port(host_port, remote_host, remote_port);

    if (strstr(method, "GET") != NULL) {
        // GET method

        // compose our request line
        strcpy(request_buf, method);
        strcat(request_buf, " ");
        strcat(request_buf, resource);
        strcat(request_buf, " ");
        strcat(request_buf, http_version_str);

        // process request header
        while (Rio_readlineb(&rio_client, buf, MAXLINE) != 0) {
            if (strcmp(buf, "\r\n") == 0) {
                break;
            } else if (strstr(buf, "User-Agent:") != NULL) {
                strcat(request_buf, user_agent_str);
                has_user_agent_str = 1;
            } else if (strstr(buf, "Accept-Encoding:") != NULL) {
                strcat(request_buf, accept_encoding_str);
                has_accept_encoding_str = 1;
            } else if (strstr(buf, "Accept:") != NULL) {
                strcat(request_buf, accept_str);
                has_accept_str = 1;
            } else if (strstr(buf, "Connection:") != NULL) {
                strcat(request_buf, connection_str);
                has_connection_str = 1;
            } else if (strstr(buf, "Proxy Connection:") != NULL) {
                strcat(request_buf, proxy_connection_str);
                has_proxy_connection_str = 1;
            } else if (strstr(buf, "Host:") != NULL) {
                strcpy(origin_host_header, buf);
                if (strlen(remote_host) < 1) {
                    // if host not specified in request line
                    // get host from host header
                    sscanf(buf, "Host: %s", host_port);
                    parse_host_port(host_port, remote_host, remote_port);
                }
                strcat(request_buf, buf);
                has_host_str = 1;
            } else {
                strcat(request_buf, buf);
            }
        }
        // if not sent, copy in out headers
        if (has_user_agent_str != 1) {
            strcat(request_buf, user_agent_str);
        }
        if (has_accept_encoding_str != 1) {
            strcat(request_buf, accept_encoding_str);
        }
        if (has_accept_str != 1) {
            strcat(request_buf, accept_str);
        }
        if (has_connection_str != 1) {
            strcat(request_buf, connection_str);
        }
        if (has_proxy_connection_str != 1) {
            strcat(request_buf, proxy_connection_str);
        }
        if (has_host_str != 1) {
            sprintf(buf, "Host: %s:%s\r\n", remote_host, remote_port);
            strcat(request_buf, buf);
        }
        strcat(request_buf, "\r\n");
        if (strcmp(remote_host, "") == 0) {
            return -1;
        }

        // compose cache id
        strcpy(cache_id, method);
        strcat(cache_id, " ");
        strcat(cache_id, remote_host);
        strcat(cache_id, ":");
        strcat(cache_id, remote_port);
        strcat(cache_id, resource);
        strcat(cache_id, " ");
        strcat(cache_id, version);

        // search in the cache
        if (read_cache_node_lru_sync(cache, cache_id, cache_content,
                                     cache_length) != -1) {
            // cache hit
            return 1;
        }

        // client to server
        *to_server_fd = Open_clientfd(remote_host, atoi(remote_port),
                                    origin_request_line, origin_host_header);
        if (*to_server_fd == -1) {
            return -1;
        } else if (*to_server_fd == -2) {
            // dns lookup failed, write our response page
            // caused by invalid host
            strcpy(buf, client_bad_request_str);
            Rio_writen(fd, buf, strlen(buf));
            return -1;
        }
        if (Rio_writen(*to_server_fd, request_buf,
                       strlen(request_buf)) == -1) {
            return -1;
        }
        return 0;
    } else {
        // non GET method
        unsigned int length = 0, size = 0;
        strcpy(request_buf, buf);
        while (strcmp(buf, "\r\n") != 0 && strlen(buf) > 0) {
            if (Rio_readlineb(&rio_client, buf, MAXLINE) == -1) {
                return -1;
            }
            if (strstr(buf, "Host:") != NULL) {
                strcpy(origin_host_header, buf);
                if (strlen(remote_host) < 1) {
                    sscanf(buf, "Host: %s", host_port);
                    parse_host_port(host_port, remote_host, remote_port);
                }
            }
            get_size(buf, &size);
            strcat(request_buf, buf);
        }
        if (strcmp(remote_host, "") == 0) {
            return -1;
        }
        *to_server_fd = Open_clientfd(remote_host, atoi(remote_port),
                                    origin_request_line, origin_host_header);
        if (*to_server_fd < 0) {
            return -1;
        }
        // write request line
        if (Rio_writen(*to_server_fd, request_buf,
                       strlen(request_buf)) == -1) {
            return -1;
        }
        // write request body
        while (size > MAXLINE) {
            if ((length = Rio_readnb(&rio_client, buf, MAXLINE)) == -1) {
                return -1;
            }
            if (Rio_writen(*to_server_fd, buf, length) == -1) {
                return -1;
            }
            size -= MAXLINE;
        }
        if (size > 0) {
            if ((length = Rio_readnb(&rio_client, buf, size)) == -1) {
                return -1;
            }
            if (Rio_writen(*to_server_fd, buf, length) == -1) {
                return -1;
            }
        }
        return 2;
    }
}
Example #13
0
int main(int argc, char *argv[])
{
    if (argc < 4)
        usage();

    char buf[256];
    int ret;

    char server_hostname[NI_MAXHOST];
    int server_port;
    int client_sock;

    Sum_State_T sum_state;
    if ( (sum_state = malloc(sizeof(*sum_state))) == NULL)
    {
        fprintf(stderr, "ERROR allocating Sum_State_T: %s\n", strerror(errno));
        exit(1);
    }

    sum_state->idx = 0;

    /* first operand begins at argv[2] */
    sum_state->max_idx = argc - 3;

    /* do we have too many operands? */
    if (sum_state->max_idx >= MAX_OPERANDS)
        usage();

    /* Convert operand arguments to numbers */
    const char *errstr;
    int i;
    for (i = 0; i <= sum_state->max_idx; i++)
    {
        sum_state->operands[i] = strtonum(argv[i+2], LLONG_MIN, LLONG_MAX, &errstr);
        if (errstr != NULL)
            usage();
    }

    /* split IP from port number */
    if (parse_host_port(argv[1], server_hostname, NI_MAXHOST, &server_port) != 0)
        usage();

/* Windows is dumb */
#ifdef WIN32
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        fprintf(stderr, "WSAStartup() failed.\n");
        exit(1);
    }
#endif

    fprintf(stderr, "Connecting to server...");
    /* Connect to server */
    if ((client_sock = connect_tcp(server_hostname, server_port, &errstr)) == -1)
    {
        fprintf(stderr, "Failed to connect: %s\n", errstr);
        return 1;
    }
    fprintf(stderr, "Done.\n");

    /* Done connecting... set up AMP Protocol */

    AMP_Proto_T *proto;
    if ( (proto = amp_new_proto()) == NULL)
    {
        fprintf(stderr, "Couldn't allocate AMP_Proto.\n");
        return 1;
    };

    amp_set_write_handler(proto, do_write, &client_sock);

    /* Set up libamp logging to stderr for any error messages that
     * it wishes to report */
    amp_set_log_handler(amp_stderr_logger);

    /* Make first call... */

    do_sum_call(proto, sum_state);

    /* Start reading loop */

    int bytesRead;
    while ( (bytesRead = recv(client_sock, buf, sizeof(buf), 0)) >= 0)
    {
        if ( (ret = amp_consume_bytes(proto, buf, bytesRead)) != 0)
        {
            fprintf(stderr, "ERROR detected by amp_consume_bytes(): %s\n", amp_strerror(ret));
            return 1;
        };
    }

    return 0;
}
Example #14
0
int ftp_command_parse(const char *input, ftp_command_t *cmd)
{
    int i;
    int len;
    int match;
    ftp_command_t tmp;
    int c;
    const char *optional_number;

    daemon_assert(input != NULL);
    daemon_assert(cmd != NULL);

    /* see if our input starts with a valid command */
    match = -1;
    for (i=0; (i<NUM_COMMAND) && (match == -1); i++) {
        len = strlen(command_def[i].name);
        if (strncasecmp(input, command_def[i].name, len) == 0) {
	    match = i;
	}
    }

    /* if we didn't find a match, return error */
    if (match == -1) {
        return 0;
    }
    daemon_assert(match >= 0);
    daemon_assert(match < NUM_COMMAND);

    /* copy our command */
    strcpy(tmp.command, command_def[match].name);

    /* advance input past the command */
    input += strlen(command_def[match].name);

    /* now act based on the command */
    switch (command_def[match].arg_type) {

        case ARG_NONE:
	    tmp.num_arg = 0;
	    break;

        case ARG_STRING:
	    if (*input != ' ') {
	        return 0;
	    }
            ++input;
            input = copy_string(tmp.arg[0].string, input);
	    tmp.num_arg = 1;
	    break;

        case ARG_OPTIONAL_STRING:
	    if (*input == ' ') {
	        ++input;
	        input = copy_string(tmp.arg[0].string, input);
	        tmp.num_arg = 1;
	    } else {
	        tmp.num_arg = 0;
	    }
	    break;

        case ARG_HOST_PORT:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            /* parse the host & port information (if any) */
	    input = parse_host_port(&tmp.arg[0].host_port, input);
	    if (input == NULL) {
	        return 0;
	    }
	    tmp.num_arg = 1;
	    break;

       case ARG_HOST_PORT_LONG:
            if (*input != ' ') {
                return 0;
            }
            input++;
 
            /* parse the host & port information (if any) */
            input = parse_host_port_long(&tmp.arg[0].host_port, input);
            if (input == NULL) {
                return 0;
            }
            tmp.num_arg = 1;
            break;    

        case ARG_HOST_PORT_EXT:
            if (*input != ' ') {
                return 0;
            }
            input++;
 
            /* parse the host & port information (if any) */
            input = parse_host_port_ext(&tmp.arg[0].host_port, input);
            if (input == NULL) {
                return 0;
            }
            tmp.num_arg = 1;
            break;
 
        /* the optional number may also be "ALL" */
        case ARG_OPTIONAL_NUMBER:
            if (*input == ' ') {
                ++input;
                optional_number = parse_number(&tmp.arg[0].num, input, 255);
                if (optional_number != NULL) {
                    input = optional_number;
                } else {
                    if ((tolower(input[0]) == 'a') &&
                        (tolower(input[1]) == 'l') &&
                        (tolower(input[2]) == 'l')) 
                    {
			tmp.arg[0].num = EPSV_ALL;
                        input += 3;
                    } else {
                        return 0;
                    }
                }
                tmp.num_arg = 1;
            } else {
                tmp.num_arg = 0;
            }
            break;     

        case ARG_TYPE:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            c = toupper(*input);
            if ((c == 'A') || (c == 'E')) {
	        tmp.arg[0].string[0] = c;
		tmp.arg[0].string[1] = '\0';
		input++;

		if (*input == ' ') {
		    input++;
		    c = toupper(*input);
		    if ((c != 'N') && (c != 'T') && (c != 'C')) {
		        return 0;
		    }
		    tmp.arg[1].string[0] = c;
		    tmp.arg[1].string[1] = '\0';
		    input++;
		    tmp.num_arg = 2;
		} else {
		    tmp.num_arg = 1;
		}
	    } else if (c == 'I') {
	        tmp.arg[0].string[0] = 'I';
	        tmp.arg[0].string[1] = '\0';
		input++;
	        tmp.num_arg = 1;
	    } else if (c == 'L') {
	        tmp.arg[0].string[0] = 'L';
	        tmp.arg[0].string[1] = '\0';
		input++;
		input = parse_number(&tmp.arg[1].num, input, 255);
		if (input == NULL) {
		    return 0;
		}
	        tmp.num_arg = 2;
	    } else {
	        return 0;
	    }

	    break;

        case ARG_STRUCTURE:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            c = toupper(*input);
	    if ((c != 'F') && (c != 'R') && (c != 'P')) {
	        return 0;
	    }
            input++;
	    tmp.arg[0].string[0] = c;
	    tmp.arg[0].string[1] = '\0';
	    tmp.num_arg = 1;
	    break;

        case ARG_MODE:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            c = toupper(*input);
	    if ((c != 'S') && (c != 'B') && (c != 'C')) {
	        return 0;
	    }
            input++;
	    tmp.arg[0].string[0] = c;
	    tmp.arg[0].string[1] = '\0';
	    tmp.num_arg = 1;
	    break;

        case ARG_OFFSET:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;
	    input = parse_offset(&tmp.arg[0].offset, input);
	    if (input == NULL) {
	        return 0;
	    }
	    tmp.num_arg = 1;
	    break;

        default:
	    daemon_assert(0);
    } 

    /* check for our ending newline */
    if (*input != '\n') {
        return 0;
    }

    /* return our result */
    *cmd = tmp;
    return 1;
}