1/*
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* Inline QOS functions */
10#include "comm/Connection.h"
11#include "Debug.h"
12
13int
14Ip::Qos::setSockTos(const int fd, tos_t tos, int type)
15{
16    // Bug 3731: FreeBSD produces 'invalid option'
17    // unless we pass it a 32-bit variable storing 8-bits of data.
18    // NP: it is documented as 'int' for all systems, even those like Linux which accept 8-bit char
19    //     so we convert to a int before setting.
20    int bTos = tos;
21
22    debugs(50, 3, "for FD " << fd << " to " << bTos);
23
24    if (type == AF_INET) {
25#if defined(IP_TOS)
26        const int x = setsockopt(fd, IPPROTO_IP, IP_TOS, &bTos, sizeof(bTos));
27        if (x < 0) {
28            int xerrno = errno;
29            debugs(50, 2, "setsockopt(IP_TOS) on " << fd << ": " << xstrerr(xerrno));
30        }
31        return x;
32#else
33        debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(IP_TOS) not supported on this platform");
34        return -1;
35#endif
36    } else { // type == AF_INET6
37#if defined(IPV6_TCLASS)
38        const int x = setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &bTos, sizeof(bTos));
39        if (x < 0) {
40            int xerrno = errno;
41            debugs(50, 2, "setsockopt(IPV6_TCLASS) on " << fd << ": " << xstrerr(xerrno));
42        }
43        return x;
44#else
45        debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(IPV6_TCLASS) not supported on this platform");
46        return -1;
47#endif
48    }
49
50    /* CANNOT REACH HERE */
51}
52
53int
54Ip::Qos::setSockTos(const Comm::ConnectionPointer &conn, tos_t tos)
55{
56    const int x = Ip::Qos::setSockTos(conn->fd, tos, conn->remote.isIPv4() ? AF_INET : AF_INET6);
57    conn->tos = (x >= 0) ? tos : 0;
58    return x;
59}
60
61int
62Ip::Qos::setSockNfmark(const int fd, nfmark_t mark)
63{
64#if SO_MARK && USE_LIBCAP
65    debugs(50, 3, "for FD " << fd << " to " << mark);
66    const int x = setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(nfmark_t));
67    if (x < 0) {
68        int xerrno = errno;
69        debugs(50, 2, "setsockopt(SO_MARK) on " << fd << ": " << xstrerr(xerrno));
70    }
71    return x;
72#elif USE_LIBCAP
73    debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(SO_MARK) not supported on this platform");
74    return -1;
75#else
76    debugs(50, DBG_IMPORTANT, "WARNING: Netfilter marking disabled (netfilter marking requires build with LIBCAP)");
77    return -1;
78#endif
79}
80
81int
82Ip::Qos::setSockNfmark(const Comm::ConnectionPointer &conn, nfmark_t mark)
83{
84    const int x = Ip::Qos::setSockNfmark(conn->fd, mark);
85    conn->nfmark = (x >= 0) ? mark : 0;
86    return x;
87}
88
89bool
90Ip::Qos::Config::isHitTosActive() const
91{
92    return (tosLocalHit || tosSiblingHit || tosParentHit || tosMiss || preserveMissTos);
93}
94
95bool
96Ip::Qos::Config::isHitNfmarkActive() const
97{
98    return (markLocalHit || markSiblingHit || markParentHit || markMiss || preserveMissMark);
99}
100
101bool
102Ip::Qos::Config::isAclNfmarkActive() const
103{
104    acl_nfmark * nfmarkAcls [] = { nfmarkToServer, nfmarkToClient };
105
106    for (int i=0; i<2; ++i) {
107        while (nfmarkAcls[i]) {
108            acl_nfmark *l = nfmarkAcls[i];
109            if (l->nfmark > 0)
110                return true;
111            nfmarkAcls[i] = l->next;
112        }
113    }
114
115    return false;
116}
117
118bool
119Ip::Qos::Config::isAclTosActive() const
120{
121    acl_tos * tosAcls [] = { tosToServer, tosToClient };
122
123    for (int i=0; i<2; ++i) {
124        while (tosAcls[i]) {
125            acl_tos *l = tosAcls[i];
126            if (l->tos > 0)
127                return true;
128            tosAcls[i] = l->next;
129        }
130    }
131
132    return false;
133}
134
135