haproxy/src/cfgparse-unix.c
Willy Tarreau 6e459d7f92 MINOR: listener: create a new struct "settings" in bind_conf
There currently is a large inconsistency in how binding parameters are
split between bind_conf and listeners. It happens that for historical
reasons some parameters are available at the listener level but cannot
be configured per-listener but only for a bind_conf, and thus, need to
be replicated. In addition, some of the bind_conf parameters are in fact
for the listening socket itself while others are for the instanciated
sockets.

A previous attempt at splitting listeners into receivers failed because
the boundary between all these settings is not well defined.

This patch introduces a level of listening socket settings in the
bind_conf, that will be detachable later. Such settings that are solely
for the listening socket are:
  - unix socket permissions (used only during binding)
  - interface (used for binding)
  - network namespace (used for binding)
  - process mask and thread mask (used during startup)

The rest seems to be used only to initialize the resulting sockets, or
to control the accept rate. For now, only the unix params (bind_conf->ux)
were moved there.
2020-09-16 20:13:13 +02:00

137 lines
3.9 KiB
C

/*
* Configuration parsing for UNIX sockets (bind and server keywords)
*
* Copyright 2000-2020 Willy Tarreau <w@1wt.eu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <haproxy/api.h>
#include <haproxy/arg.h>
#include <haproxy/errors.h>
#include <haproxy/list.h>
#include <haproxy/listener.h>
#include <haproxy/namespace.h>
#include <haproxy/proxy-t.h>
#include <haproxy/server.h>
#include <haproxy/tools.h>
/* parse the "mode" bind keyword */
static int bind_parse_mode(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
char *endptr;
conf->settings.ux.mode = strtol(args[cur_arg + 1], &endptr, 8);
if (!*args[cur_arg + 1] || *endptr) {
memprintf(err, "'%s' : missing or invalid mode '%s' (octal integer expected)", args[cur_arg], args[cur_arg + 1]);
return ERR_ALERT | ERR_FATAL;
}
return 0;
}
/* parse the "gid" bind keyword */
static int bind_parse_gid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing value", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
conf->settings.ux.gid = atol(args[cur_arg + 1]);
return 0;
}
/* parse the "group" bind keyword */
static int bind_parse_group(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct group *group;
if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing group name", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
group = getgrnam(args[cur_arg + 1]);
if (!group) {
memprintf(err, "'%s' : unknown group name '%s'", args[cur_arg], args[cur_arg + 1]);
return ERR_ALERT | ERR_FATAL;
}
conf->settings.ux.gid = group->gr_gid;
return 0;
}
/* parse the "uid" bind keyword */
static int bind_parse_uid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing value", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
conf->settings.ux.uid = atol(args[cur_arg + 1]);
return 0;
}
/* parse the "user" bind keyword */
static int bind_parse_user(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
struct passwd *user;
if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing user name", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
user = getpwnam(args[cur_arg + 1]);
if (!user) {
memprintf(err, "'%s' : unknown user name '%s'", args[cur_arg], args[cur_arg + 1]);
return ERR_ALERT | ERR_FATAL;
}
conf->settings.ux.uid = user->pw_uid;
return 0;
}
/* Note: must not be declared <const> as its list will be overwritten.
* Please take care of keeping this list alphabetically sorted, doing so helps
* all code contributors.
* Optional keywords are also declared with a NULL ->parse() function so that
* the config parser can report an appropriate error when a known keyword was
* not enabled.
*/
static struct bind_kw_list bind_kws = { "UNIX", { }, {
{ "gid", bind_parse_gid, 1 }, /* set the socket's gid */
{ "group", bind_parse_group, 1 }, /* set the socket's gid from the group name */
{ "mode", bind_parse_mode, 1 }, /* set the socket's mode (eg: 0644)*/
{ "uid", bind_parse_uid, 1 }, /* set the socket's uid */
{ "user", bind_parse_user, 1 }, /* set the socket's uid from the user name */
{ NULL, NULL, 0 },
}};
INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);