diff --git a/include/proto/listener.h b/include/proto/listener.h index 0ad0beb8c..7fdb1cfad 100644 --- a/include/proto/listener.h +++ b/include/proto/listener.h @@ -78,6 +78,17 @@ int unbind_listener_no_close(struct listener *listener); */ int unbind_all_listeners(struct protocol *proto); + +/* creates one or multiple listeners for bind_conf on sockaddr on port + * range to , and possibly attached to fd (or -1 for auto + * allocation). The address family is taken from ss->ss_family. The number of + * jobs and listeners is automatically increased by the number of listeners + * created. It returns non-zero on success, zero on error with the error message + * set in . + */ +int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss, + int portl, int porth, int fd, char **err); + /* Delete a listener from its protocol's list of listeners. The listener's * state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's * number of listeners is updated. Note that the listener must have previously diff --git a/src/cfgparse.c b/src/cfgparse.c index 759d40759..9b91b9048 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -220,14 +220,13 @@ static struct cfg_kw_list cfg_keywords = { */ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err) { - struct listener *l; char *next, *dupstr; int port, end; next = dupstr = strdup(str); while (next && *next) { - struct sockaddr_storage ss, *ss2; + struct sockaddr_storage *ss2; int fd = -1; str = next; @@ -283,31 +282,10 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, } /* OK the address looks correct */ - memcpy(&ss, ss2, sizeof(ss)); - - for (; port <= end; port++) { - struct protocol *proto = protocol_by_family(ss.ss_family); - - if (!proto) { - memprintf(err, "unsupported protocol family %d for address '%s'.\n", ss.ss_family, str); - goto fail; - } - - l = calloc(1, sizeof(*l)); - l->obj_type = OBJ_TYPE_LISTENER; - LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe); - LIST_ADDQ(&bind_conf->listeners, &l->by_bind); - l->bind_conf = bind_conf; - - l->fd = fd; - memcpy(&l->addr, &ss, sizeof(ss)); - l->state = LI_INIT; - - proto->add(l, port); - - jobs++; - listeners++; - } /* end for(port) */ + if (!create_listeners(bind_conf, ss2, port, end, fd, err)) { + memprintf(err, "%s for address '%s'.\n", *err, str); + goto fail; + } } /* end while(next) */ free(dupstr); return 1; diff --git a/src/listener.c b/src/listener.c index abedd2fef..47bed179e 100644 --- a/src/listener.c +++ b/src/listener.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -298,6 +299,48 @@ int unbind_all_listeners(struct protocol *proto) return ERR_NONE; } +/* creates one or multiple listeners for bind_conf on sockaddr on port + * range to , and possibly attached to fd (or -1 for auto + * allocation). The address family is taken from ss->ss_family. The number of + * jobs and listeners is automatically increased by the number of listeners + * created. It returns non-zero on success, zero on error with the error message + * set in . + */ +int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss, + int portl, int porth, int fd, char **err) +{ + struct protocol *proto = protocol_by_family(ss->ss_family); + struct listener *l; + int port; + + if (!proto) { + memprintf(err, "unsupported protocol family %d", ss->ss_family); + return 0; + } + + for (port = portl; port <= porth; port++) { + l = calloc(1, sizeof(*l)); + if (!l) { + memprintf(err, "out of memory"); + return 0; + } + l->obj_type = OBJ_TYPE_LISTENER; + LIST_ADDQ(&bc->frontend->conf.listeners, &l->by_fe); + LIST_ADDQ(&bc->listeners, &l->by_bind); + l->bind_conf = bc; + + l->fd = fd; + memcpy(&l->addr, ss, sizeof(*ss)); + l->state = LI_INIT; + + proto->add(l, port); + + jobs++; + listeners++; + } + return 1; +} + /* Delete a listener from its protocol's list of listeners. The listener's * state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's * number of listeners is updated. Note that the listener must have previously