1 /*
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
13 #include <sys/types.h>
14 #include <sys/socket.h>
15
16 #include <haproxy/api.h>
17 #include <haproxy/errors.h>
18 #include <haproxy/list.h>
19 #include <haproxy/protocol.h>
20 #include <haproxy/tools.h>
21
22
23 /* List head of all registered protocols */
24 static struct list protocols = LIST_HEAD_INIT(protocols);
25 struct protocol *__protocol_by_family[AF_CUST_MAX] = { };
26
27 /* 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
33 /* Registers the protocol <proto> */
protocol_register(struct protocol * proto)34 void protocol_register(struct protocol *proto)
35 {
36 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
37 LIST_ADDQ(&protocols, &proto->list);
38 if (proto->sock_domain >= 0 && proto->sock_domain < AF_CUST_MAX)
39 __protocol_by_family[proto->sock_domain] = proto;
40 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
41 }
42
43 /* Unregisters the protocol <proto>. Note that all listeners must have
44 * previously been unbound.
45 */
protocol_unregister(struct protocol * proto)46 void protocol_unregister(struct protocol *proto)
47 {
48 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
49 LIST_DEL(&proto->list);
50 LIST_INIT(&proto->list);
51 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
52 }
53
54 /* binds all listeners of all registered protocols. Returns a composition
55 * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
56 */
protocol_bind_all(char * errmsg,int errlen)57 int protocol_bind_all(char *errmsg, int errlen)
58 {
59 struct protocol *proto;
60 int err;
61
62 err = 0;
63 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
64 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 }
71 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
72 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 */
protocol_unbind_all(void)80 int protocol_unbind_all(void)
81 {
82 struct protocol *proto;
83 int err;
84
85 err = 0;
86 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
87 list_for_each_entry(proto, &protocols, list) {
88 if (proto->unbind_all) {
89 err |= proto->unbind_all(proto);
90 }
91 }
92 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
93 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 */
protocol_enable_all(void)100 int protocol_enable_all(void)
101 {
102 struct protocol *proto;
103 int err;
104
105 err = 0;
106 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
107 list_for_each_entry(proto, &protocols, list) {
108 if (proto->enable_all) {
109 err |= proto->enable_all(proto);
110 }
111 }
112 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
113 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 */
protocol_disable_all(void)120 int protocol_disable_all(void)
121 {
122 struct protocol *proto;
123 int err;
124
125 err = 0;
126 HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
127 list_for_each_entry(proto, &protocols, list) {
128 if (proto->disable_all) {
129 err |= proto->disable_all(proto);
130 }
131 }
132 HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
133 return err;
134 }
135
136 /*
137 * Local variables:
138 * c-indent-level: 8
139 * c-basic-offset: 8
140 * End:
141 */
142