blob: faa634192dfe02adaf4abca0d039faa50c0ea37f [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 Tarreau48fbcae2020-06-03 18:09:46 +020021#include <haproxy/tools.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020022
Willy Tarreaud1d54542012-09-12 22:58:11 +020023
24/* List head of all registered protocols */
25static struct list protocols = LIST_HEAD_INIT(protocols);
William Lallemand2d3f8a42018-09-11 16:51:28 +020026struct protocol *__protocol_by_family[AF_CUST_MAX] = { };
Willy Tarreaud1d54542012-09-12 22:58:11 +020027
Willy Tarreaudaacf362019-07-24 16:45:02 +020028/* This is the global spinlock we may need to register/unregister listeners or
29 * protocols. Its main purpose is in fact to serialize the rare stop/deinit()
30 * phases.
31 */
32__decl_spinlock(proto_lock);
33
Willy Tarreaud1d54542012-09-12 22:58:11 +020034/* Registers the protocol <proto> */
35void protocol_register(struct protocol *proto)
36{
Willy Tarreaudaacf362019-07-24 16:45:02 +020037 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020038 LIST_ADDQ(&protocols, &proto->list);
William Lallemand2d3f8a42018-09-11 16:51:28 +020039 if (proto->sock_domain >= 0 && proto->sock_domain < AF_CUST_MAX)
Willy Tarreaub550d002015-02-20 16:53:25 +010040 __protocol_by_family[proto->sock_domain] = proto;
Willy Tarreaudaacf362019-07-24 16:45:02 +020041 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020042}
43
44/* Unregisters the protocol <proto>. Note that all listeners must have
45 * previously been unbound.
46 */
47void protocol_unregister(struct protocol *proto)
48{
Willy Tarreaudaacf362019-07-24 16:45:02 +020049 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020050 LIST_DEL(&proto->list);
51 LIST_INIT(&proto->list);
Willy Tarreaudaacf362019-07-24 16:45:02 +020052 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020053}
54
55/* binds all listeners of all registered protocols. Returns a composition
56 * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
57 */
58int protocol_bind_all(char *errmsg, int errlen)
59{
60 struct protocol *proto;
Willy Tarreau94320852020-09-01 18:48:35 +020061 struct listener *listener;
Willy Tarreaud1d54542012-09-12 22:58:11 +020062 int err;
63
64 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +020065 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020066 list_for_each_entry(proto, &protocols, list) {
Willy Tarreau94320852020-09-01 18:48:35 +020067 list_for_each_entry(listener, &proto->listeners, proto_list) {
68 err |= proto->bind(listener, errmsg, errlen);
69 if (err & ERR_ABORT)
Willy Tarreaud1d54542012-09-12 22:58:11 +020070 break;
71 }
72 }
Willy Tarreaudaacf362019-07-24 16:45:02 +020073 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020074 return err;
75}
76
77/* unbinds all listeners of all registered protocols. They are also closed.
78 * This must be performed before calling exit() in order to get a chance to
79 * remove file-system based sockets and pipes.
80 * Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
81 */
82int protocol_unbind_all(void)
83{
84 struct protocol *proto;
85 int err;
86
87 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +020088 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020089 list_for_each_entry(proto, &protocols, list) {
90 if (proto->unbind_all) {
91 err |= proto->unbind_all(proto);
92 }
93 }
Willy Tarreaudaacf362019-07-24 16:45:02 +020094 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020095 return err;
96}
97
98/* enables all listeners of all registered protocols. This is intended to be
99 * used after a fork() to enable reading on all file descriptors. Returns a
100 * composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
101 */
102int protocol_enable_all(void)
103{
104 struct protocol *proto;
105 int err;
106
107 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200108 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200109 list_for_each_entry(proto, &protocols, list) {
110 if (proto->enable_all) {
111 err |= proto->enable_all(proto);
112 }
113 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200114 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200115 return err;
116}
117
118/* disables all listeners of all registered protocols. This may be used before
119 * a fork() to avoid duplicating poll lists. Returns a composition of ERR_NONE,
120 * ERR_RETRYABLE, ERR_FATAL.
121 */
122int protocol_disable_all(void)
123{
124 struct protocol *proto;
125 int err;
126
127 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200128 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200129 list_for_each_entry(proto, &protocols, list) {
130 if (proto->disable_all) {
131 err |= proto->disable_all(proto);
132 }
133 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200134 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200135 return err;
136}
137
Willy Tarreaud1d54542012-09-12 22:58:11 +0200138/*
139 * Local variables:
140 * c-indent-level: 8
141 * c-basic-offset: 8
142 * End:
143 */