• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

36.32
/pdns/unix_utility.cc
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
#include "utility.hh"
26
#include <cstring>
27
#include <fcntl.h>
28
#include <unistd.h>
29
#include <stdlib.h>
30
#include "pdnsexception.hh"
31
#include "logger.hh"
32
#include "logging.hh"
33
#include "misc.hh"
34
#include <pwd.h>
35
#include <grp.h>
36
#include <sys/types.h>
37
#include <sys/select.h>
38

39
#ifdef NEED_INET_NTOP_PROTO
40
extern "C" {
41
const char *inet_ntop(int af, const void *src, char *dst, size_t cnt);
42
}
43
#endif
44

45

46
#include "namespaces.hh"
47

48

49
// Connects to socket with timeout
50
int Utility::timed_connect( Utility::sock_t sock,
51
    const sockaddr *addr,
52
    Utility::socklen_t sockaddr_size,
53
    int timeout_sec,
54
    int timeout_usec )
55
{
×
56
  fd_set set;
×
57
  struct timeval timeout;
×
58
  int ret;
×
59

60
  timeout.tv_sec = timeout_sec;
×
61
  timeout.tv_usec = timeout_usec;
×
62

63
  FD_ZERO(&set);
×
64
  FD_SET(sock, &set);
×
65

66
  setNonBlocking(sock);
×
67

68
  if ((ret = connect (sock, addr, sockaddr_size)) < 0) {
×
69
    if (errno != EINPROGRESS)
×
70
      return ret;
×
71
  }
×
72

73
  ret = select(sock + 1, nullptr, &set, nullptr, &timeout);
×
74
  setBlocking(sock);
×
75

76
  return ret;
×
77
}
×
78

79

80

81
void Utility::setBindAny([[maybe_unused]] int af, [[maybe_unused]] sock_t sock)
82
{
×
83
  const int one = 1;
×
84

85
  (void) one; // avoids 'unused var' warning on systems that have none of the defines checked below
×
86
#ifdef IP_FREEBIND
×
87
  if (setsockopt(sock, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0) {
×
88
    int err = errno;
×
89
    SLOG(g_log<<Logger::Warning<<"Warning: IP_FREEBIND setsockopt failed: "<<stringerror(err)<<endl,
×
90
         g_slog->withName("runtime")->error(Logr::Warning, err, "Warning: IP_FREEBIND setsockopt failed"));
×
91
  }
×
92
#endif
×
93

94
#ifdef IP_BINDANY
95
  if (af == AF_INET)
96
    if (setsockopt(sock, IPPROTO_IP, IP_BINDANY, &one, sizeof(one)) < 0) {
97
      int err = errno;
98
      SLOG(g_log<<Logger::Warning<<"Warning: IP_BINDANY setsockopt failed: "<<stringerror(err)<<endl,
99
           g_slog->withName("runtime")->error(Logr::Warning, err, "Warning: IP_BINDANY setsockopt failed"));
100
    }
101
#endif
102
#ifdef IPV6_BINDANY
103
  if (af == AF_INET6) {
104
    if (setsockopt(sock, IPPROTO_IPV6, IPV6_BINDANY, &one, sizeof(one)) < 0) {
105
      int err = errno;
106
      SLOG(g_log<<Logger::Warning<<"Warning: IPV6_BINDANY setsockopt failed: "<<stringerror(err)<<endl,
107
           g_slog->withName("runtime")->error(Logr::Warning, err, "Warning: IPV6_BINDANY setsockopt failed"));
108
    }
109
  }
110
#endif
111
#ifdef SO_BINDANY
112
  if (setsockopt(sock, SOL_SOCKET, SO_BINDANY, &one, sizeof(one)) < 0) {
113
    int err = errno;
114
    SLOG(g_log<<Logger::Warning<<"Warning: SO_BINDANY setsockopt failed: "<<stringerror(err)<<endl,
115
         g_slog->withName("runtime")->error(Logr::Warning, err, "Warning: SO_BINDANY setsockopt failed"));
116
  }
117
#endif
118
}
×
119

120
const char *Utility::inet_ntop(int af, const char *src, char *dst, size_t size)
121
{
×
122
  return ::inet_ntop(af,src,dst,size);
×
123
}
×
124

125
unsigned int Utility::sleep(unsigned int sec)
126
{
×
127
  return ::sleep(sec);
×
128
}
×
129

130
void Utility::usleep(unsigned long usec)
131
{
14✔
132
  struct timespec ts;
14✔
133
  ts.tv_sec = usec / 1000000;
14✔
134
  ts.tv_nsec = (usec % 1000000) * 1000;
14✔
135
  // POSIX.1 recommends using nanosleep instead of usleep
136
  ::nanosleep(&ts, nullptr);
14✔
137
}
14✔
138

139

140
// Drops the program's group privileges.
141
void Utility::dropGroupPrivs( uid_t uid, gid_t gid )
142
{
153✔
143
  if(gid && gid != getegid()) {
153!
144
    if(setgid(gid)<0) {
×
145
      int err = errno;
×
146
      SLOG(g_log<<Logger::Critical<<"Unable to set effective group id to "<<gid<<": "<<stringerror(err)<<endl,
×
147
           g_slog->withName("runtime")->error(Logr::Critical, err, "Unable to set effective group id", "gid", Logging::Loggable(gid)));
×
148
      exit(1);
×
149
    }
×
150
    else {
×
151
      SLOG(g_log<<Logger::Info<<"Set effective group id to "<<gid<<endl,
×
152
           g_slog->withName("runtime")->info(Logr::Info, "Set effective group id", "gid", Logging::Loggable(gid)));
×
153
    }
×
154
    struct passwd *pw=getpwuid(uid);
×
155
    if(!pw) {
×
156
      SLOG(g_log<<Logger::Warning<<"Unable to determine user name for uid "<<uid<<endl,
×
157
           g_slog->withName("runtime")->info(Logr::Warning, "Unable to determine user name", "uid", Logging::Loggable(uid)));
×
158
      if (setgroups(0, nullptr)<0) {
×
159
        int err = errno;
×
160
        SLOG(g_log<<Logger::Critical<<"Unable to drop supplementary gids: "<<stringerror(err)<<endl,
×
161
             g_slog->withName("runtime")->error(Logr::Critical, err, "Unable to drop supplementary gids"));
×
162
        exit(1);
×
163
      }
×
164
    } else {
×
165
      if (initgroups(pw->pw_name, gid)<0) {
×
166
        int err = errno;
×
167
        SLOG(g_log<<Logger::Critical<<"Unable to set supplementary groups: "<<stringerror(err)<<endl,
×
168
             g_slog->withName("runtime")->error(Logr::Critical, err, "Unable to set supplementary groups"));
×
169
        exit(1);
×
170
      }
×
171
    }
×
172
  }
×
173
}
153✔
174

175

176
// Drops the program's user privileges.
177
void Utility::dropUserPrivs( uid_t uid )
178
{
153✔
179
  if(uid && uid != geteuid()) {
153!
180
    if(setuid(uid)<0) {
×
181
      int err = errno;
×
182
      SLOG(g_log<<Logger::Critical<<"Unable to set effective user id to "<<uid<<": "<<stringerror(err)<<endl,
×
183
           g_slog->withName("runtime")->error(Logr::Critical, err, "Unable to set effective user id", "uid", Logging::Loggable(uid)));
×
184
      exit(1);
×
185
    }
×
186
    else {
×
187
      SLOG(g_log<<Logger::Info<<"Set effective user id to "<<uid<<endl,
×
188
           g_slog->withName("runtime")->info(Logr::Info, "Set effective user", "uid", Logging::Loggable(uid)));
×
189
    }
×
190
  }
×
191
}
153✔
192

193

194
// Returns the current process id.
195
Utility::pid_t Utility::getpid( )
196
{
306✔
197
  return ::getpid();
306✔
198
}
306✔
199

200

201
// Returns the current time.
202
int Utility::gettimeofday( struct timeval *tv, void * /* tz */)
203
{
20,774✔
204
  return ::gettimeofday(tv, nullptr);
20,774✔
205
}
20,774✔
206

207
// Writes a vector.
208
int Utility::writev(int socket, const iovec *vector, size_t count )
209
{
240✔
210
  return ::writev(socket,vector,count);
240✔
211
}
240✔
212

213
/* this is cut and pasted from dietlibc, gratefully copied! */
214
static int isleap(int year) {
109,206✔
215
  /* every fourth year is a leap year except for century years that are
216
   * not divisible by 400. */
217
  return (!(year%4) && ((year%100) || !(year%400)));
109,206!
218
}
109,206✔
219

220
time_t Utility::timegm(struct tm *const t)
221
{
109,206✔
222
  const static short spm[13] = /* days per month -- nonleap! */
109,206✔
223
  { 0,
109,206✔
224
    (31),
109,206✔
225
    (31+28),
109,206✔
226
    (31+28+31),
109,206✔
227
    (31+28+31+30),
109,206✔
228
    (31+28+31+30+31),
109,206✔
229
    (31+28+31+30+31+30),
109,206✔
230
    (31+28+31+30+31+30+31),
109,206✔
231
    (31+28+31+30+31+30+31+31),
109,206✔
232
    (31+28+31+30+31+30+31+31+30),
109,206✔
233
    (31+28+31+30+31+30+31+31+30+31),
109,206✔
234
    (31+28+31+30+31+30+31+31+30+31+30),
109,206✔
235
    (31+28+31+30+31+30+31+31+30+31+30+31),
109,206✔
236
  };
109,206✔
237

238
  time_t  day;
109,206✔
239
  time_t  i;
109,206✔
240
  time_t years = t->tm_year - 70;
109,206✔
241

242
  if (t->tm_sec>60) { t->tm_min += t->tm_sec/60; t->tm_sec%=60; }
109,206!
243
  if (t->tm_min>60) { t->tm_hour += t->tm_min/60; t->tm_min%=60; }
109,206!
244
  if (t->tm_hour>60) { t->tm_mday += t->tm_hour/60; t->tm_hour%=60; }
109,206!
245
  if (t->tm_mon>11) { t->tm_year += t->tm_mon/12; t->tm_mon%=12; }
109,206!
246

247
  while (t->tm_mday>spm[1+t->tm_mon]) {
109,206!
248
    if (t->tm_mon==1 && isleap(t->tm_year+1900)) {
×
249
      if (t->tm_mon==31+29) break;
×
250
      --t->tm_mday;
×
251
    }
×
252
    t->tm_mday-=spm[t->tm_mon];
×
253
    ++t->tm_mon;
×
254
    if (t->tm_mon>11) { t->tm_mon=0; ++t->tm_year; }
×
255
  }
×
256

257
  if (t->tm_year < 70)
109,206!
258
    return (time_t) -1;
×
259
  /* Days since 1970 is 365 * number of years + number of leap years since 1970 */
260
  day  = years * 365 + (years + 1) / 4;
109,206✔
261

262
  /* After 2100 we have to subtract 3 leap years for every 400 years
263
     This is not intuitive. Most mktime implementations do not support
264
     dates after 2059, anyway, so we might leave this out for its
265
     bloat. */
266
  if ((years -= 131) >= 0) {
109,206!
267
    years /= 100;
×
268
    day -= (years >> 2) * 3 + 1;
×
269
    if ((years &= 3) == 3) years--;
×
270
    day -= years;
×
271
  }
×
272

273
  day += t->tm_yday = spm [t->tm_mon] + t->tm_mday-1 + ( isleap (t->tm_year+1900)  &  (t->tm_mon > 1) );
109,206✔
274

275
  /* day is now the number of days since 'Jan 1 1970' */
276
  i = 7;
109,206✔
277
  // coverity[store_truncates_time_t]
278
  t->tm_wday = (day + 4) % i;                        /* Sunday=0, Monday=1, ..., Saturday=6 */
109,206✔
279

280
  i = 24;
109,206✔
281
  day *= i;
109,206✔
282
  i = 60;
109,206✔
283
  return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
109,206✔
284
}
109,206✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc