mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-17 00:41:00 +01:00
Commit 0d06df6 ("MINOR: sock: introduce sock_inet and sock_unix")
made use of isdigit() on the UNIX socket path without casting the
value to unsigned char, breaking the build on cygwin and possibly
other platforms. No backport is needed.
100 lines
2.7 KiB
C
100 lines
2.7 KiB
C
/*
|
|
* SOCK_UNIX socket management
|
|
*
|
|
* Copyright 2000-2020 Willy Tarreau <w@1wt.eu>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/un.h>
|
|
|
|
#include <haproxy/api.h>
|
|
#include <haproxy/listener.h>
|
|
#include <haproxy/namespace.h>
|
|
#include <haproxy/sock_unix.h>
|
|
#include <haproxy/tools.h>
|
|
|
|
|
|
/* PLEASE NOTE for functions below:
|
|
*
|
|
* The address family SHOULD always be checked. In some cases a function will
|
|
* be used in a situation where the address family is guaranteed (e.g. protocol
|
|
* definitions), so the test may be avoided. This special case must then be
|
|
* mentioned in the comment before the function definition.
|
|
*/
|
|
|
|
|
|
/* Compares two AF_UNIX sockaddr addresses. Returns 0 if they match or non-zero
|
|
* if they do not match. It also supports ABNS socket addresses (those starting
|
|
* with \0). For regular UNIX sockets however, this does explicitly support
|
|
* matching names ending exactly with .XXXXX.tmp which are newly bound sockets
|
|
* about to be replaced; this suffix is then ignored. Note that our UNIX socket
|
|
* paths are always zero-terminated.
|
|
*/
|
|
int sock_unix_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b)
|
|
{
|
|
const struct sockaddr_un *au = (const struct sockaddr_un *)a;
|
|
const struct sockaddr_un *bu = (const struct sockaddr_un *)b;
|
|
int idx, dot, idx2;
|
|
|
|
if (a->ss_family != b->ss_family)
|
|
return -1;
|
|
|
|
if (a->ss_family != AF_UNIX)
|
|
return -1;
|
|
|
|
if (au->sun_path[0] != bu->sun_path[0])
|
|
return -1;
|
|
|
|
if (au->sun_path[0] == 0)
|
|
return memcmp(au->sun_path, bu->sun_path, sizeof(au->sun_path));
|
|
|
|
idx = 1; dot = 0;
|
|
while (au->sun_path[idx] == bu->sun_path[idx]) {
|
|
if (au->sun_path[idx] == 0)
|
|
return 0;
|
|
if (au->sun_path[idx] == '.')
|
|
dot = idx;
|
|
idx++;
|
|
}
|
|
|
|
/* Now we have a difference. It's OK if they are within or after a
|
|
* sequence of digits following a dot, and are followed by ".tmp".
|
|
*/
|
|
if (!dot)
|
|
return -1;
|
|
|
|
/* First, check in path "a" */
|
|
if (au->sun_path[idx] != 0) {
|
|
for (idx2 = dot + 1; idx2 && isdigit((unsigned char)au->sun_path[idx2]);)
|
|
idx2++;
|
|
if (strcmp(au->sun_path + idx2, ".tmp") != 0)
|
|
return -1;
|
|
}
|
|
|
|
/* Then check in path "b" */
|
|
if (bu->sun_path[idx] != 0) {
|
|
for (idx2 = dot + 1; idx2 && isdigit((unsigned char)bu->sun_path[idx2]); idx2++)
|
|
;
|
|
if (strcmp(bu->sun_path + idx2, ".tmp") != 0)
|
|
return -1;
|
|
}
|
|
|
|
/* OK that's a match */
|
|
return 0;
|
|
}
|