blob: f739444a0a66b7b2491d52fe223323b4d102a6b6 [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 Tarreau48fbcae2020-06-03 18:09:46 +020019#include <haproxy/tools.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020020
Willy Tarreau2dd7c352020-06-03 15:26:55 +020021#include <haproxy/protocol.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020022
23/* List head of all registered protocols */
24static struct list protocols = LIST_HEAD_INIT(protocols);
William Lallemand2d3f8a42018-09-11 16:51:28 +020025struct protocol *__protocol_by_family[AF_CUST_MAX] = { };
Willy Tarreaud1d54542012-09-12 22:58:11 +020026
Willy Tarreaudaacf362019-07-24 16:45:02 +020027/* This is the global spinlock we may need to register/unregister listeners or
28 * protocols. Its main purpose is in fact to serialize the rare stop/deinit()
29 * phases.
30 */
31__decl_spinlock(proto_lock);
32
Willy Tarreaud1d54542012-09-12 22:58:11 +020033/* Registers the protocol <proto> */
34void protocol_register(struct protocol *proto)
35{
Willy Tarreaudaacf362019-07-24 16:45:02 +020036 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020037 LIST_ADDQ(&protocols, &proto->list);
William Lallemand2d3f8a42018-09-11 16:51:28 +020038 if (proto->sock_domain >= 0 && proto->sock_domain < AF_CUST_MAX)
Willy Tarreaub550d002015-02-20 16:53:25 +010039 __protocol_by_family[proto->sock_domain] = proto;
Willy Tarreaudaacf362019-07-24 16:45:02 +020040 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020041}
42
43/* Unregisters the protocol <proto>. Note that all listeners must have
44 * previously been unbound.
45 */
46void protocol_unregister(struct protocol *proto)
47{
Willy Tarreaudaacf362019-07-24 16:45:02 +020048 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020049 LIST_DEL(&proto->list);
50 LIST_INIT(&proto->list);
Willy Tarreaudaacf362019-07-24 16:45:02 +020051 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020052}
53
54/* binds all listeners of all registered protocols. Returns a composition
55 * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
56 */
57int protocol_bind_all(char *errmsg, int errlen)
58{
59 struct protocol *proto;
60 int err;
61
62 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +020063 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020064 list_for_each_entry(proto, &protocols, list) {
65 if (proto->bind_all) {
66 err |= proto->bind_all(proto, errmsg, errlen);
67 if ( err & ERR_ABORT )
68 break;
69 }
70 }
Willy Tarreaudaacf362019-07-24 16:45:02 +020071 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020072 return err;
73}
74
75/* unbinds all listeners of all registered protocols. They are also closed.
76 * This must be performed before calling exit() in order to get a chance to
77 * remove file-system based sockets and pipes.
78 * Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
79 */
80int protocol_unbind_all(void)
81{
82 struct protocol *proto;
83 int err;
84
85 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +020086 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020087 list_for_each_entry(proto, &protocols, list) {
88 if (proto->unbind_all) {
89 err |= proto->unbind_all(proto);
90 }
91 }
Willy Tarreaudaacf362019-07-24 16:45:02 +020092 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +020093 return err;
94}
95
96/* enables all listeners of all registered protocols. This is intended to be
97 * used after a fork() to enable reading on all file descriptors. Returns a
98 * composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
99 */
100int protocol_enable_all(void)
101{
102 struct protocol *proto;
103 int err;
104
105 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200106 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200107 list_for_each_entry(proto, &protocols, list) {
108 if (proto->enable_all) {
109 err |= proto->enable_all(proto);
110 }
111 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200112 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200113 return err;
114}
115
116/* disables all listeners of all registered protocols. This may be used before
117 * a fork() to avoid duplicating poll lists. Returns a composition of ERR_NONE,
118 * ERR_RETRYABLE, ERR_FATAL.
119 */
120int protocol_disable_all(void)
121{
122 struct protocol *proto;
123 int err;
124
125 err = 0;
Willy Tarreaudaacf362019-07-24 16:45:02 +0200126 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200127 list_for_each_entry(proto, &protocols, list) {
128 if (proto->disable_all) {
129 err |= proto->disable_all(proto);
130 }
131 }
Willy Tarreaudaacf362019-07-24 16:45:02 +0200132 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
Willy Tarreaud1d54542012-09-12 22:58:11 +0200133 return err;
134}
135
Willy Tarreaud1d54542012-09-12 22:58:11 +0200136/*
137 * Local variables:
138 * c-indent-level: 8
139 * c-basic-offset: 8
140 * End:
141 */