Beispiel #1
1
int
accept_listener_source_address(struct Listener *listener, char *source) {
    if (listener->source_address != NULL) {
        err("Duplicate source address: %s", source);
        return 0;
    }

    listener->source_address = new_address(source);
    if (listener->source_address == NULL) {
        err("Unable to parse source address: %s", source);
        return 0;
    }
    if (!address_is_sockaddr(listener->source_address)) {
        err("Only source socket addresses permitted");
        free(listener->source_address);
        listener->source_address = NULL;
        return 0;
    }
    if (address_port(listener->source_address) != 0) {
        char address[256];
        err("Source address on listener %s set to non zero port, "
                "this prevents multiple connection to each backend server.",
                display_address(listener->address, address, sizeof(address)));
    }

    return 1;
}
Beispiel #2
0
struct Address *
listener_lookup_server_address(const struct Listener *listener,
        const char *name, size_t name_len) {
    struct Address *new_addr = NULL;
    short set_to_fallback = 0;
    const struct Address *addr =
        table_lookup_server_address(listener->table, name, name_len);

    if (addr == NULL)
        addr = listener->fallback_address;

    if (addr == NULL)
        return NULL;

    int port = address_port(addr);

    if (address_is_wildcard(addr)) {
        new_addr = new_address(name);
        if (new_addr == NULL) {
            warn("Invalid hostname %.*s in client request",
                    (int)name_len, name);
            set_to_fallback = 1;
        } else if (address_is_sockaddr(new_addr)) {
            warn("Refusing to proxy to socket address literal %.*s in request",
                    (int)name_len, name);
            set_to_fallback = 1;
        }

        if (!set_to_fallback && port != 0)
            address_set_port(new_addr, port);
    } else {
        size_t len = address_len(addr);
        new_addr = malloc(len);
        if (new_addr == NULL) {
            err("%s: malloc", __func__);
            set_to_fallback = 1;
        }

        memcpy(new_addr, addr, len);
    }

    if (set_to_fallback) {
        size_t len = address_len(listener->fallback_address);
        new_addr = malloc(len);
        if (new_addr == NULL) {
            err("%s: malloc", __func__);
            return NULL;
        }
        memcpy(new_addr, listener->fallback_address, len);
    }
    
    if (!set_to_fallback && port == 0)
        address_set_port(new_addr, address_port(listener->address));

    return new_addr;
}
Beispiel #3
0
int
init_listener(struct Listener *listener, const struct Table_head *tables) {
    int sockfd;
    int on = 1;

    listener->table = table_lookup(tables, listener->table_name);
    if (listener->table == NULL) {
        fprintf(stderr, "Table \"%s\" not defined\n", listener->table_name);
        return -1;
    }
    init_table(listener->table);

    /* If no port was specified on the fallback address, inherit the address
     * from the listening address */
    if (listener->fallback_address &&
            address_port(listener->fallback_address) == 0)
        address_set_port(listener->fallback_address,
                address_port(listener->address));

    sockfd = socket(address_sa(listener->address)->sa_family, SOCK_STREAM, 0);
    if (sockfd < 0) {
        err("socket failed: %s", strerror(errno));
        return -2;
    }

    /* set SO_REUSEADDR on server socket to facilitate restart */
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    if (bind(sockfd, address_sa(listener->address),
                address_sa_len(listener->address)) < 0) {
        err("bind failed: %s", strerror(errno));
        close(sockfd);
        return -3;
    }

    if (listen(sockfd, SOMAXCONN) < 0) {
        err("listen failed: %s", strerror(errno));
        close(sockfd);
        return -4;
    }

    struct ev_io *listener_watcher = &listener->watcher;
    ev_io_init(listener_watcher, accept_cb, sockfd, EV_READ);
    listener->watcher.data = listener;

    ev_io_start(EV_DEFAULT, listener_watcher);

    return sockfd;
}
Beispiel #4
0
int
accept_backend_arg(struct Backend *backend, const char *arg) {
    if (backend->pattern == NULL) {
        backend->pattern = strdup(arg);
        if (backend->pattern == NULL) {
            err("strdup failed");
            return -1;
        }
    } else if (backend->address == NULL) {

        backend->address = new_address(arg);
        if (backend->address == NULL) {
            err("invalid address: %s", arg);
            return -1;
        }
#ifndef HAVE_LIBUDNS
        if (!address_is_sockaddr(backend->address)) {
            err("Only socket address backends are permitted when compiled without libudns");
            return -1;
        }
#endif
    } else if (address_port(backend->address) == 0 && is_numeric(arg)) {
        address_set_port(backend->address, atoi(arg));
    } else {
        err("Unexpected table backend argument: %s", arg);
        return -1;
    }

    return 1;
}
Beispiel #5
0
int
accept_backend_arg(struct Backend *backend, char *arg) {
    if (backend->name == NULL) {
        backend->name = strdup(arg);
        if (backend->name == NULL) {
            err("strdup failed");
            return -1;
        }
    } else if (backend->address == NULL) {
        /* Store address in lower case */
        for (char *c = arg; *c != '\0'; c++)
            *c = tolower(*c);

        backend->address = new_address(arg);
        if (backend->address == NULL) {
            err("invalid address: %s", arg);
            return -1;
        }
#ifndef HAVE_LIBUDNS
        if (!address_is_sockaddr(backend->address)) {
            err("Only socket address backends are permitted when compiled without libudns");
            return -1;
        }
#endif
    } else if (address_port(backend->address) == 0 && is_numeric(arg)) {
        address_set_port(backend->address, atoi(arg));
    } else {
        err("Unexpected table backend argument: %s", arg);
        return -1;
    }

    return 1;
}
Beispiel #6
0
int
accept_listener_arg(struct Listener *listener, char *arg) {
    if (listener->address == NULL && !is_numeric(arg)) {
        listener->address = new_address(arg);

        if (listener->address == NULL ||
                !address_is_sockaddr(listener->address)) {
            fprintf(stderr, "Invalid listener argument %s\n", arg);
            return -1;
        }
    } else if (listener->address == NULL && is_numeric(arg)) {
        listener->address = new_address("[::]");

        if (listener->address == NULL ||
                !address_is_sockaddr(listener->address)) {
            fprintf(stderr, "Unable to initialize default address\n");
            return -1;
        }

        address_set_port(listener->address, atoi(arg));
    } else if (address_port(listener->address) == 0 && is_numeric(arg)) {
        address_set_port(listener->address, atoi(arg));
    } else {
        fprintf(stderr, "Invalid listener argument %s\n", arg);
    }

    return 1;
}
Beispiel #7
0
int
valid_listener(const struct Listener *listener) {
    if (listener->address == NULL) {
        fprintf(stderr, "No address specified\n");
        return 0;
    }

    if (!address_is_sockaddr(listener->address)) {
        fprintf(stderr, "Address not specified as IP/socket\n");
        return 0;
    }

    switch (address_sa(listener->address)->sa_family) {
        case AF_UNIX:
            break;
        case AF_INET:
            /* fall through */
        case AF_INET6:
            if (address_port(listener->address) == 0) {
                fprintf(stderr, "No port specified\n");
                return 0;
            }
            break;
        default:
            fprintf(stderr, "Invalid address family\n");
            return 0;
    }

    if (listener->protocol != tls_protocol && listener->protocol != http_protocol) {
        fprintf(stderr, "Invalid protocol\n");
        return 0;
    }

    return 1;
}
Beispiel #8
0
int
accept_backend_arg(struct Backend *backend, char *arg) {
    if (backend->hostname == NULL) {
        backend->hostname = strdup(arg);
        if (backend->hostname == NULL) {
            err("strdup failed");
            return -1;
        }
    } else if (backend->address == NULL) {
        /* Store address in lower case */
        for (char *c = arg; *c == '\0'; c++)
            *c = tolower(*c);

        backend->address = new_address(arg);
        if (backend->address == NULL) {
            err("invalid address: %s\n", arg);
            return -1;
        }
    } else if (address_port(backend->address) == 0 && is_numeric(arg)) {
        address_set_port(backend->address, atoi(arg));
    } else {
        err("Unexpected table backend argument: %s\n", arg);
        return -1;
    }

    return 1;
}
Beispiel #9
0
struct Address *
listener_lookup_server_address(const struct Listener *listener,
        const char *name, size_t name_len) {
    struct Address *new_addr = NULL;
    const struct Address *addr =
        table_lookup_server_address(listener->table, name, name_len);

    if (addr == NULL)
        addr = listener->fallback_address;

    if (addr == NULL)
        return NULL;

    int port = address_port(addr);

    if (address_is_wildcard(addr)) {
        new_addr = new_address(name);
        if (new_addr == NULL) {
            warn("Invalid hostname %.*s", (int)name_len, name);

            return listener->fallback_address;
        }

        if (port != 0)
            address_set_port(new_addr, port);
    } else {
        size_t len = address_len(addr);
        new_addr = malloc(len);
        if (new_addr == NULL) {
            err("%s: malloc", __func__);

            return listener->fallback_address;
        }

        memcpy(new_addr, addr, len);
    }

    if (port == 0)
        address_set_port(new_addr, address_port(listener->address));

    return new_addr;
}
Beispiel #10
0
int main() {
    /* using volatile variables so we can example core dumps */
    struct Address *addr;
    char buffer[255];
    int port;

    for (volatile unsigned int i = 0; i < sizeof(good) / sizeof(struct Test); i++) {
        addr = new_address(good[i].input);

        assert(addr != NULL);

        if (good[i].expected_type & TYPE_HOSTNAME && !address_is_hostname(addr)) {
            fprintf(stderr, "Expected %s to be a hostname\n", buffer);
            return 1;
        }

        if (good[i].expected_type & TYPE_SOCKADDR && !address_is_sockaddr(addr)) {
            fprintf(stderr, "Expected %s to be a sockaddr\n", buffer);
            return 1;
        }

        if (good[i].expected_type & TYPE_WILDCARD && !address_is_wildcard(addr)) {
            fprintf(stderr, "Expected %s to be a wildcard\n", buffer);
            return 1;
        }

        display_address(addr, buffer, sizeof(buffer));

        if (strcmp(buffer, good[i].output)) {
            fprintf(stderr, "display_address(%p) returned \"%s\", expected \"%s\"\n", addr, buffer, good[i].output);
            return 1;
        }

        port = address_port(addr);

        if (good[i].port != port) {
            fprintf(stderr, "address_port(%p) return %d, expected %d\n", addr, port, good[i].port);
            return 1;
        }

        free(addr);
    }

    for (volatile unsigned int i = 0; i < sizeof(bad) / sizeof(const char *); i++) {
        addr = new_address(bad[i]);

        if (addr != NULL) {
            fprintf(stderr, "Accepted bad hostname \"%s\"\n", bad[i]);
            return 1;
        }
    }

    return 0;
}
Beispiel #11
0
int
accept_listener_protocol(struct Listener *listener, char *protocol) {
    if (strncasecmp(protocol, http_protocol->name, strlen(protocol)) == 0)
        listener->protocol = http_protocol;
    else
        listener->protocol = tls_protocol;

    if (address_port(listener->address) == 0)
        address_set_port(listener->address, listener->protocol->default_port);

    return 1;
}
Beispiel #12
0
static int
lconnect(lua_State *L) {
	size_t sz = 0;
	const char * addr = luaL_checklstring(L,1,&sz);
	char tmp[sz];
	int port = 0;
	const char * host = address_port(L, tmp, addr, 2, &port);
	if (port == 0) {
		return luaL_error(L, "Invalid port");
	}
	struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
	int id = skynet_socket_connect(ctx, host, port);
	lua_pushinteger(L, id);

	return 1;
}
Beispiel #13
0
static int
ludp_connect(lua_State *L) {
	struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
	int id = luaL_checkinteger(L, 1);
	size_t sz = 0;
	const char * addr = luaL_checklstring(L,2,&sz);
	char tmp[sz];
	int port = 0;
	const char * host = NULL;
	if (addr) {
		host = address_port(L, tmp, addr, 3, &port);
	}

	if (skynet_socket_udp_connect(ctx, id, host, port)) {
		return luaL_error(L, "udp connect failed");
	}

	return 0;
}
Beispiel #14
0
static int
ludp(lua_State *L) {
	struct skynet_context * ctx = lua_touserdata(L, lua_upvalueindex(1));
	size_t sz = 0;
	const char * addr = lua_tolstring(L,1,&sz);
	char tmp[sz];
	int port = 0;
	const char * host = NULL;
	if (addr) {
		host = address_port(L, tmp, addr, 2, &port);
	}

	int id = skynet_socket_udp(ctx, host, port);
	if (id < 0) {
		return luaL_error(L, "udp init failed");
	}
	lua_pushinteger(L, id);
	return 1;
}
Beispiel #15
0
int main() {
    /* using volatile variables so we can example core dumps */
    for (volatile unsigned int i = 0; i < sizeof(good) / sizeof(struct Test); i++) {
        int port;
        char buffer[255];
        struct Address *addr = new_address(good[i].input);

        assert(addr != NULL);
        assert(address_compare(addr, addr) == 0);
        assert(address_compare(NULL, addr) < 0);
        assert(address_compare(addr, NULL) > 0);
        assert(address_len(addr) > 0);

        if (good[i].expected_type & TYPE_HOSTNAME) {
            assert(address_is_hostname(addr));
            assert(!address_is_sockaddr(addr));
            assert(!address_is_wildcard(addr));
            assert(address_hostname(addr) != NULL);
            assert(address_sa(addr) == NULL);
            assert(address_sa_len(addr) == 0);
        } else if (good[i].expected_type & TYPE_SOCKADDR) {
            assert(!address_is_hostname(addr));
            assert(address_is_sockaddr(addr));
            assert(!address_is_wildcard(addr));
            assert(address_hostname(addr) == NULL);
            assert(address_sa(addr) != NULL);
            assert(address_sa_len(addr) > 0);
        } else if (good[i].expected_type & TYPE_WILDCARD) {
            assert(!address_is_hostname(addr));
            assert(!address_is_sockaddr(addr));
            assert(address_is_wildcard(addr));
            assert(address_hostname(addr) == NULL);
            assert(address_sa(addr) == NULL);
            assert(address_sa_len(addr) == 0);
        }

        display_address(addr, buffer, sizeof(buffer));

        if (strcmp(buffer, good[i].output)) {
            fprintf(stderr, "display_address(%p) returned \"%s\", expected \"%s\"\n", addr, buffer, good[i].output);
            return 1;
        }

        assert(display_address(addr, NULL, 0) == NULL);

        port = address_port(addr);

        if (good[i].port != port) {
            fprintf(stderr, "address_port(%p) return %d, expected %d\n", addr, port, good[i].port);
            return 1;
        }

        address_set_port(addr, port);

        if (good[i].port != port) {
            fprintf(stderr, "address_port(%p) return %d, expected %d\n", addr, port, good[i].port);
            return 1;
        }

        free(addr);
    }

    for (volatile unsigned int i = 0; i < sizeof(bad) / sizeof(const char *); i++) {
        struct Address *addr = new_address(bad[i]);

        if (addr != NULL) {
            fprintf(stderr, "Accepted bad hostname \"%s\"\n", bad[i]);
            return 1;
        }
    }

    assert(compare_address_strings("unix:/dev/log", "127.0.0.1") < 0);
    assert(compare_address_strings("unix:/dev/log", "unix:/dev/logsocket") < 0);
    assert(compare_address_strings("0.0.0.0", "127.0.0.1") < 0);
    assert(compare_address_strings("127.0.0.1", "0.0.0.0") > 0);
    assert(compare_address_strings("127.0.0.1", "127.0.0.1") == 0);
    assert(compare_address_strings("127.0.0.1:80", "127.0.0.1:81") < 0);
    assert(compare_address_strings("*:80", "*:81") < 0);
    assert(compare_address_strings("*:81", "*:80") > 0);
    assert(compare_address_strings("example.com", "example.net") < 0);
    assert(compare_address_strings("example.net", "example.com") > 0);
    assert(compare_address_strings("example.com", "example.com.net") < 0);
    assert(compare_address_strings("example.com.net", "example.com") > 0);
    assert(compare_address_strings("example.com", "example.com:80") < 0);
    assert(compare_address_strings("example.com:80", "example.com") > 0);
    assert(compare_address_strings(NULL, "example.com") < 0);
    assert(compare_address_strings("example.com", NULL) > 0);
    assert(compare_address_strings("example.com", "::") < 0);
    assert(compare_address_strings("::", "example.com") > 0);
    assert(compare_address_strings("0.0.0.0", "*") < 0);
    assert(compare_address_strings("*", "0.0.0.0") > 0);

    do {
        struct Address *addr = new_address("*");

        assert(addr != NULL);
        assert(address_len(addr) > 0);

        free(addr);
    } while (0);

    return 0;
}
Beispiel #16
0
static int
init_listener(struct Listener *listener, const struct Table_head *tables, struct ev_loop *loop) {
    struct Table *table = table_lookup(tables, listener->table_name);
    if (table == NULL) {
        err("Table \"%s\" not defined", listener->table_name);
        return -1;
    }
    init_table(table);
    listener->table = table_ref_get(table);

    /* If no port was specified on the fallback address, inherit the address
     * from the listening address */
    if (listener->fallback_address &&
            address_port(listener->fallback_address) == 0)
        address_set_port(listener->fallback_address,
                address_port(listener->address));

    int sockfd = socket(address_sa(listener->address)->sa_family, SOCK_STREAM, 0);
    if (sockfd < 0) {
        err("socket failed: %s", strerror(errno));
        return -2;
    }

    /* set SO_REUSEADDR on server socket to facilitate restart */
    int on = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    int result = bind(sockfd, address_sa(listener->address),
            address_sa_len(listener->address));
    if (result < 0 && errno == EACCES) {
        /* Retry using binder module */
        close(sockfd);
        sockfd = bind_socket(address_sa(listener->address),
                address_sa_len(listener->address));
        if (sockfd < 0) {
            char address[128];
            err("binder failed to bind to %s",
                display_address(listener->address, address, sizeof(address)));
            close(sockfd);
            return -3;
        }
    } else if (result < 0) {
        char address[128];
        err("bind %s failed: %s",
            display_address(listener->address, address, sizeof(address)),
            strerror(errno));
        close(sockfd);
        return -3;
    }

    if (listen(sockfd, SOMAXCONN) < 0) {
        err("listen failed: %s", strerror(errno));
        close(sockfd);
        return -4;
    }


    int flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    listener_ref_get(listener);
    ev_io_init(&listener->watcher, accept_cb, sockfd, EV_READ);
    listener->watcher.data = listener;
    listener->backoff_timer.data = listener;

    ev_io_start(loop, &listener->watcher);

    return sockfd;
}