Coverage Report

Created: 2026-04-01 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/Tuple.cxx
Line
Count
Source
1
#if defined(HAVE_CONFIG_H)
2
#include "config.h"
3
#endif
4
5
#include "resip/stack/Tuple.hxx"
6
#include "rutil/compat.hxx"
7
8
#include <iostream>
9
#include <string.h>
10
#include <sys/types.h>
11
#include "rutil/ResipAssert.h"
12
13
#if !defined (WIN32)
14
#include <arpa/inet.h>
15
#include <netinet/in.h>
16
#if defined(__APPLE__) && !defined(s6_addr16)
17
#define s6_addr16 __u6_addr.__u6_addr16
18
#endif
19
#endif
20
21
#include "rutil/Data.hxx"
22
#include "rutil/DnsUtil.hxx"
23
#include "rutil/GenericIPAddress.hxx"
24
#include "rutil/HashMap.hxx"
25
#include "rutil/DigestStream.hxx"
26
#include "rutil/Logger.hxx"
27
#ifdef USE_NETNS
28
#   include "rutil/NetNs.hxx"
29
#endif
30
31
using namespace resip;
32
33
#define RESIPROCATE_SUBSYSTEM Subsystem::DNS
34
35
Tuple::Tuple() : 
36
35.5k
   mFlowKey(0),
37
35.5k
   mTransportKey(0),
38
35.5k
   onlyUseExistingConnection(false),
39
35.5k
   mTransportType(UNKNOWN_TRANSPORT)
40
35.5k
{
41
35.5k
   sockaddr_in* addr4 = (sockaddr_in*)&mSockaddr;
42
35.5k
   memset(addr4, 0, sizeof(sockaddr_in));
43
35.5k
   mSockaddr.sa_family = AF_INET;
44
35.5k
}
45
46
Tuple::Tuple(const GenericIPAddress& genericAddress, TransportType type, 
47
             const Data& targetDomain) : 
48
0
   mFlowKey(0),
49
0
   mTransportKey(0),
50
0
   onlyUseExistingConnection(false),
51
0
   mTransportType(type),
52
0
   mTargetDomain(targetDomain)
53
0
{
54
0
   setSockaddr(genericAddress);
55
0
}
56
57
58
Tuple::Tuple(const Data& printableAddr, 
59
             int port,
60
             IpVersion ipVer,
61
             TransportType type,
62
             const Data& targetDomain,
63
             const Data& netNs) :
64
0
   mFlowKey(0),
65
0
   mTransportKey(0),
66
0
   onlyUseExistingConnection(false),
67
0
   mTransportType(type),
68
0
   mTargetDomain(targetDomain),
69
0
   mNetNs(netNs)
70
0
{
71
0
   if (ipVer == V4)
72
0
   {
73
0
      memset(&m_anonv4, 0, sizeof(m_anonv4));
74
0
      m_anonv4.sin_family = AF_INET;
75
0
      m_anonv4.sin_port = htons(port);
76
77
0
      if (printableAddr.empty())
78
0
      {
79
0
         m_anonv4.sin_addr.s_addr = htonl(INADDR_ANY); 
80
0
      }
81
0
      else
82
0
      {
83
0
         DnsUtil::inet_pton( printableAddr, m_anonv4.sin_addr);
84
0
      }
85
0
   }
86
0
   else
87
0
   {
88
0
#ifdef USE_IPV6
89
0
      memset(&m_anonv6, 0, sizeof(m_anonv6));
90
0
      m_anonv6.sin6_family = AF_INET6;
91
0
      m_anonv6.sin6_port = htons(port);
92
0
      if (printableAddr.empty())
93
0
      {
94
0
         m_anonv6.sin6_addr = in6addr_any;
95
0
      }
96
0
      else
97
0
      {
98
0
         DnsUtil::inet_pton( printableAddr, m_anonv6.sin6_addr);
99
0
      }
100
#else
101
      // avoid asserts since Tuples created via printableAddr can be created from items 
102
      // received from the wire or from configuration settings.  Just create an IPV4 inaddr_any tuple.
103
      //assert(0);  
104
      memset(&m_anonv4, 0, sizeof(m_anonv4));
105
      m_anonv4.sin_family = AF_INET;
106
      m_anonv4.sin_port = htons(port);
107
      m_anonv4.sin_addr.s_addr = htonl(INADDR_ANY); 
108
#endif
109
0
   }
110
0
}
111
112
Tuple::Tuple(const Data& printableAddr, 
113
             int port,
114
             TransportType ptype,
115
             const Data& targetDomain,
116
             const Data& netNs) : 
117
12
   mFlowKey(0),
118
12
   mTransportKey(0),
119
12
   onlyUseExistingConnection(false),
120
12
   mTransportType(ptype),
121
12
   mTargetDomain(targetDomain),
122
12
   mNetNs(netNs)
123
12
{
124
12
   if (DnsUtil::isIpV4Address(printableAddr))
125
10
   {
126
10
      memset(&m_anonv4, 0, sizeof(m_anonv4));
127
      
128
10
      DnsUtil::inet_pton( printableAddr, m_anonv4.sin_addr);
129
10
      m_anonv4.sin_family = AF_INET;
130
10
      m_anonv4.sin_port = htons(port);
131
10
   }
132
2
#ifdef USE_IPV6
133
2
   else if(DnsUtil::isIpV6Address(printableAddr))
134
2
   {
135
2
      memset(&m_anonv6, 0, sizeof(m_anonv6));
136
2
      DnsUtil::inet_pton( printableAddr, m_anonv6.sin6_addr);
137
2
      m_anonv6.sin6_family = AF_INET6;
138
2
      m_anonv6.sin6_port = htons(port);
139
2
   }
140
0
#endif
141
0
   else
142
0
   {
143
      // avoid asserts since Tuples created via printableAddr can be created from items 
144
      // received from the wire or from configuration settings.  Just create an IPV4 inaddr_any tuple.
145
      // assert(0);  
146
0
      memset(&m_anonv4, 0, sizeof(m_anonv4));
147
0
      m_anonv4.sin_family = AF_INET;
148
0
      m_anonv4.sin_port = htons(port);
149
0
      m_anonv4.sin_addr.s_addr = htonl(INADDR_ANY);
150
0
   }
151
12
}
152
153
Tuple::Tuple(const in_addr& ipv4,
154
             int port,
155
             TransportType ptype,
156
             const Data& targetDomain,
157
             const Data& netNs)
158
0
     :mFlowKey(0),
159
0
     mTransportKey(0),
160
0
     onlyUseExistingConnection(false),
161
0
     mTransportType(ptype),
162
0
     mTargetDomain(targetDomain),
163
0
     mNetNs(netNs)
164
0
{
165
0
   memset(&m_anonv4, 0, sizeof(sockaddr_in));
166
0
   m_anonv4.sin_addr = ipv4;
167
0
   m_anonv4.sin_port = htons(port);
168
0
   m_anonv4.sin_family = AF_INET;
169
0
}
170
171
#ifdef USE_IPV6
172
Tuple::Tuple(const in6_addr& ipv6,
173
             int port,
174
             TransportType ptype,
175
             const Data& targetDomaina,
176
             const Data& netNs)
177
0
     :mFlowKey(0),
178
0
     mTransportKey(0),
179
0
     onlyUseExistingConnection(false),
180
0
     mTransportType(ptype),
181
0
     mTargetDomain(targetDomaina),
182
0
     mNetNs(netNs)
183
0
{
184
0
   memset(&m_anonv6, 0, sizeof(sockaddr_in6));
185
0
   m_anonv6.sin6_addr = ipv6;
186
0
   m_anonv6.sin6_port = htons(port);
187
0
   m_anonv6.sin6_family = AF_INET6;
188
0
}
189
#endif
190
191
Tuple::Tuple(const struct sockaddr& addr, 
192
             TransportType ptype,
193
             const Data& targetDomain) : 
194
0
   mFlowKey(0),
195
0
   mTransportKey(0),
196
0
   onlyUseExistingConnection(false),
197
0
   mSockaddr(addr),
198
0
   mTransportType(ptype),
199
0
   mTargetDomain(targetDomain)
200
0
{
201
0
   if (addr.sa_family == AF_INET)   
202
0
   {
203
0
      m_anonv4 = (sockaddr_in&)(addr);
204
0
   }
205
0
#ifdef USE_IPV6
206
0
   else if (addr.sa_family == AF_INET6)
207
0
   {
208
0
      m_anonv6 = (sockaddr_in6&)(addr);
209
0
   }
210
0
#endif
211
0
   else
212
0
   {
213
0
      resip_assert(0);
214
0
   }
215
0
}
216
217
void
218
Tuple::copySockaddrAnyPort(sockaddr *sa)
219
0
{
220
0
   memcpy(sa, &mSockaddr, length());
221
   // zero the port number
222
0
   if (sa->sa_family == AF_INET)
223
0
   {
224
0
      ((sockaddr_in*)sa)->sin_port = 0;
225
0
   }
226
0
#ifdef USE_IPV6
227
0
   else if (sa->sa_family == AF_INET6)
228
0
   {
229
0
      ((sockaddr_in6*)sa)->sin6_port = 0;
230
0
   }
231
0
#endif
232
0
   else
233
0
   {
234
0
      resip_assert(0);
235
0
   }
236
0
}
237
238
void
239
Tuple::setSockaddr(const GenericIPAddress& addr)
240
0
{
241
0
  if (addr.isVersion4())
242
0
  {
243
0
     m_anonv4 = addr.v4Address;
244
0
  }
245
0
  else
246
0
#ifdef USE_IPV6
247
0
  {
248
0
     m_anonv6 = addr.v6Address;
249
0
  }
250
#else
251
  {
252
     resip_assert(0);
253
  }
254
#endif
255
0
}
256
257
#ifdef USE_NETNS
258
#   define TOKEN_SIZE 8
259
#   define TOKEN_IP_ADDRESS_OFFSET 4
260
#else
261
0
#   define TOKEN_SIZE 7
262
0
#   define TOKEN_IP_ADDRESS_OFFSET 3
263
#endif
264
265
void
266
Tuple::writeBinaryToken(const resip::Tuple& tuple, resip::Data& container, const Data& salt)
267
0
{
268
   // .bwc. Maybe should just write the raw sockaddr into a buffer, and tack
269
   // on the flowid and onlyUseExistingConnection flag. Would require 10 extra
270
   // bytes for V6, and 14 extra bytes for V4. 
271
   // V6: sin6_len(1), sin6_flowinfo(4), flowId(4), onlyUseExistingConnection(1)
272
   // V4: sin_family(2 instead of 1), sin_zero(8), flowId(4), onlyUseExistingConnection(1)
273
0
   uint32_t rawToken[TOKEN_SIZE];
274
0
   memset(&rawToken, 0, TOKEN_SIZE * 4);
275
276
0
   rawToken[0] = tuple.mFlowKey;
277
278
0
   rawToken[1] = tuple.mTransportKey;
279
280
   // 0xXXXX0000
281
0
   rawToken[2] += (tuple.getPort() << 16);
282
283
   // 0x0000XX00
284
0
   rawToken[2] += (tuple.getType() << 8);
285
286
   // 0x000000X0
287
0
   if(tuple.onlyUseExistingConnection)
288
0
   {
289
0
      rawToken[2] += 0x00000010;
290
0
   }
291
292
#ifdef USE_NETNS
293
   rawToken[3] = NetNs::getNetNsId(tuple.getNetNs());
294
#endif
295
296
0
#ifdef USE_IPV6
297
0
   if(tuple.ipVersion()==V6)
298
0
   {
299
      // 0x0000000X
300
0
      rawToken[2] += 0x00000001;
301
0
      in6_addr address = reinterpret_cast<const sockaddr_in6&>(tuple.getSockaddr()).sin6_addr;
302
0
      resip_assert(sizeof(address)==16);
303
0
      memcpy(&rawToken[TOKEN_IP_ADDRESS_OFFSET],&address,16);
304
0
   }
305
0
   else
306
0
#endif
307
0
   {
308
0
      in_addr address = reinterpret_cast<const sockaddr_in&>(tuple.getSockaddr()).sin_addr;
309
0
      resip_assert(sizeof(address)==4);
310
0
      memcpy(&rawToken[TOKEN_IP_ADDRESS_OFFSET],&address,4);
311
0
   }
312
   
313
0
   container.clear();
314
0
   container.reserve(((tuple.ipVersion()==V6) ? TOKEN_SIZE*4 : (TOKEN_SIZE-3)*4) + (salt.empty() ? 0 : 32));
315
0
   container.append((char*)&rawToken[0],(tuple.ipVersion()==V6) ? TOKEN_SIZE*4 : (TOKEN_SIZE-3)*4);
316
317
0
   if(!salt.empty())
318
0
   {
319
      // TODO - potentially use SHA1 HMAC for stronger encryption
320
0
      DigestStream ms;
321
0
      ms << container << salt;
322
0
      container += ms.getHex();
323
0
   }
324
0
}
325
326
327
Tuple
328
Tuple::makeTupleFromBinaryToken(const resip::Data& binaryFlowToken, const Data& salt)
329
0
{
330
   // To check if size is valid, we first need the IP version, so make sure the token is at least
331
   // the size of an IPv4 token
332
0
   if(binaryFlowToken.size()<16)
333
0
   {
334
      // !bwc! Should not assert here, since this sort of thing
335
      // can come off the wire easily.
336
      // TODO Throw an exception here?
337
0
      DebugLog(<<"binary flow token was too small: " << binaryFlowToken.size());
338
0
      return Tuple();
339
0
   }
340
341
0
   const uint32_t* rawToken=reinterpret_cast<const uint32_t*>(binaryFlowToken.data());
342
343
0
   FlowKey mFlowKey=rawToken[0];
344
0
   TransportKey transportKey=rawToken[1];
345
346
0
   IpVersion version = (rawToken[2] & 0x00000001 ? V6 : V4);
347
348
0
   bool isRealFlow = (rawToken[2] & 0x00000010 ? true : false);
349
350
0
   uint8_t temp = (TransportType)((rawToken[2] & 0x00000F00) >> 8);
351
0
   if(temp >= MAX_TRANSPORT)
352
0
   {
353
0
      DebugLog(<<"Garbage transport type in flow token: " << temp );
354
0
      return Tuple();
355
0
   }
356
0
   TransportType type = (TransportType)temp;
357
358
0
   uint16_t port= (rawToken[2] >> 16);
359
360
   // Now that we have the version we can do a more accurate check on the size
361
0
   if(!((version==V4 && salt.empty() && binaryFlowToken.size()==(TOKEN_SIZE-3)*4) ||
362
0
        (version==V4 && !salt.empty() && binaryFlowToken.size()==(TOKEN_SIZE-3)*4 + 32) ||
363
0
        (version==V6 && salt.empty() && binaryFlowToken.size()==TOKEN_SIZE*4) ||
364
0
        (version==V6 && !salt.empty() && binaryFlowToken.size()==TOKEN_SIZE*4 + 32)))
365
0
   {
366
0
      DebugLog(<<"Binary flow token is the wrong size for its IP version.");
367
0
      return Tuple();
368
0
   }
369
370
   // If salt is specified, validate HMAC
371
0
   if(!salt.empty())
372
0
   {
373
0
      unsigned int tokenSizeLessHMAC = version == V4 ? (TOKEN_SIZE-3)*4 : TOKEN_SIZE*4;
374
0
      Data flowTokenLessHMAC(Data::Share, binaryFlowToken.data(), tokenSizeLessHMAC);
375
0
      Data flowTokenHMAC(Data::Share, binaryFlowToken.data()+tokenSizeLessHMAC, 32);
376
0
      DigestStream ms;
377
0
      ms << flowTokenLessHMAC << salt;
378
0
      if(ms.getHex() != flowTokenHMAC)
379
0
      {
380
0
         DebugLog(<<"Binary flow token has invalid HMAC, not our token");
381
0
         return Tuple();
382
0
      }
383
0
   }
384
385
0
   Data netNs("");
386
#ifdef USE_NETNS
387
   int netNsId = rawToken[3];
388
   try
389
   {
390
      netNs = NetNs::getNetNsName(netNsId);
391
   }
392
   catch (const NetNs::Exception& e)
393
   {
394
       ErrLog(<< "Tuple binary token contained netns id: " << netNsId << "which does not exist." 
395
               << e);
396
   }
397
#endif
398
399
0
   if(version==V6)
400
0
   {
401
0
#ifdef USE_IPV6
402
0
      in6_addr address;
403
0
      resip_assert(sizeof(address)==16);
404
0
      memcpy(&address,&rawToken[TOKEN_IP_ADDRESS_OFFSET],16);
405
0
      Tuple result(address, port, type, Data::Empty, netNs);
406
#else
407
      Tuple result(resip::Data::Empty, port, type, Data::Empty, netNs);
408
#endif
409
0
      result.mFlowKey=(FlowKey)mFlowKey;
410
0
      result.mTransportKey = (TransportKey)transportKey;
411
0
      result.onlyUseExistingConnection=isRealFlow;
412
0
      return result;
413
0
   }
414
415
0
   in_addr address;
416
0
   resip_assert(sizeof(address)==4);
417
0
   memcpy(&address,&rawToken[TOKEN_IP_ADDRESS_OFFSET],4);
418
0
   Tuple result(address, port, type, Data::Empty, netNs);
419
0
   result.mFlowKey=(FlowKey)mFlowKey;
420
0
   result.mTransportKey = (TransportKey)transportKey;
421
0
   result.onlyUseExistingConnection=isRealFlow;
422
0
   return result;
423
0
}
424
425
Data 
426
Tuple::presentationFormat() const
427
0
{
428
0
#ifdef USE_IPV6
429
0
   if (isV4())
430
0
   {
431
0
      return Tuple::inet_ntop(*this);
432
0
   }
433
0
   else if (IN6_IS_ADDR_V4MAPPED(&m_anonv6.sin6_addr))
434
0
   {
435
0
      return DnsUtil::inet_ntop(*(reinterpret_cast<const in_addr*>(
436
0
                                   (reinterpret_cast<const unsigned char*>(&m_anonv6.sin6_addr) + 12))));
437
0
   }
438
0
   else
439
0
   {
440
0
      return Tuple::inet_ntop(*this);
441
0
   }
442
#else
443
      return Tuple::inet_ntop(*this);
444
#endif
445
446
0
}
447
448
void
449
Tuple::setPort(int port)
450
0
{
451
0
   if (mSockaddr.sa_family == AF_INET) // v4   
452
0
   {
453
0
      m_anonv4.sin_port = htons(port);
454
0
   }
455
0
   else
456
0
   {
457
0
#ifdef USE_IPV6
458
0
      m_anonv6.sin6_port = htons(port);
459
#else
460
      resip_assert(0);
461
#endif
462
0
   }
463
0
}
464
465
int 
466
Tuple::getPort() const
467
0
{
468
0
   if (mSockaddr.sa_family == AF_INET) // v4   
469
0
   {
470
0
      return ntohs(m_anonv4.sin_port);
471
0
   }
472
0
   else
473
0
   {
474
0
#ifdef USE_IPV6
475
0
      return ntohs(m_anonv6.sin6_port);
476
#else
477
      resip_assert(0);
478
#endif
479
0
   }
480
   
481
0
   return -1;
482
0
}
483
484
bool
485
Tuple::isAnyInterface() const
486
0
{
487
0
   if (isV4())
488
0
   {
489
0
      return m_anonv4.sin_addr.s_addr == htonl(INADDR_ANY); 
490
0
   }
491
0
#if defined (USE_IPV6)
492
0
   else
493
0
   {
494
0
      return memcmp(&m_anonv6.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0;
495
0
   }
496
#else
497
   return false;
498
#endif
499
0
}
500
501
static Tuple loopbackv4("127.0.0.1",0,UNKNOWN_TRANSPORT);
502
bool
503
Tuple::isLoopback() const
504
0
{
505
0
   if(ipVersion()==V4)
506
0
   {
507
0
      return isEqualWithMask(loopbackv4,8,true,true);
508
0
   }
509
0
   else if (ipVersion()==V6)
510
0
   {
511
0
#ifdef USE_IPV6
512
0
#if defined(__linux__) || defined(__APPLE__) || defined(WIN32)
513
0
      return IN6_IS_ADDR_LOOPBACK(&(m_anonv6.sin6_addr)) != 0;
514
#else
515
      return ((*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[0])) == 0) && 
516
             (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[4])) == 0) && 
517
             (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[8])) == 0) && 
518
             (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[12])) == ntohl(1)));
519
#endif
520
0
#endif
521
0
   }
522
0
   else
523
0
   {
524
0
      resip_assert(0);
525
0
   }
526
   
527
0
   return false;
528
0
}
529
530
bool 
531
Tuple::isV4() const
532
0
{
533
0
   return mSockaddr.sa_family == AF_INET;
534
0
}
535
536
IpVersion 
537
Tuple::ipVersion() const
538
0
{
539
0
   return mSockaddr.sa_family == AF_INET ? V4 : V6;
540
0
}
541
542
static Tuple v4privateaddrbase1("10.0.0.0",0,UNKNOWN_TRANSPORT);
543
static Tuple v4privateaddrbase2("172.16.0.0",0,UNKNOWN_TRANSPORT);
544
static Tuple v4privateaddrbase3("192.168.0.0",0,UNKNOWN_TRANSPORT);
545
static Tuple v4sharedaddrbase1("100.64.0.0",0,UNKNOWN_TRANSPORT);
546
547
#ifdef USE_IPV6
548
static Tuple v6privateaddrbase("fc00::",0,UNKNOWN_TRANSPORT);
549
#endif
550
551
bool 
552
Tuple::isPrivateAddress() const
553
0
{
554
0
   if(ipVersion()==V4)
555
0
   {
556
      // RFC 1918 & RFC 6598
557
0
      return isEqualWithMask(v4privateaddrbase1,8,true,true) ||  // 10.0.0.0        -   10.255.255.255  (10/8 prefix)
558
0
             isEqualWithMask(v4privateaddrbase2,12,true,true) || // 172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
559
0
             isEqualWithMask(v4privateaddrbase3,16,true,true) || // 192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
560
0
             isEqualWithMask(v4sharedaddrbase1,10,true,true) ||  // 100.64.0.0      -   100.127.255.255 (100.64/110 prefix)
561
0
             isLoopback();
562
0
   }
563
0
#ifdef USE_IPV6
564
0
   else if (ipVersion()==V6)
565
0
   {
566
      // RFC 4193
567
      // ?slg? should we look specifically for ipv4 mapped/compatible address and apply V4 rules to them?
568
0
      return isEqualWithMask(v6privateaddrbase,7,true,true) ||  // fc00::/7
569
0
             isLoopback();
570
0
   }
571
0
#endif
572
0
   else
573
0
   {
574
0
      resip_assert(0);
575
0
   }
576
   
577
0
   return false;
578
0
}
579
580
socklen_t
581
Tuple::length() const
582
0
{
583
0
   if (mSockaddr.sa_family == AF_INET) // v4
584
0
   {
585
0
      return sizeof(sockaddr_in);
586
0
   }
587
0
#ifdef USE_IPV6
588
0
   else  if (mSockaddr.sa_family == AF_INET6) // v6
589
0
   {
590
0
      return sizeof(sockaddr_in6);
591
0
   }
592
0
#endif
593
594
0
   resip_assert(0);
595
0
   return 0;
596
0
}
597
598
599
bool
600
Tuple::operator==(const Tuple& rhs) const
601
0
{
602
0
   return isEqual(rhs);
603
0
}
604
605
bool
606
Tuple::isEqual(const Tuple& compare, bool ignorePort, bool ignoreTransport) const
607
0
{
608
0
   if (ignoreTransport || getType() == compare.getType())  // check if transport type matches
609
0
   {
610
0
      if (mSockaddr.sa_family == compare.mSockaddr.sa_family)
611
0
      {
612
0
         if (mSockaddr.sa_family == AF_INET) // v4
613
0
         {
614
0
            return ((ignorePort || m_anonv4.sin_port == compare.m_anonv4.sin_port) &&
615
0
               memcmp(&m_anonv4.sin_addr, &compare.m_anonv4.sin_addr, sizeof(in_addr)) == 0 &&
616
0
               compare.mNetNs == mNetNs);
617
0
         }
618
0
         else // v6
619
0
         {
620
0
#ifdef USE_IPV6
621
0
            return ((ignorePort || m_anonv6.sin6_port == compare.m_anonv6.sin6_port) &&
622
0
               memcmp(&m_anonv6.sin6_addr, &compare.m_anonv6.sin6_addr, sizeof(in6_addr)) == 0 &&
623
0
               compare.mNetNs == mNetNs);
624
#else
625
            resip_assert(0);
626
#endif
627
0
         }
628
0
      }
629
0
   }
630
631
   // !dlb! don't include connection 
632
633
0
   return false;
634
0
}
635
636
bool
637
Tuple::operator<(const Tuple& rhs) const
638
0
{
639
0
   if (mTransportType < rhs.mTransportType)
640
0
   {
641
0
      return true;
642
0
   }
643
0
   else if (mTransportType > rhs.mTransportType)
644
0
   {
645
0
      return false;
646
0
   }
647
648
#ifdef USE_NETNS
649
   // netns needs to be checked before port and address as the port/address 
650
   // comparison bails out in equal case.  Ideally netns comparison should
651
   // be last as its the most expensive comparison.  For now putting it here
652
   // for minimal code change
653
   else if(mNetNs < rhs.mNetNs)
654
   {
655
       return(true);
656
   }
657
   else if(mNetNs > rhs.mNetNs)
658
   {
659
       return(false);
660
   }
661
#endif
662
663
0
   else if (mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
664
0
   {
665
0
      int c=memcmp(&m_anonv4.sin_addr,
666
0
                   &rhs.m_anonv4.sin_addr,
667
0
                   sizeof(in_addr));
668
669
0
      if (c < 0)
670
0
      {
671
0
         return true;
672
0
      }
673
0
      else if (c > 0)
674
0
      {
675
0
         return false;
676
0
      }
677
0
      else if (m_anonv4.sin_port < rhs.m_anonv4.sin_port)
678
0
      {
679
0
         return true;
680
0
      }
681
0
      else
682
0
      {
683
0
         return false;
684
0
      }
685
0
   }
686
0
#ifdef USE_IPV6
687
0
   else if (mSockaddr.sa_family == AF_INET6 &&
688
0
            rhs.mSockaddr.sa_family == AF_INET6)
689
0
   {
690
0
      int c = memcmp(&m_anonv6.sin6_addr,
691
0
                     &rhs.m_anonv6.sin6_addr,
692
0
                     sizeof(in6_addr));
693
0
      if (c < 0)
694
0
      {
695
0
         return true;
696
0
      }
697
0
      else if (c > 0)
698
0
      {
699
0
         return false;
700
0
      }
701
0
      else if (m_anonv6.sin6_port < rhs.m_anonv6.sin6_port)
702
0
      {
703
0
         return true;
704
0
      }
705
0
      else
706
0
      {
707
0
         return false;
708
0
      }
709
0
   }
710
0
   else if (mSockaddr.sa_family == AF_INET6 &&
711
0
            rhs.mSockaddr.sa_family == AF_INET)
712
0
   {
713
0
      return true;
714
0
   }
715
0
   else if (mSockaddr.sa_family == AF_INET &&
716
0
            rhs.mSockaddr.sa_family == AF_INET6)
717
0
   {
718
0
      return false;
719
0
   }
720
0
#endif
721
722
0
   else
723
0
   {
724
      //assert(0);
725
0
      return false;
726
0
   }
727
0
}
728
729
EncodeStream&
730
resip::operator<<(EncodeStream& ostrm, const Tuple& tuple)
731
0
{
732
0
   ostrm << "[ " ;
733
   
734
0
#ifdef USE_IPV6
735
0
   if (tuple.mSockaddr.sa_family == AF_INET6)
736
0
   {
737
0
      ostrm << "V6 " << DnsUtil::inet_ntop(tuple.m_anonv6.sin6_addr) << " port=" << tuple.getPort();
738
0
   }
739
0
   else
740
0
#endif
741
0
   if (tuple.mSockaddr.sa_family == AF_INET)
742
0
   {
743
0
      ostrm << "V4 " << Tuple::inet_ntop(tuple) << ":" << tuple.getPort();
744
0
   }
745
0
   else
746
0
   {
747
0
      resip_assert(0);
748
0
   }
749
750
0
   ostrm << " " << Tuple::toData(tuple.mTransportType);
751
752
0
   if (!tuple.mTargetDomain.empty())
753
0
   {
754
0
       ostrm << " targetDomain=" << tuple.mTargetDomain;
755
0
   }
756
   
757
0
   if(tuple.mFlowKey != 0)
758
0
   {
759
0
      ostrm << " flowKey=" << tuple.mFlowKey;
760
0
   }
761
762
0
   if(tuple.mTransportKey != 0)
763
0
   {
764
0
      ostrm << " transportKey=" << tuple.mTransportKey;
765
0
   }
766
767
#ifdef USE_NETNS
768
      ostrm << " mNetNs=" << tuple.mNetNs;
769
#endif
770
771
0
   ostrm << " ]";
772
   
773
0
   return ostrm;
774
0
}
775
776
size_t 
777
Tuple::hash() const
778
0
{
779
   // !dlb! do not include the connection
780
0
#ifdef USE_IPV6
781
0
   if (mSockaddr.sa_family == AF_INET6)
782
0
   {
783
0
      const sockaddr_in6& in6 =
784
0
         reinterpret_cast<const sockaddr_in6&>(mSockaddr);
785
786
0
      return size_t(Data(Data::Share, (const char *)&in6.sin6_addr.s6_addr, sizeof(in6.sin6_addr.s6_addr)).hash() +
787
#ifdef USE_NETNS
788
                    mNetNs.hash() +
789
#endif
790
0
                    5*in6.sin6_port +
791
0
                    25*mTransportType);
792
0
   }
793
0
   else
794
0
#endif
795
0
   {
796
0
      const sockaddr_in& in4 =
797
0
         reinterpret_cast<const sockaddr_in&>(mSockaddr);
798
         
799
0
      return size_t(in4.sin_addr.s_addr +
800
#ifdef USE_NETNS
801
                    mNetNs.hash() +
802
#endif
803
0
                    5*in4.sin_port +
804
0
                    25*mTransportType);
805
0
   }    
806
0
}
807
808
HashValueImp(resip::Tuple, data.hash());
809
810
TransportType
811
Tuple::toTransport(const Data& transportName)
812
0
{
813
0
   return resip::toTransportType(transportName); // TransportTypes.hxx
814
0
};
815
816
const Data&
817
Tuple::toData(TransportType type)
818
0
{
819
0
   return resip::toData(type);  // TransportTypes.hxx
820
0
}
821
822
const Data&
823
Tuple::toDataLower(TransportType type)
824
0
{
825
0
   return resip::toDataLower(type);  // TransportTypes.hxx
826
0
}
827
828
Data
829
Tuple::inet_ntop(const Tuple& tuple)
830
0
{
831
0
#ifdef USE_IPV6
832
0
   if (!tuple.isV4())
833
0
   {
834
0
      const sockaddr_in6& addr = reinterpret_cast<const sockaddr_in6&>(tuple.getSockaddr());
835
0
      return DnsUtil::inet_ntop(addr.sin6_addr);
836
0
   }
837
0
   else
838
0
#endif
839
0
   {
840
0
      const sockaddr_in& addr = reinterpret_cast<const sockaddr_in&>(tuple.getSockaddr());
841
0
      return DnsUtil::inet_ntop(addr.sin_addr);
842
0
   }
843
0
}
844
845
bool
846
Tuple::isEqualWithMask(const Tuple& compare, short mask, bool ignorePort, bool ignoreTransport) const
847
0
{
848
0
   if(ignoreTransport || getType() == compare.getType())  // check if transport type matches
849
0
   {
850
0
      if (mSockaddr.sa_family == compare.getSockaddr().sa_family && mSockaddr.sa_family == AF_INET) // v4
851
0
      {
852
0
         sockaddr_in* addr1 = (sockaddr_in*)&mSockaddr;
853
0
         sockaddr_in* addr2 = (sockaddr_in*)&compare.getSockaddr();
854
855
0
         return ((ignorePort || addr1->sin_port == addr2->sin_port)  &&
856
0
                 (addr1->sin_addr.s_addr & htonl((0xFFFFFFFF << (32 - mask)))) == 
857
0
                  (addr2->sin_addr.s_addr & htonl((0xFFFFFFFF << (32 - mask)))));
858
0
      }
859
0
#ifdef USE_IPV6
860
0
      else if (mSockaddr.sa_family == compare.getSockaddr().sa_family && mSockaddr.sa_family == AF_INET6) // v6
861
0
      {
862
0
         sockaddr_in6* addr1 = (sockaddr_in6*)&mSockaddr;
863
0
         sockaddr_in6* addr2 = (sockaddr_in6*)&compare.getSockaddr();
864
865
0
         if(ignorePort || addr1->sin6_port == addr2->sin6_port)
866
0
         {
867
0
            uint32_t mask6part;
868
0
            uint32_t temp;
869
0
            bool match=true;
870
0
            for(int i = 3; i >= 0; i--)
871
0
            {
872
0
               if(mask <= 32*i)
873
0
               {
874
0
                  mask6part = 0;
875
0
               }
876
0
               else
877
0
               {
878
0
                  temp = mask - 32*i;
879
0
                  if(temp >= 32)
880
0
                  {
881
0
                     mask6part = 0xffffffff;
882
0
                  }
883
0
                  else
884
0
                  {
885
0
                     mask6part = 0xffffffff << (32 - temp);
886
0
                  }
887
0
               }
888
#ifdef WIN32
889
               if((*((unsigned long*)&addr1->sin6_addr.u.Word[i*2]) & htonl(mask6part)) != 
890
                  (*((unsigned long*)&addr2->sin6_addr.u.Word[i*2]) & htonl(mask6part)))
891
#elif defined(sun)
892
               // sun has no s6_addr16
893
               if((*((unsigned long*)&addr1->sin6_addr._S6_un._S6_u32[i]) & htonl(mask6part)) !=
894
                  (*((unsigned long*)&addr2->sin6_addr._S6_un._S6_u32[i]) & htonl(mask6part)))
895
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
896
               // bsd has no s6_addr16
897
               if((*((unsigned long*)&addr1->sin6_addr.__u6_addr.__u6_addr32[i]) & htonl(mask6part)) != 
898
                  (*((unsigned long*)&addr2->sin6_addr.__u6_addr.__u6_addr32[i]) & htonl(mask6part)))         
899
#else
900
0
               if((*((uint32_t*)&addr1->sin6_addr.s6_addr16[i*2]) & htonl(mask6part)) != 
901
0
                  (*((uint32_t*)&addr2->sin6_addr.s6_addr16[i*2]) & htonl(mask6part)))
902
0
#endif
903
0
               {
904
0
                  match=false;
905
0
                  break;
906
0
               }
907
0
            }
908
0
            if(match)
909
0
            {
910
0
               return true;
911
0
            }
912
0
         }
913
0
      }
914
0
#endif
915
0
   }
916
0
   return false;
917
0
}
918
919
// special comparitors
920
bool
921
Tuple::AnyInterfaceCompare::operator()(const Tuple& lhs,
922
                                       const Tuple& rhs) const
923
0
{
924
0
   if (lhs.mTransportType < rhs.mTransportType)
925
0
   {
926
0
      return true;
927
0
   }
928
0
   else if (lhs.mTransportType > rhs.mTransportType)
929
0
   {
930
0
      return false;
931
0
   }
932
0
   else if (lhs.mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
933
0
   {
934
0
      if (lhs.m_anonv4.sin_port < rhs.m_anonv4.sin_port)
935
0
      {
936
0
         return true;
937
0
      }
938
0
      else
939
0
      {
940
0
         return false;
941
0
      }
942
0
   }
943
0
#ifdef USE_IPV6
944
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
945
0
            rhs.mSockaddr.sa_family == AF_INET6)
946
0
   {
947
0
      if (lhs.m_anonv6.sin6_port < rhs.m_anonv6.sin6_port)
948
0
      {
949
0
         return true;
950
0
      }
951
0
      else
952
0
      {
953
0
         return false;
954
0
      }
955
0
   }
956
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
957
0
            rhs.mSockaddr.sa_family == AF_INET)
958
0
   {
959
0
      return true;
960
0
   }
961
0
   else if (lhs.mSockaddr.sa_family == AF_INET &&
962
0
            rhs.mSockaddr.sa_family == AF_INET6)
963
0
   {
964
0
      return false;
965
0
   }
966
0
#endif
967
0
   else
968
0
   {
969
0
      return false;
970
0
   }
971
0
};
972
973
bool
974
Tuple::AnyPortCompare::operator()(const Tuple& lhs,
975
                                  const Tuple& rhs) const
976
0
{
977
0
   if (lhs.mTransportType < rhs.mTransportType)
978
0
   {
979
0
      return true;
980
0
   }
981
0
   else if (lhs.mTransportType > rhs.mTransportType)
982
0
   {
983
0
      return false;
984
0
   }
985
986
   // transport types equal, so compare addresses
987
0
   if (lhs.mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
988
0
   {
989
0
      int c = memcmp(&lhs.m_anonv4.sin_addr,
990
0
                     &rhs.m_anonv4.sin_addr,
991
0
                     sizeof(in_addr));
992
993
0
      if (c < 0)
994
0
      {
995
0
         return true;
996
0
      }
997
0
      else if (c > 0)
998
0
      {
999
0
         return false;
1000
0
      }
1001
0
   }
1002
0
#ifdef USE_IPV6
1003
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
1004
0
            rhs.mSockaddr.sa_family == AF_INET6)
1005
0
   {
1006
0
      int c = memcmp(&lhs.m_anonv6.sin6_addr,
1007
0
                     &rhs.m_anonv6.sin6_addr,
1008
0
                     sizeof(in6_addr));
1009
0
      if (c < 0)
1010
0
      {
1011
0
         return true;
1012
0
      }
1013
0
      else if (c > 0)
1014
0
      {
1015
0
         return false;
1016
0
      }
1017
0
   }
1018
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
1019
0
            rhs.mSockaddr.sa_family == AF_INET)
1020
0
   {
1021
0
      return true;
1022
0
   }
1023
0
   else if (lhs.mSockaddr.sa_family == AF_INET &&
1024
0
            rhs.mSockaddr.sa_family == AF_INET6)
1025
0
   {
1026
0
      return false;
1027
0
   }
1028
0
#endif
1029
#ifdef USE_NETNS
1030
   // transport type and addresses are equal, so compare netns
1031
   if(lhs.mNetNs < rhs.mNetNs)
1032
   {
1033
       //DebugLog(<< "AnyPortCompare netns less than (l=" << lhs.mNetNs << ", r=" << rhs.mNetNs);
1034
       return(true);
1035
   }
1036
   else if(rhs.mNetNs < lhs.mNetNs)
1037
   {
1038
       //DebugLog(<< "AnyPortCompare netns greater than (l=" << lhs.mNetNs << ", r=" << rhs.mNetNs);
1039
       return(false);
1040
   }
1041
   //DebugLog(<< "AnyPortCompare netns equal to (l=\"" << lhs.mNetNs << "\", r=\"" << rhs.mNetNs << "\"");
1042
#endif
1043
1044
0
   return false;
1045
0
}
1046
1047
bool
1048
Tuple::FlowKeyCompare::operator()(const Tuple& lhs,
1049
                                  const Tuple& rhs) const
1050
0
{
1051
0
   if (lhs == rhs)
1052
0
   {
1053
0
      return lhs.mFlowKey < rhs.mFlowKey;
1054
0
   }
1055
0
   return lhs < rhs;
1056
0
};
1057
1058
GenericIPAddress 
1059
Tuple::toGenericIPAddress() const
1060
0
{
1061
0
   if (isV4())
1062
0
   {
1063
0
      return GenericIPAddress(m_anonv4);
1064
0
   }
1065
0
   else
1066
0
#ifdef USE_IPV6
1067
0
  {
1068
0
      return GenericIPAddress(m_anonv6);
1069
0
  }
1070
#else
1071
  {
1072
     resip_assert(0);
1073
     return m_anonv4; //bogus
1074
  }
1075
#endif
1076
0
}
1077
1078
bool
1079
Tuple::AnyPortAnyInterfaceCompare::operator()(const Tuple& lhs,
1080
                                              const Tuple& rhs) const
1081
0
{
1082
0
   if (lhs.mTransportType < rhs.mTransportType)
1083
0
   {
1084
0
      return true;
1085
0
   }
1086
0
   else if (lhs.mTransportType > rhs.mTransportType)
1087
0
   {
1088
0
      return false;
1089
0
   }
1090
0
#ifdef USE_IPV6
1091
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
1092
0
            rhs.mSockaddr.sa_family == AF_INET)
1093
0
   {
1094
0
      return true;
1095
0
   }
1096
0
   else if (lhs.mSockaddr.sa_family == AF_INET &&
1097
0
            rhs.mSockaddr.sa_family == AF_INET6)
1098
0
   {
1099
0
      return false;
1100
0
   }
1101
0
#endif
1102
0
   else
1103
0
   {
1104
0
      return false;
1105
0
   }
1106
0
};
1107
1108
/* ====================================================================
1109
 * The Vovida Software License, Version 1.0 
1110
 * 
1111
 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
1112
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
1113
 * 
1114
 * Redistribution and use in source and binary forms, with or without
1115
 * modification, are permitted provided that the following conditions
1116
 * are met:
1117
 * 
1118
 * 1. Redistributions of source code must retain the above copyright
1119
 *    notice, this list of conditions and the following disclaimer.
1120
 * 
1121
 * 2. Redistributions in binary form must reproduce the above copyright
1122
 *    notice, this list of conditions and the following disclaimer in
1123
 *    the documentation and/or other materials provided with the
1124
 *    distribution.
1125
 * 
1126
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1127
 *    and "Vovida Open Communication Application Library (VOCAL)" must
1128
 *    not be used to endorse or promote products derived from this
1129
 *    software without prior written permission. For written
1130
 *    permission, please contact vocal@vovida.org.
1131
 *
1132
 * 4. Products derived from this software may not be called "VOCAL", nor
1133
 *    may "VOCAL" appear in their name, without prior written
1134
 *    permission of Vovida Networks, Inc.
1135
 * 
1136
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1137
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1138
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1139
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
1140
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1141
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1142
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1143
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1144
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1145
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1146
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1147
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1148
 * DAMAGE.
1149
 * 
1150
 * ====================================================================
1151
 * 
1152
 * This software consists of voluntary contributions made by Vovida
1153
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1154
 * Inc.  For more information on Vovida Networks, Inc., please see
1155
 * <http://www.vovida.org/>.
1156
 *
1157
 */