Coverage Report

Created: 2026-10-16 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/src/protocol.c
Line
Count
Source
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 <unistd.h>
14
15
#include <sys/types.h>
16
#include <sys/socket.h>
17
18
#include <haproxy/api.h>
19
#include <haproxy/errors.h>
20
#include <haproxy/global.h>
21
#include <haproxy/list.h>
22
#include <haproxy/listener.h>
23
#include <haproxy/proto_quic.h>
24
#include <haproxy/protocol.h>
25
#include <haproxy/proxy.h>
26
#include <haproxy/quic_tune.h>
27
#include <haproxy/sock.h>
28
#include <haproxy/tools.h>
29
#include <haproxy/twork.h>
30
31
32
/* List head of all registered protocols */
33
static struct list protocols = LIST_HEAD_INIT(protocols);
34
struct protocol *__protocol_by_family[AF_CUST_MAX][PROTO_NUM_TYPES][2] __read_mostly = { };
35
const struct proto_fam *__proto_fam_by_family[AF_CUST_MAX] = { };
36
37
/* This is the global spinlock we may need to register/unregister listeners or
38
 * protocols. Its main purpose is in fact to serialize the rare stop/deinit()
39
 * phases.
40
 */
41
__decl_spinlock(proto_lock);
42
43
/* Registers the protocol <proto> */
44
void protocol_register(struct protocol *proto)
45
0
{
46
0
  int sock_family = proto->fam->sock_family;
47
48
0
  BUG_ON(sock_family < 0 || sock_family >= AF_CUST_MAX);
49
0
  BUG_ON(proto->proto_type >= PROTO_NUM_TYPES);
50
51
0
  LIST_INIT(&proto->receivers);
52
0
  proto->nb_receivers = 0;
53
54
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
55
0
  LIST_APPEND(&protocols, &proto->list);
56
0
  __protocol_by_family[sock_family]
57
0
                      [proto->proto_type]
58
0
                      [proto->xprt_type == PROTO_TYPE_DGRAM ||
59
0
                       proto->sock_prot == IPPROTO_MPTCP] = proto;
60
0
  __proto_fam_by_family[sock_family] = proto->fam;
61
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
62
0
}
63
64
/* Unregisters the protocol <proto>. Note that all listeners must have
65
 * previously been unbound.
66
 */
67
void protocol_unregister(struct protocol *proto)
68
0
{
69
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
70
0
  LIST_DELETE(&proto->list);
71
0
  LIST_INIT(&proto->list);
72
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
73
0
}
74
75
/* clears flag <flag> on all protocols. */
76
void protocol_clrf_all(uint flag)
77
0
{
78
0
  struct protocol *proto;
79
80
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
81
0
  list_for_each_entry(proto, &protocols, list)
82
0
    proto->flags &= ~flag;
83
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
84
0
}
85
86
/* sets flag <flag> on all protocols. */
87
void protocol_setf_all(uint flag)
88
0
{
89
0
  struct protocol *proto;
90
91
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
92
0
  list_for_each_entry(proto, &protocols, list)
93
0
    proto->flags |= flag;
94
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
95
0
}
96
97
/* Checks if protocol <proto> supports PROTO_F flag <flag>. Returns zero if not,
98
 * non-zero if supported. It may return a cached value from a previous test,
99
 * and may run live tests then update the proto's flags to cache a result. It's
100
 * better to call it only if needed so that it doesn't result in modules being
101
 * loaded in case of a live test. It is only supposed to be used during boot.
102
 */
103
int protocol_supports_flag(struct protocol *proto, uint flag)
104
0
{
105
0
  if (flag == PROTO_F_REUSEPORT_SUPPORTED) {
106
0
    int ret = 0;
107
108
    /* check if the protocol supports SO_REUSEPORT */
109
0
    if (!(_HA_ATOMIC_LOAD(&proto->flags) & PROTO_F_REUSEPORT_SUPPORTED))
110
0
      return 0;
111
112
    /* TESTED is set, assume supported (live test already ran and passed) */
113
0
    if (_HA_ATOMIC_LOAD(&proto->flags) & PROTO_F_REUSEPORT_TESTED)
114
0
      return 1;
115
116
    /* run a live check */
117
0
    ret = _sock_supports_reuseport(proto->fam, proto->sock_type, proto->sock_prot);
118
0
    if (!ret)
119
0
      _HA_ATOMIC_AND(&proto->flags, ~PROTO_F_REUSEPORT_SUPPORTED);
120
121
0
    _HA_ATOMIC_OR(&proto->flags, PROTO_F_REUSEPORT_TESTED);
122
0
    return ret;
123
0
  }
124
0
  return 0;
125
0
}
126
127
#ifdef USE_QUIC
128
/* Return 1 if QUIC protocol may be bound, 0 if no, depending on the tuning
129
 * parameters.
130
 */
131
static inline int protocol_may_bind_quic(struct listener *l)
132
{
133
  return !(quic_tune.fe.opts & QUIC_TUNE_FE_LISTEN_OFF);
134
}
135
#endif
136
137
void protocol_init_rx_agents(void)
138
0
{
139
0
  struct protocol *proto;
140
0
  struct receiver *rx;
141
142
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
143
0
  list_for_each_entry(proto, &protocols, list) {
144
0
    list_for_each_entry(rx, &proto->receivers, proto_list) {
145
0
      twork_init(&rx->agent.twk);
146
0
      rx->agent.want_state = RX_AGENT_ST_NONE;
147
0
      rx->agent.close_fd = -1;
148
0
      rx->agent.xfer_fd = -1;
149
0
      rx->agent.getsocks_fd = -1;
150
0
    }
151
0
  }
152
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
153
0
}
154
155
/*
156
 * With per-thread-group FD tables, gives up the calling thread's group's
157
 * inherited copies of the receiver FDs it does not own: a receiver's FD is
158
 * only ever used from its owner group, and keeping the other groups' copies
159
 * alive would make every release require all groups' cooperation.
160
 */
161
void protocol_localize_rx_fds(void)
162
0
{
163
0
  struct protocol *proto;
164
0
  struct receiver *rx;
165
166
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
167
0
  list_for_each_entry(proto, &protocols, list) {
168
0
    list_for_each_entry(rx, &proto->receivers, proto_list) {
169
0
      int fd = rx->fd;
170
171
0
      if (fd < 0 || rx_owner_tgid(rx) == tgid)
172
0
        continue;
173
174
0
      fdtab[fd].owner = NULL;
175
0
      fdtab[fd].state = 0;
176
0
      fdtab[fd].thread_mask = 0;
177
0
      fdtab[fd].update_mask = 0;
178
0
      fdtab[fd].running_mask = 0;
179
0
      HA_ATOMIC_STORE(&fdtab[fd].refc_tgid, 0);
180
0
      close(fd);
181
0
    }
182
0
  }
183
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
184
0
}
185
186
static uint getsocks_busy;
187
188
/*
189
 * Collect file descriptor from other thread groups, if they have their
190
 * own file descriptors table.
191
 */
192
int protocol_getsocks_foreign_fds(struct receiver ***orxs, int **ofds)
193
0
{
194
0
  struct protocol *proto;
195
0
  struct receiver *rx;
196
0
  struct receiver **rxs;
197
0
  int *fds;
198
0
  int nb, filled, done, i;
199
0
  uint idle = 0;
200
201
0
  *orxs = NULL;
202
0
  *ofds = NULL;
203
204
0
  if (MAX_TGROUPS < 2 || !(global.tune.options & GTUNE_NO_TG_FD_SHARING) || global.nbtgroups < 2)
205
0
    return 0;
206
207
  /* a concurrent collection would overwrite the per-receiver slots, and
208
   * two of them blocking their groups' runner threads would deadlock.
209
   */
210
0
  if (!HA_ATOMIC_CAS(&getsocks_busy, &idle, 1)) {
211
0
    ha_warning("_getsocks: a collection is already in progress, giving up.\n");
212
0
    return -1;
213
0
  }
214
215
  /* first pass: count the candidates */
216
0
  nb = 0;
217
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
218
0
  list_for_each_entry(proto, &protocols, list) {
219
0
    list_for_each_entry(rx, &proto->receivers, proto_list) {
220
0
      if (rx->fd < 0 || rx_owner_tgid(rx) == tgid)
221
0
        continue;
222
0
      if (!(ha_tgroup_ctx[rx_owner_tgid(rx) - 1].fdtab[rx->fd].state & FD_EXPORTED))
223
0
        continue;
224
0
      nb++;
225
0
    }
226
0
  }
227
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
228
229
0
  if (!nb) {
230
0
    HA_ATOMIC_STORE(&getsocks_busy, 0);
231
0
    return 0;
232
0
  }
233
234
0
  rxs = calloc(nb, sizeof(*rxs));
235
0
  fds = calloc(nb, sizeof(*fds));
236
0
  if (!rxs || !fds) {
237
0
    free(rxs);
238
0
    free(fds);
239
0
    HA_ATOMIC_STORE(&getsocks_busy, 0);
240
0
    ha_warning("Failed to allocate memory to transfer other groups' sockets\n");
241
0
    return -1;
242
0
  }
243
244
  /* second pass: arm the requests. A copy left over by a previous
245
   * timed-out collection is closed on the way.
246
   */
247
0
  filled = 0;
248
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
249
0
  list_for_each_entry(proto, &protocols, list) {
250
0
    list_for_each_entry(rx, &proto->receivers, proto_list) {
251
0
      int old;
252
253
0
      if (filled >= nb)
254
0
        break;
255
0
      if (rx->fd < 0 || rx_owner_tgid(rx) == tgid)
256
0
        continue;
257
0
      if (!(ha_tgroup_ctx[rx_owner_tgid(rx) - 1].fdtab[rx->fd].state & FD_EXPORTED))
258
0
        continue;
259
260
0
      old = rx->agent.getsocks_fd;
261
0
      if (old >= 0)
262
0
        close(old);
263
0
      HA_ATOMIC_STORE(&rx->agent.getsocks_fd, -1);
264
0
      rxs[filled++] = rx;
265
0
      rx_agent_getsocks_request(rx, tgid);
266
0
    }
267
0
  }
268
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
269
0
  nb = filled;
270
271
0
  for (i = 0; i < 50; i++) {
272
0
    rx_xfer_drain(tgid - 1);
273
0
    done = 1;
274
0
    for (filled = 0; filled < nb; filled++) {
275
0
      if (HA_ATOMIC_LOAD(&rxs[filled]->agent.getsocks_fd) < 0)
276
0
        done = 0;
277
0
    }
278
0
    if (done)
279
0
      break;
280
    /* XXX: we're waiting for other thread groups to send their
281
     * fds, let's sleep for a bit.
282
     */
283
0
    usleep(10000);
284
0
  }
285
286
0
  done = 0;
287
0
  for (i = 0; i < nb; i++) {
288
0
    int f = HA_ATOMIC_LOAD(&rxs[i]->agent.getsocks_fd);
289
290
0
    if (f < 0) {
291
0
      ha_warning("_getsocks: could not get a copy of a listener FD from thread group %u, the new process will have to bind it itself.\n",
292
0
                 rx_owner_tgid(rxs[i]));
293
0
      continue;
294
0
    }
295
0
    HA_ATOMIC_STORE(&rxs[i]->agent.getsocks_fd, -1);
296
0
    rxs[done] = rxs[i];
297
0
    fds[done] = f;
298
0
    done++;
299
0
  }
300
301
0
  HA_ATOMIC_STORE(&getsocks_busy, 0);
302
303
0
  if (!done) {
304
0
    free(rxs);
305
0
    free(fds);
306
0
    return 0;
307
0
  }
308
0
  *orxs = rxs;
309
0
  *ofds = fds;
310
0
  return done;
311
0
}
312
313
/* binds all listeners of all registered protocols. Returns a composition
314
 * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
315
 */
316
int protocol_bind_all(int verbose)
317
0
{
318
0
  struct protocol *proto;
319
0
  struct listener *listener;
320
0
  struct receiver *receiver;
321
0
  char msg[1000];
322
0
  char *errmsg;
323
0
  int err, lerr;
324
325
0
  err = 0;
326
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
327
0
  list_for_each_entry(proto, &protocols, list) {
328
0
    list_for_each_entry(receiver, &proto->receivers, proto_list) {
329
0
      listener = LIST_ELEM(receiver, struct listener *, rx);
330
#ifdef USE_QUIC
331
      if ((proto == &proto_quic4 || proto == &proto_quic6) &&
332
          !protocol_may_bind_quic(listener))
333
        continue;
334
#endif
335
336
0
      lerr = proto->fam->bind(receiver, &errmsg);
337
0
      err |= lerr;
338
339
      /* errors are reported if <verbose> is set or if they are fatal */
340
0
      if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
341
0
        struct proxy *px = listener->bind_conf->frontend;
342
343
0
        if (lerr & ERR_ALERT)
344
0
          ha_alert("Binding [%s:%d] for %s %s: protocol %s: %s.\n",
345
0
                   listener->bind_conf->file, listener->bind_conf->line,
346
0
             proxy_type_str(px), px->id, proto->name, errmsg);
347
0
        else if (lerr & ERR_WARN)
348
0
          ha_warning("Binding [%s:%d] for %s %s: protocol %s: %s.\n",
349
0
                     listener->bind_conf->file, listener->bind_conf->line,
350
0
               proxy_type_str(px), px->id, proto->name, errmsg);
351
0
      }
352
0
      if (lerr != ERR_NONE)
353
0
        ha_free(&errmsg);
354
355
0
      if (lerr & ERR_ABORT)
356
0
        break;
357
358
0
      if (lerr & ~ERR_WARN)
359
0
        continue;
360
361
      /* for now there's still always a listening function */
362
0
      BUG_ON(!proto->listen);
363
0
      lerr = proto->listen(listener, msg, sizeof(msg));
364
0
      err |= lerr;
365
366
0
      if (verbose || (lerr & (ERR_FATAL | ERR_ABORT))) {
367
0
        struct proxy *px = listener->bind_conf->frontend;
368
369
0
        if (lerr & ERR_ALERT)
370
0
          ha_alert("Starting [%s:%d] for %s %s: protocol %s: %s.\n",
371
0
                   listener->bind_conf->file, listener->bind_conf->line,
372
0
             proxy_type_str(px), px->id, proto->name, msg);
373
0
        else if (lerr & ERR_WARN)
374
0
          ha_warning("Starting [%s:%d] for %s %s: protocol %s: %s.\n",
375
0
                     listener->bind_conf->file, listener->bind_conf->line,
376
0
               proxy_type_str(px), px->id, proto->name, msg);
377
0
      }
378
0
      if (lerr & ERR_ABORT)
379
0
        break;
380
0
    }
381
0
    if (err & ERR_ABORT)
382
0
      break;
383
0
  }
384
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
385
0
  return err;
386
0
}
387
388
/* unbinds all listeners of all registered protocols. They are also closed.
389
 * This must be performed before calling exit() in order to get a chance to
390
 * remove file-system based sockets and pipes.
391
 * Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
392
 */
393
int protocol_unbind_all(void)
394
0
{
395
0
  struct protocol *proto;
396
0
  struct listener *listener;
397
0
  int err;
398
399
0
  err = 0;
400
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
401
0
  list_for_each_entry(proto, &protocols, list) {
402
0
    list_for_each_entry(listener, &proto->receivers, rx.proto_list)
403
0
      unbind_listener(listener);
404
0
  }
405
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
406
0
  return err;
407
0
}
408
409
/* stops all listeners of all registered protocols. This will normally catch
410
 * every single listener, all protocols included. This is to be used during
411
 * soft_stop() only. It does not return any error.
412
 */
413
void protocol_stop_now(void)
414
0
{
415
0
  struct protocol *proto;
416
0
  struct listener *listener, *lback;
417
418
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
419
0
  list_for_each_entry(proto, &protocols, list) {
420
0
    list_for_each_entry_safe(listener, lback, &proto->receivers, rx.proto_list)
421
0
      stop_listener(listener, 0, 1, 0);
422
0
  }
423
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
424
0
}
425
426
/* suspends all listeners of all registered protocols. This is typically
427
 * used on SIG_TTOU to release all listening sockets for the time needed to
428
 * try to bind a new process. The listeners enter LI_PAUSED or LI_ASSIGNED.
429
 * It returns ERR_NONE, with ERR_FATAL on failure.
430
 */
431
int protocol_pause_all(void)
432
0
{
433
0
  struct protocol *proto;
434
0
  struct listener *listener;
435
0
  int err;
436
437
0
  err = 0;
438
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
439
0
  list_for_each_entry(proto, &protocols, list) {
440
0
    list_for_each_entry(listener, &proto->receivers, rx.proto_list)
441
0
      if (!suspend_listener(listener, 0, 0))
442
0
        err |= ERR_FATAL;
443
0
  }
444
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
445
0
  return err;
446
0
}
447
448
/* resumes all listeners of all registered protocols. This is typically used on
449
 * SIG_TTIN to re-enable listening sockets after a new process failed to bind.
450
 * The listeners switch to LI_READY/LI_FULL. It returns ERR_NONE, with ERR_FATAL
451
 * on failure.
452
 */
453
int protocol_resume_all(void)
454
0
{
455
0
  struct protocol *proto;
456
0
  struct listener *listener;
457
0
  int err;
458
459
0
  err = 0;
460
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
461
0
  list_for_each_entry(proto, &protocols, list) {
462
0
    list_for_each_entry(listener, &proto->receivers, rx.proto_list)
463
0
      if (!resume_listener(listener, 0, 0))
464
0
        err |= ERR_FATAL;
465
0
  }
466
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
467
0
  return err;
468
0
}
469
470
/* enables all listeners of all registered protocols. This is intended to be
471
 * used after a fork() to enable reading on all file descriptors. Returns ERR_NONE.
472
 */
473
int protocol_enable_all(void)
474
0
{
475
0
  struct protocol *proto;
476
0
  struct listener *listener;
477
478
0
  HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
479
0
  list_for_each_entry(proto, &protocols, list) {
480
0
    list_for_each_entry(listener, &proto->receivers, rx.proto_list)
481
0
      enable_listener(listener);
482
0
  }
483
0
  HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
484
0
  return ERR_NONE;
485
0
}
486
487
/*
488
 * Local variables:
489
 *  c-indent-level: 8
490
 *  c-basic-offset: 8
491
 * End:
492
 */