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