blob: 03f70859133ffff5b646f8bab9ba4c514e3d570c [file] [log] [blame]
Willy Tarreaud1d54542012-09-12 22:58:11 +02001/*
2 * Protocol registration functions.
3 *
4 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreaua6e3be72016-08-10 18:24:48 +020013#include <sys/types.h>
Willy Tarreaub550d002015-02-20 16:53:25 +010014#include <sys/socket.h>
15
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020016#include <haproxy/api.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020017#include <haproxy/errors.h>
Willy Tarreau853b2972020-05-27 18:01:47 +020018#include <haproxy/list.h>
Willy Tarreau94320852020-09-01 18:48:35 +020019#include <haproxy/listener.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020020#include <haproxy/protocol.h>
Willy Tarreaue91bff22020-09-02 11:11:43 +020021#include <haproxy/proxy.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020022#include <haproxy/tools.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020023
Willy Tarreaud1d54542012-09-12 22:58:11 +020024
25/* List head of all registered protocols */
26static struct list protocols = LIST_HEAD_INIT(protocols);
Willy Tarreaue3b45182021-10-27 17:28:55 +020027struct protocol *__protocol_by_family[AF_CUST_MAX][PROTO_NUM_TYPES][2] __read_mostly = { };
Willy Tarreaud1d54542012-09-12 22:58:11 +020028
Willy Tarreaudaacf362019-07-24 16:45:02 +020029/* This is the global spinlock we may need to register/unregister listeners or
30 * protocols. Its main purpose is in fact to serialize the rare stop/deinit()
31 * phases.
32 */
33__decl_spinlock(proto_lock);
34
Willy Tarreaud1d54542012-09-12 22:58:11 +020035/* Registers the protocol <proto> */
36void protocol_register(struct protocol *proto)
37{
Willy Tarreaubdcee7f2021-10-27 15:06:35 +020038 int sock_domain = proto->fam->sock_domain;
39
40 BUG_ON(sock_domain < 0 || sock_domain >= AF_CUST_MAX);
Willy Tarreaue3b45182021-10-27 17:28:55 +020041 BUG_ON(proto->proto_type >= PROTO_NUM_TYPES);
Willy Tarreaubdcee7f2021-10-27 15:06:35 +020042
Willy Tarreaudaacf362019-07-24 16:45:02 +020043 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau2b718102021-04-21 07:32:39 +020044 LIST_APPEND(&protocols, &proto->list);
Willy Tarreaubdcee7f2021-10-27 15:06:35 +020045 __protocol_by_family[sock_domain]
Willy Tarreaue3b45182021-10-27 17:28:55 +020046 [proto->proto_type]
Willy Tarreau91b47262022-05-20 16:36:46 +020047 [proto->xprt_type == PROTO_TYPE_DGRAM] = proto;
Willy Tarreaudaacf362019-07-24 16:45:02 +020048 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020049}
50
51/* Unregisters the protocol <proto>. Note that all listeners must have
52 * previously been unbound.
53 */
54void protocol_unregister(struct protocol *proto)
55{
Willy Tarreaudaacf362019-07-24 16:45:02 +020056 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau2b718102021-04-21 07:32:39 +020057 LIST_DELETE(&proto->list);
Willy Tarreaud1d54542012-09-12 22:58:11 +020058 LIST_INIT(&proto->list);
Willy Tarreaudaacf362019-07-24 16:45:02 +020059 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020060}
61
62/* binds all listeners of all registered protocols. Returns a composition
63 * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
64 */
Willy Tarreaue91bff22020-09-02 11:11:43 +020065int protocol_bind_all(int verbose)
Willy Tarreaud1d54542012-09-12 22:58:11 +020066{
67 struct protocol *proto;
Willy Tarreau94320852020-09-01 18:48:35 +020068 struct listener *listener;
Willy Tarreaufc974882020-09-02 18:22:11 +020069 struct receiver *receiver;
Bjoern Jackeed174852021-01-12 19:24:43 +010070 char msg[1000];
Willy Tarreaufc974882020-09-02 18:22:11 +020071 char *errmsg;
Willy Tarreaue91bff22020-09-02 11:11:43 +020072 int err, lerr;
Willy Tarreaud1d54542012-09-12 22:58:11 +020073
74 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +020075 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020076 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +020077 list_for_each_entry(receiver, &proto->receivers, proto_list) {
Willy Tarreaufc974882020-09-02 18:22:11 +020078 listener = LIST_ELEM(receiver, struct listener *, rx);
79
Willy Tarreau233ad282020-10-15 21:45:15 +020080 lerr = proto->fam->bind(receiver, &errmsg);
Willy Tarreaufc974882020-09-02 18:22:11 +020081 err |= lerr;
Willy Tarreaue91bff22020-09-02 11:11:43 +020082
83 /* errors are reported if <verbose> is set or if they are fatal */
84 if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
85 struct proxy *px = listener->bind_conf->frontend;
86
87 if (lerr & ERR_ALERT)
Willy Tarreau37de5532021-10-14 11:55:48 +020088 ha_alert("Binding [%s:%d] for %s %s: %s\n",
89 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +020090 proxy_type_str(px), px->id, errmsg);
Willy Tarreaue91bff22020-09-02 11:11:43 +020091 else if (lerr & ERR_WARN)
Willy Tarreau37de5532021-10-14 11:55:48 +020092 ha_warning("Binding [%s:%d] for %s %s: %s\n",
93 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +020094 proxy_type_str(px), px->id, errmsg);
Willy Tarreau61cfdf42021-02-20 10:46:51 +010095 ha_free(&errmsg);
Willy Tarreaue91bff22020-09-02 11:11:43 +020096 }
Willy Tarreaufc974882020-09-02 18:22:11 +020097 if (lerr & ERR_ABORT)
98 break;
Willy Tarreaue91bff22020-09-02 11:11:43 +020099
Willy Tarreaufc974882020-09-02 18:22:11 +0200100 if (lerr & ~ERR_WARN)
101 continue;
102
103 /* for now there's still always a listening function */
104 BUG_ON(!proto->listen);
105 lerr = proto->listen(listener, msg, sizeof(msg));
Willy Tarreaue91bff22020-09-02 11:11:43 +0200106 err |= lerr;
Willy Tarreaufc974882020-09-02 18:22:11 +0200107
108 if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
109 struct proxy *px = listener->bind_conf->frontend;
110
111 if (lerr & ERR_ALERT)
Willy Tarreau37de5532021-10-14 11:55:48 +0200112 ha_alert("Starting [%s:%d] for %s %s: %s\n",
113 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200114 proxy_type_str(px), px->id, msg);
115 else if (lerr & ERR_WARN)
Willy Tarreau37de5532021-10-14 11:55:48 +0200116 ha_warning("Starting [%s:%d] for %s %s: %s\n",
117 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200118 proxy_type_str(px), px->id, msg);
119 }
Willy Tarreaue91bff22020-09-02 11:11:43 +0200120 if (lerr & ERR_ABORT)
Willy Tarreaud1d54542012-09-12 22:58:11 +0200121 break;
122 }
Willy Tarreaue91bff22020-09-02 11:11:43 +0200123 if (err & ERR_ABORT)
124 break;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200125 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200126 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200127 return err;
128}
129
130/* unbinds all listeners of all registered protocols. They are also closed.
131 * This must be performed before calling exit() in order to get a chance to
132 * remove file-system based sockets and pipes.
133 * Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
134 */
135int protocol_unbind_all(void)
136{
137 struct protocol *proto;
Willy Tarreauca212622020-09-02 10:31:31 +0200138 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200139 int err;
140
141 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200142 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200143 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200144 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Willy Tarreauca212622020-09-02 10:31:31 +0200145 unbind_listener(listener);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200146 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200147 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200148 return err;
149}
150
Willy Tarreaueb778242021-06-11 16:27:10 +0200151/* stops all listeners of all registered protocols. This will normally catch
152 * every single listener, all protocols included. This is to be used during
153 * soft_stop() only. It does not return any error.
Willy Tarreau02e85572020-10-07 16:50:49 +0200154 */
155void protocol_stop_now(void)
156{
157 struct protocol *proto;
158 struct listener *listener, *lback;
159
160 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
161 list_for_each_entry(proto, &protocols, list) {
162 list_for_each_entry_safe(listener, lback, &proto->receivers, rx.proto_list)
Aurelien DARRAGON00132882022-09-09 15:32:57 +0200163 stop_listener(listener, 0, 1);
Willy Tarreau02e85572020-10-07 16:50:49 +0200164 }
165 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
166}
167
Willy Tarreau09819d12020-09-24 16:26:50 +0200168/* pauses all listeners of all registered protocols. This is typically
169 * used on SIG_TTOU to release all listening sockets for the time needed to
170 * try to bind a new process. The listeners enter LI_PAUSED. It returns
171 * ERR_NONE, with ERR_FATAL on failure.
172 */
173int protocol_pause_all(void)
174{
175 struct protocol *proto;
176 struct listener *listener;
177 int err;
178
179 err = 0;
180 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
181 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200182 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Aurelien DARRAGON00132882022-09-09 15:32:57 +0200183 if (!pause_listener(listener, 0))
Willy Tarreau09819d12020-09-24 16:26:50 +0200184 err |= ERR_FATAL;
185 }
186 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
187 return err;
188}
189
190/* resumes all listeners of all registered protocols. This is typically used on
191 * SIG_TTIN to re-enable listening sockets after a new process failed to bind.
192 * The listeners switch to LI_READY/LI_FULL. It returns ERR_NONE, with ERR_FATAL
193 * on failure.
194 */
195int protocol_resume_all(void)
196{
197 struct protocol *proto;
198 struct listener *listener;
199 int err;
200
201 err = 0;
202 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
203 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200204 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Aurelien DARRAGON00132882022-09-09 15:32:57 +0200205 if (!resume_listener(listener, 0))
Willy Tarreau09819d12020-09-24 16:26:50 +0200206 err |= ERR_FATAL;
207 }
208 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
209 return err;
210}
211
Willy Tarreaud1d54542012-09-12 22:58:11 +0200212/* enables all listeners of all registered protocols. This is intended to be
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200213 * used after a fork() to enable reading on all file descriptors. Returns
214 * composition of ERR_NONE.
Willy Tarreaud1d54542012-09-12 22:58:11 +0200215 */
216int protocol_enable_all(void)
217{
218 struct protocol *proto;
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200219 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200220
Willy Tarreaudaacf362019-07-24 16:45:02 +0200221 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200222 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200223 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200224 enable_listener(listener);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200225 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200226 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200227 return ERR_NONE;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200228}
229
Willy Tarreaud1d54542012-09-12 22:58:11 +0200230/*
231 * Local variables:
232 * c-indent-level: 8
233 * c-basic-offset: 8
234 * End:
235 */