blob: cafaa72e702b5543469d914825fc5107c3ec17ab [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 Tarreau61cfdf42021-02-20 10:46:51 +0100102 ha_free(&errmsg);
Willy Tarreaue91bff22020-09-02 11:11:43 +0200103 }
Willy Tarreaufc974882020-09-02 18:22:11 +0200104 if (lerr & ERR_ABORT)
105 break;
Willy Tarreaue91bff22020-09-02 11:11:43 +0200106
Willy Tarreaufc974882020-09-02 18:22:11 +0200107 if (lerr & ~ERR_WARN)
108 continue;
109
110 /* for now there's still always a listening function */
111 BUG_ON(!proto->listen);
112 lerr = proto->listen(listener, msg, sizeof(msg));
Willy Tarreaue91bff22020-09-02 11:11:43 +0200113 err |= lerr;
Willy Tarreaufc974882020-09-02 18:22:11 +0200114
115 if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
116 struct proxy *px = listener->bind_conf->frontend;
117
118 if (lerr & ERR_ALERT)
Willy Tarreau37de5532021-10-14 11:55:48 +0200119 ha_alert("Starting [%s:%d] for %s %s: %s\n",
120 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200121 proxy_type_str(px), px->id, msg);
122 else if (lerr & ERR_WARN)
Willy Tarreau37de5532021-10-14 11:55:48 +0200123 ha_warning("Starting [%s:%d] for %s %s: %s\n",
124 listener->bind_conf->file, listener->bind_conf->line,
Willy Tarreaufc974882020-09-02 18:22:11 +0200125 proxy_type_str(px), px->id, msg);
126 }
Willy Tarreaue91bff22020-09-02 11:11:43 +0200127 if (lerr & ERR_ABORT)
Willy Tarreaud1d54542012-09-12 22:58:11 +0200128 break;
129 }
Willy Tarreaue91bff22020-09-02 11:11:43 +0200130 if (err & ERR_ABORT)
131 break;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200132 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200133 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200134 return err;
135}
136
137/* unbinds all listeners of all registered protocols. They are also closed.
138 * This must be performed before calling exit() in order to get a chance to
139 * remove file-system based sockets and pipes.
140 * Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
141 */
142int protocol_unbind_all(void)
143{
144 struct protocol *proto;
Willy Tarreauca212622020-09-02 10:31:31 +0200145 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200146 int err;
147
148 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200149 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200150 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200151 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Willy Tarreauca212622020-09-02 10:31:31 +0200152 unbind_listener(listener);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200153 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200154 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200155 return err;
156}
157
Willy Tarreaueb778242021-06-11 16:27:10 +0200158/* stops all listeners of all registered protocols. This will normally catch
159 * every single listener, all protocols included. This is to be used during
160 * soft_stop() only. It does not return any error.
Willy Tarreau02e85572020-10-07 16:50:49 +0200161 */
162void protocol_stop_now(void)
163{
164 struct protocol *proto;
165 struct listener *listener, *lback;
166
167 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
168 list_for_each_entry(proto, &protocols, list) {
169 list_for_each_entry_safe(listener, lback, &proto->receivers, rx.proto_list)
Aurelien DARRAGON00132882022-09-09 15:32:57 +0200170 stop_listener(listener, 0, 1);
Willy Tarreau02e85572020-10-07 16:50:49 +0200171 }
172 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
173}
174
Willy Tarreau09819d12020-09-24 16:26:50 +0200175/* pauses all listeners of all registered protocols. This is typically
176 * used on SIG_TTOU to release all listening sockets for the time needed to
177 * try to bind a new process. The listeners enter LI_PAUSED. It returns
178 * ERR_NONE, with ERR_FATAL on failure.
179 */
180int protocol_pause_all(void)
181{
182 struct protocol *proto;
183 struct listener *listener;
184 int err;
185
186 err = 0;
187 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
188 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200189 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Aurelien DARRAGON00132882022-09-09 15:32:57 +0200190 if (!pause_listener(listener, 0))
Willy Tarreau09819d12020-09-24 16:26:50 +0200191 err |= ERR_FATAL;
192 }
193 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
194 return err;
195}
196
197/* resumes all listeners of all registered protocols. This is typically used on
198 * SIG_TTIN to re-enable listening sockets after a new process failed to bind.
199 * The listeners switch to LI_READY/LI_FULL. It returns ERR_NONE, with ERR_FATAL
200 * on failure.
201 */
202int protocol_resume_all(void)
203{
204 struct protocol *proto;
205 struct listener *listener;
206 int err;
207
208 err = 0;
209 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
210 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200211 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Aurelien DARRAGON00132882022-09-09 15:32:57 +0200212 if (!resume_listener(listener, 0))
Willy Tarreau09819d12020-09-24 16:26:50 +0200213 err |= ERR_FATAL;
214 }
215 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
216 return err;
217}
218
Willy Tarreaud1d54542012-09-12 22:58:11 +0200219/* enables all listeners of all registered protocols. This is intended to be
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200220 * used after a fork() to enable reading on all file descriptors. Returns
221 * composition of ERR_NONE.
Willy Tarreaud1d54542012-09-12 22:58:11 +0200222 */
223int protocol_enable_all(void)
224{
225 struct protocol *proto;
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200226 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200227
Willy Tarreaudaacf362019-07-24 16:45:02 +0200228 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200229 list_for_each_entry(proto, &protocols, list) {
Willy Tarreaud7f331c2020-09-25 17:01:43 +0200230 list_for_each_entry(listener, &proto->receivers, rx.proto_list)
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200231 enable_listener(listener);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200232 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200233 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreau5b95ae62020-09-25 16:41:05 +0200234 return ERR_NONE;
Willy Tarreaud1d54542012-09-12 22:58:11 +0200235}
236
Willy Tarreaud1d54542012-09-12 22:58:11 +0200237/*
238 * Local variables:
239 * c-indent-level: 8
240 * c-basic-offset: 8
241 * End:
242 */