blob: c627d5c73493fa3567aaba8e828d88eecfc3ad6e [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>
Frédéric Lécaille12a03172023-01-12 15:23:54 +010018#include <haproxy/global.h>
Willy Tarreau853b2972020-05-27 18:01:47 +020019#include <haproxy/list.h>
Willy Tarreau94320852020-09-01 18:48:35 +020020#include <haproxy/listener.h>
Frédéric Lécaille12a03172023-01-12 15:23:54 +010021#include <haproxy/proto_quic.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020022#include <haproxy/protocol.h>
Willy Tarreaue91bff22020-09-02 11:11:43 +020023#include <haproxy/proxy.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020024#include <haproxy/tools.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020025
Willy Tarreaud1d54542012-09-12 22:58:11 +020026
27/* List head of all registered protocols */
28static struct list protocols = LIST_HEAD_INIT(protocols);
Willy Tarreaue3b45182021-10-27 17:28:55 +020029struct protocol *__protocol_by_family[AF_CUST_MAX][PROTO_NUM_TYPES][2] __read_mostly = { };
Willy Tarreaud1d54542012-09-12 22:58:11 +020030
Willy Tarreaudaacf362019-07-24 16:45:02 +020031/* This is the global spinlock we may need to register/unregister listeners or
32 * protocols. Its main purpose is in fact to serialize the rare stop/deinit()
33 * phases.
34 */
35__decl_spinlock(proto_lock);
36
Willy Tarreaud1d54542012-09-12 22:58:11 +020037/* Registers the protocol <proto> */
38void protocol_register(struct protocol *proto)
39{
Willy Tarreaubdcee7f2021-10-27 15:06:35 +020040 int sock_domain = proto->fam->sock_domain;
41
42 BUG_ON(sock_domain < 0 || sock_domain >= AF_CUST_MAX);
Willy Tarreaue3b45182021-10-27 17:28:55 +020043 BUG_ON(proto->proto_type >= PROTO_NUM_TYPES);
Willy Tarreaubdcee7f2021-10-27 15:06:35 +020044
Willy Tarreaudaacf362019-07-24 16:45:02 +020045 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau2b718102021-04-21 07:32:39 +020046 LIST_APPEND(&protocols, &proto->list);
Willy Tarreaubdcee7f2021-10-27 15:06:35 +020047 __protocol_by_family[sock_domain]
Willy Tarreaue3b45182021-10-27 17:28:55 +020048 [proto->proto_type]
Willy Tarreau91b47262022-05-20 16:36:46 +020049 [proto->xprt_type == PROTO_TYPE_DGRAM] = proto;
Willy Tarreaudaacf362019-07-24 16:45:02 +020050 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020051}
52
53/* Unregisters the protocol <proto>. Note that all listeners must have
54 * previously been unbound.
55 */
56void protocol_unregister(struct protocol *proto)
57{
Willy Tarreaudaacf362019-07-24 16:45:02 +020058 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau2b718102021-04-21 07:32:39 +020059 LIST_DELETE(&proto->list);
Willy Tarreaud1d54542012-09-12 22:58:11 +020060 LIST_INIT(&proto->list);
Willy Tarreaudaacf362019-07-24 16:45:02 +020061 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020062}
63
64/* binds all listeners of all registered protocols. Returns a composition
65 * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
66 */
Willy Tarreaue91bff22020-09-02 11:11:43 +020067int protocol_bind_all(int verbose)
Willy Tarreaud1d54542012-09-12 22:58:11 +020068{
69 struct protocol *proto;
Willy Tarreau94320852020-09-01 18:48:35 +020070 struct listener *listener;
Willy Tarreaufc974882020-09-02 18:22:11 +020071 struct receiver *receiver;
Bjoern Jackeed174852021-01-12 19:24:43 +010072 char msg[1000];
Willy Tarreaufc974882020-09-02 18:22:11 +020073 char *errmsg;
Willy Tarreaue91bff22020-09-02 11:11:43 +020074 int err, lerr;
Willy Tarreaud1d54542012-09-12 22:58:11 +020075
76 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +020077 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020078 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +020079 list_for_each_entry(receiver, &proto->receivers, proto_list) {
Frédéric Lécaille12a03172023-01-12 15:23:54 +010080#ifdef USE_QUIC
81 if ((global.tune.options & GTUNE_NO_QUIC) &&
82 (proto == &proto_quic4 || proto == &proto_quic6))
83 continue;
84#endif
Willy Tarreaufc974882020-09-02 18:22:11 +020085 listener = LIST_ELEM(receiver, struct listener *, rx);
86
Willy Tarreau233ad282020-10-15 21:45:15 +020087 lerr = proto->fam->bind(receiver, &errmsg);
Willy Tarreaufc974882020-09-02 18:22:11 +020088 err |= lerr;
Willy Tarreaue91bff22020-09-02 11:11:43 +020089
90 /* errors are reported if <verbose> is set or if they are fatal */
91 if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
92 struct proxy *px = listener->bind_conf->frontend;
93
94 if (lerr & ERR_ALERT)
Willy Tarreau37de5532021-10-14 11:55:48 +020095 ha_alert("Binding [%s:%d] for %s %s: %s\n",
96 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +020097 proxy_type_str(px), px->id, errmsg);
Willy Tarreaue91bff22020-09-02 11:11:43 +020098 else if (lerr & ERR_WARN)
Willy Tarreau37de5532021-10-14 11:55:48 +020099 ha_warning("Binding [%s:%d] for %s %s: %s\n",
100 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200101 proxy_type_str(px), px->id, errmsg);
Willy Tarreaue91bff22020-09-02 11:11:43 +0200102 }
Aurelien DARRAGON84296272023-02-07 15:51:58 +0100103 if (lerr != ERR_NONE)
104 ha_free(&errmsg);
105
Willy Tarreaufc974882020-09-02 18:22:11 +0200106 if (lerr & ERR_ABORT)
107 break;
Willy Tarreaue91bff22020-09-02 11:11:43 +0200108
Willy Tarreaufc974882020-09-02 18:22:11 +0200109 if (lerr & ~ERR_WARN)
110 continue;
111
112 /* for now there's still always a listening function */
113 BUG_ON(!proto->listen);
114 lerr = proto->listen(listener, msg, sizeof(msg));
Willy Tarreaue91bff22020-09-02 11:11:43 +0200115 err |= lerr;
Willy Tarreaufc974882020-09-02 18:22:11 +0200116
117 if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
118 struct proxy *px = listener->bind_conf->frontend;
119
120 if (lerr & ERR_ALERT)
Willy Tarreau37de5532021-10-14 11:55:48 +0200121 ha_alert("Starting [%s:%d] for %s %s: %s\n",
122 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200123 proxy_type_str(px), px->id, msg);
124 else if (lerr & ERR_WARN)
Willy Tarreau37de5532021-10-14 11:55:48 +0200125 ha_warning("Starting [%s:%d] for %s %s: %s\n",
126 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200127 proxy_type_str(px), px->id, msg);
128 }
Willy Tarreaue91bff22020-09-02 11:11:43 +0200129 if (lerr & ERR_ABORT)
Willy Tarreaud1d54542012-09-12 22:58:11 +0200130 break;
131 }
Willy Tarreaue91bff22020-09-02 11:11:43 +0200132 if (err & ERR_ABORT)
133 break;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200134 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200135 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200136 return err;
137}
138
139/* unbinds all listeners of all registered protocols. They are also closed.
140 * This must be performed before calling exit() in order to get a chance to
141 * remove file-system based sockets and pipes.
142 * Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
143 */
144int protocol_unbind_all(void)
145{
146 struct protocol *proto;
Willy Tarreauca212622020-09-02 10:31:31 +0200147 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200148 int err;
149
150 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200151 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200152 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200153 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Willy Tarreauca212622020-09-02 10:31:31 +0200154 unbind_listener(listener);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200155 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200156 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200157 return err;
158}
159
Willy Tarreaueb778242021-06-11 16:27:10 +0200160/* stops all listeners of all registered protocols. This will normally catch
161 * every single listener, all protocols included. This is to be used during
162 * soft_stop() only. It does not return any error.
Willy Tarreau02e85572020-10-07 16:50:49 +0200163 */
164void protocol_stop_now(void)
165{
166 struct protocol *proto;
167 struct listener *listener, *lback;
168
169 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
170 list_for_each_entry(proto, &protocols, list) {
171 list_for_each_entry_safe(listener, lback, &proto->receivers, rx.proto_list)
Aurelien DARRAGON4059e092023-02-06 17:06:03 +0100172 stop_listener(listener, 0, 1, 0);
Willy Tarreau02e85572020-10-07 16:50:49 +0200173 }
174 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
175}
176
Aurelien DARRAGONd3ffba42023-02-13 17:45:08 +0100177/* suspends all listeners of all registered protocols. This is typically
Willy Tarreau09819d12020-09-24 16:26:50 +0200178 * used on SIG_TTOU to release all listening sockets for the time needed to
Aurelien DARRAGONd3ffba42023-02-13 17:45:08 +0100179 * try to bind a new process. The listeners enter LI_PAUSED or LI_ASSIGNED.
180 * It returns ERR_NONE, with ERR_FATAL on failure.
Willy Tarreau09819d12020-09-24 16:26:50 +0200181 */
182int protocol_pause_all(void)
183{
184 struct protocol *proto;
185 struct listener *listener;
186 int err;
187
188 err = 0;
189 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
190 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200191 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Aurelien DARRAGONd3ffba42023-02-13 17:45:08 +0100192 if (!suspend_listener(listener, 0, 0))
Willy Tarreau09819d12020-09-24 16:26:50 +0200193 err |= ERR_FATAL;
194 }
195 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
196 return err;
197}
198
199/* resumes all listeners of all registered protocols. This is typically used on
200 * SIG_TTIN to re-enable listening sockets after a new process failed to bind.
201 * The listeners switch to LI_READY/LI_FULL. It returns ERR_NONE, with ERR_FATAL
202 * on failure.
203 */
204int protocol_resume_all(void)
205{
206 struct protocol *proto;
207 struct listener *listener;
208 int err;
209
210 err = 0;
211 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
212 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200213 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Aurelien DARRAGON4059e092023-02-06 17:06:03 +0100214 if (!resume_listener(listener, 0, 0))
Willy Tarreau09819d12020-09-24 16:26:50 +0200215 err |= ERR_FATAL;
216 }
217 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
218 return err;
219}
220
Willy Tarreaud1d54542012-09-12 22:58:11 +0200221/* enables all listeners of all registered protocols. This is intended to be
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200222 * used after a fork() to enable reading on all file descriptors. Returns
223 * composition of ERR_NONE.
Willy Tarreaud1d54542012-09-12 22:58:11 +0200224 */
225int protocol_enable_all(void)
226{
227 struct protocol *proto;
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200228 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200229
Willy Tarreaudaacf362019-07-24 16:45:02 +0200230 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200231 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200232 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200233 enable_listener(listener);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200234 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200235 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200236 return ERR_NONE;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200237}
238
Willy Tarreaud1d54542012-09-12 22:58:11 +0200239/*
240 * Local variables:
241 * c-indent-level: 8
242 * c-basic-offset: 8
243 * End:
244 */