Coverage Report

Created: 2025-11-05 06:27

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/MD5Stream.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
33.7k
   mFlowKey(0),
37
33.7k
   mTransportKey(0),
38
33.7k
   onlyUseExistingConnection(false),
39
33.7k
   mTransportType(UNKNOWN_TRANSPORT)
40
33.7k
{
41
33.7k
   sockaddr_in* addr4 = (sockaddr_in*)&mSockaddr;
42
33.7k
   memset(addr4, 0, sizeof(sockaddr_in));
43
33.7k
   mSockaddr.sa_family = AF_INET;
44
33.7k
}
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 if USE_SSL is defined for stronger encryption
320
0
      MD5Stream 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
      MD5Stream 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 Tuple::operator==(const Tuple& rhs) const
600
0
{
601
0
   if (mSockaddr.sa_family == rhs.mSockaddr.sa_family)
602
0
   {
603
0
      if (mSockaddr.sa_family == AF_INET) // v4
604
0
      {
605
0
         return (m_anonv4.sin_port == rhs.m_anonv4.sin_port &&
606
0
                 mTransportType == rhs.mTransportType &&
607
0
                 memcmp(&m_anonv4.sin_addr, &rhs.m_anonv4.sin_addr, sizeof(in_addr)) == 0 &&
608
0
                 rhs.mNetNs == mNetNs);
609
0
      }
610
0
      else // v6
611
0
      {
612
0
#ifdef USE_IPV6
613
0
         return (m_anonv6.sin6_port == rhs.m_anonv6.sin6_port &&
614
0
                 mTransportType == rhs.mTransportType &&
615
0
                 memcmp(&m_anonv6.sin6_addr, &rhs.m_anonv6.sin6_addr, sizeof(in6_addr)) == 0 &&
616
0
                 rhs.mNetNs == mNetNs);
617
#else
618
         resip_assert(0);
619
         return false;
620
#endif
621
0
      }
622
0
   }
623
0
   else
624
0
   {
625
0
      return false;
626
0
   }
627
628
   // !dlb! don't include connection 
629
0
}
630
631
bool
632
Tuple::operator<(const Tuple& rhs) const
633
0
{
634
0
   if (mTransportType < rhs.mTransportType)
635
0
   {
636
0
      return true;
637
0
   }
638
0
   else if (mTransportType > rhs.mTransportType)
639
0
   {
640
0
      return false;
641
0
   }
642
643
#ifdef USE_NETNS
644
   // netns needs to be checked before port and address as the port/address 
645
   // comparison bails out in equal case.  Ideally netns comparison should
646
   // be last as its the most expensive comparison.  For now putting it here
647
   // for minimal code change
648
   else if(mNetNs < rhs.mNetNs)
649
   {
650
       return(true);
651
   }
652
   else if(mNetNs > rhs.mNetNs)
653
   {
654
       return(false);
655
   }
656
#endif
657
658
0
   else if (mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
659
0
   {
660
0
      int c=memcmp(&m_anonv4.sin_addr,
661
0
                   &rhs.m_anonv4.sin_addr,
662
0
                   sizeof(in_addr));
663
664
0
      if (c < 0)
665
0
      {
666
0
         return true;
667
0
      }
668
0
      else if (c > 0)
669
0
      {
670
0
         return false;
671
0
      }
672
0
      else if (m_anonv4.sin_port < rhs.m_anonv4.sin_port)
673
0
      {
674
0
         return true;
675
0
      }
676
0
      else
677
0
      {
678
0
         return false;
679
0
      }
680
0
   }
681
0
#ifdef USE_IPV6
682
0
   else if (mSockaddr.sa_family == AF_INET6 &&
683
0
            rhs.mSockaddr.sa_family == AF_INET6)
684
0
   {
685
0
      int c = memcmp(&m_anonv6.sin6_addr,
686
0
                     &rhs.m_anonv6.sin6_addr,
687
0
                     sizeof(in6_addr));
688
0
      if (c < 0)
689
0
      {
690
0
         return true;
691
0
      }
692
0
      else if (c > 0)
693
0
      {
694
0
         return false;
695
0
      }
696
0
      else if (m_anonv6.sin6_port < rhs.m_anonv6.sin6_port)
697
0
      {
698
0
         return true;
699
0
      }
700
0
      else
701
0
      {
702
0
         return false;
703
0
      }
704
0
   }
705
0
   else if (mSockaddr.sa_family == AF_INET6 &&
706
0
            rhs.mSockaddr.sa_family == AF_INET)
707
0
   {
708
0
      return true;
709
0
   }
710
0
   else if (mSockaddr.sa_family == AF_INET &&
711
0
            rhs.mSockaddr.sa_family == AF_INET6)
712
0
   {
713
0
      return false;
714
0
   }
715
0
#endif
716
717
0
   else
718
0
   {
719
      //assert(0);
720
0
      return false;
721
0
   }
722
0
}
723
724
EncodeStream&
725
resip::operator<<(EncodeStream& ostrm, const Tuple& tuple)
726
0
{
727
0
   ostrm << "[ " ;
728
   
729
0
#ifdef USE_IPV6
730
0
   if (tuple.mSockaddr.sa_family == AF_INET6)
731
0
   {
732
0
      ostrm << "V6 " << DnsUtil::inet_ntop(tuple.m_anonv6.sin6_addr) << " port=" << tuple.getPort();
733
0
   }
734
0
   else
735
0
#endif
736
0
   if (tuple.mSockaddr.sa_family == AF_INET)
737
0
   {
738
0
      ostrm << "V4 " << Tuple::inet_ntop(tuple) << ":" << tuple.getPort();
739
0
   }
740
0
   else
741
0
   {
742
0
      resip_assert(0);
743
0
   }
744
745
0
   ostrm << " " << Tuple::toData(tuple.mTransportType);
746
747
0
   if (!tuple.mTargetDomain.empty())
748
0
   {
749
0
       ostrm << " targetDomain=" << tuple.mTargetDomain;
750
0
   }
751
   
752
0
   if(tuple.mFlowKey != 0)
753
0
   {
754
0
      ostrm << " flowKey=" << tuple.mFlowKey;
755
0
   }
756
757
0
   if(tuple.mTransportKey != 0)
758
0
   {
759
0
      ostrm << " transportKey=" << tuple.mTransportKey;
760
0
   }
761
762
#ifdef USE_NETNS
763
      ostrm << " mNetNs=" << tuple.mNetNs;
764
#endif
765
766
0
   ostrm << " ]";
767
   
768
0
   return ostrm;
769
0
}
770
771
size_t 
772
Tuple::hash() const
773
0
{
774
   // !dlb! do not include the connection
775
0
#ifdef USE_IPV6
776
0
   if (mSockaddr.sa_family == AF_INET6)
777
0
   {
778
0
      const sockaddr_in6& in6 =
779
0
         reinterpret_cast<const sockaddr_in6&>(mSockaddr);
780
781
0
      return size_t(Data(Data::Share, (const char *)&in6.sin6_addr.s6_addr, sizeof(in6.sin6_addr.s6_addr)).hash() +
782
#ifdef USE_NETNS
783
                    mNetNs.hash() +
784
#endif
785
0
                    5*in6.sin6_port +
786
0
                    25*mTransportType);
787
0
   }
788
0
   else
789
0
#endif
790
0
   {
791
0
      const sockaddr_in& in4 =
792
0
         reinterpret_cast<const sockaddr_in&>(mSockaddr);
793
         
794
0
      return size_t(in4.sin_addr.s_addr +
795
#ifdef USE_NETNS
796
                    mNetNs.hash() +
797
#endif
798
0
                    5*in4.sin_port +
799
0
                    25*mTransportType);
800
0
   }    
801
0
}
802
803
HashValueImp(resip::Tuple, data.hash());
804
805
TransportType
806
Tuple::toTransport(const Data& transportName)
807
0
{
808
0
   return resip::toTransportType(transportName); // TransportTypes.hxx
809
0
};
810
811
const Data&
812
Tuple::toData(TransportType type)
813
0
{
814
0
   return resip::toData(type);  // TransportTypes.hxx
815
0
}
816
817
const Data&
818
Tuple::toDataLower(TransportType type)
819
0
{
820
0
   return resip::toDataLower(type);  // TransportTypes.hxx
821
0
}
822
823
Data
824
Tuple::inet_ntop(const Tuple& tuple)
825
0
{
826
0
#ifdef USE_IPV6
827
0
   if (!tuple.isV4())
828
0
   {
829
0
      const sockaddr_in6& addr = reinterpret_cast<const sockaddr_in6&>(tuple.getSockaddr());
830
0
      return DnsUtil::inet_ntop(addr.sin6_addr);
831
0
   }
832
0
   else
833
0
#endif
834
0
   {
835
0
      const sockaddr_in& addr = reinterpret_cast<const sockaddr_in&>(tuple.getSockaddr());
836
0
      return DnsUtil::inet_ntop(addr.sin_addr);
837
0
   }
838
0
}
839
840
841
bool
842
Tuple::isEqualWithMask(const Tuple& compare, short mask, bool ignorePort, bool ignoreTransport) const
843
0
{
844
0
   if(ignoreTransport || getType() == compare.getType())  // check if transport type matches
845
0
   {
846
0
      if (mSockaddr.sa_family == compare.getSockaddr().sa_family && mSockaddr.sa_family == AF_INET) // v4
847
0
      {
848
0
         sockaddr_in* addr1 = (sockaddr_in*)&mSockaddr;
849
0
         sockaddr_in* addr2 = (sockaddr_in*)&compare.getSockaddr();
850
851
0
         return ((ignorePort || addr1->sin_port == addr2->sin_port)  &&
852
0
                 (addr1->sin_addr.s_addr & htonl((0xFFFFFFFF << (32 - mask)))) == 
853
0
                  (addr2->sin_addr.s_addr & htonl((0xFFFFFFFF << (32 - mask)))));
854
0
      }
855
0
#ifdef USE_IPV6
856
0
      else if (mSockaddr.sa_family == compare.getSockaddr().sa_family && mSockaddr.sa_family == AF_INET6) // v6
857
0
      {
858
0
         sockaddr_in6* addr1 = (sockaddr_in6*)&mSockaddr;
859
0
         sockaddr_in6* addr2 = (sockaddr_in6*)&compare.getSockaddr();
860
861
0
         if(ignorePort || addr1->sin6_port == addr2->sin6_port)
862
0
         {
863
0
            uint32_t mask6part;
864
0
            uint32_t temp;
865
0
            bool match=true;
866
0
            for(int i = 3; i >= 0; i--)
867
0
            {
868
0
               if(mask <= 32*i)
869
0
               {
870
0
                  mask6part = 0;
871
0
               }
872
0
               else
873
0
               {
874
0
                  temp = mask - 32*i;
875
0
                  if(temp >= 32)
876
0
                  {
877
0
                     mask6part = 0xffffffff;
878
0
                  }
879
0
                  else
880
0
                  {
881
0
                     mask6part = 0xffffffff << (32 - temp);
882
0
                  }
883
0
               }
884
#ifdef WIN32
885
               if((*((unsigned long*)&addr1->sin6_addr.u.Word[i*2]) & htonl(mask6part)) != 
886
                  (*((unsigned long*)&addr2->sin6_addr.u.Word[i*2]) & htonl(mask6part)))
887
#elif defined(sun)
888
               // sun has no s6_addr16
889
               if((*((unsigned long*)&addr1->sin6_addr._S6_un._S6_u32[i]) & htonl(mask6part)) !=
890
                  (*((unsigned long*)&addr2->sin6_addr._S6_un._S6_u32[i]) & htonl(mask6part)))
891
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
892
               // bsd has no s6_addr16
893
               if((*((unsigned long*)&addr1->sin6_addr.__u6_addr.__u6_addr32[i]) & htonl(mask6part)) != 
894
                  (*((unsigned long*)&addr2->sin6_addr.__u6_addr.__u6_addr32[i]) & htonl(mask6part)))         
895
#else
896
0
               if((*((uint32_t*)&addr1->sin6_addr.s6_addr16[i*2]) & htonl(mask6part)) != 
897
0
                  (*((uint32_t*)&addr2->sin6_addr.s6_addr16[i*2]) & htonl(mask6part)))
898
0
#endif
899
0
               {
900
0
                  match=false;
901
0
                  break;
902
0
               }
903
0
            }
904
0
            if(match)
905
0
            {
906
0
               return true;
907
0
            }
908
0
         }
909
0
      }
910
0
#endif
911
0
   }
912
0
   return false;
913
0
}
914
915
916
// special comparitors
917
bool
918
Tuple::AnyInterfaceCompare::operator()(const Tuple& lhs,
919
                                       const Tuple& rhs) const
920
0
{
921
0
   if (lhs.mTransportType < rhs.mTransportType)
922
0
   {
923
0
      return true;
924
0
   }
925
0
   else if (lhs.mTransportType > rhs.mTransportType)
926
0
   {
927
0
      return false;
928
0
   }
929
0
   else if (lhs.mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
930
0
   {
931
0
      if (lhs.m_anonv4.sin_port < rhs.m_anonv4.sin_port)
932
0
      {
933
0
         return true;
934
0
      }
935
0
      else
936
0
      {
937
0
         return false;
938
0
      }
939
0
   }
940
0
#ifdef USE_IPV6
941
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
942
0
            rhs.mSockaddr.sa_family == AF_INET6)
943
0
   {
944
0
      if (lhs.m_anonv6.sin6_port < rhs.m_anonv6.sin6_port)
945
0
      {
946
0
         return true;
947
0
      }
948
0
      else
949
0
      {
950
0
         return false;
951
0
      }
952
0
   }
953
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
954
0
            rhs.mSockaddr.sa_family == AF_INET)
955
0
   {
956
0
      return true;
957
0
   }
958
0
   else if (lhs.mSockaddr.sa_family == AF_INET &&
959
0
            rhs.mSockaddr.sa_family == AF_INET6)
960
0
   {
961
0
      return false;
962
0
   }
963
0
#endif
964
0
   else
965
0
   {
966
0
      return false;
967
0
   }
968
0
};
969
970
bool
971
Tuple::AnyPortCompare::operator()(const Tuple& lhs,
972
                                  const Tuple& rhs) const
973
0
{
974
0
   if (lhs.mTransportType < rhs.mTransportType)
975
0
   {
976
0
      return true;
977
0
   }
978
0
   else if (lhs.mTransportType > rhs.mTransportType)
979
0
   {
980
0
      return false;
981
0
   }
982
983
   // transport types equal, so compare addresses
984
0
   if (lhs.mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
985
0
   {
986
0
      int c = memcmp(&lhs.m_anonv4.sin_addr,
987
0
                     &rhs.m_anonv4.sin_addr,
988
0
                     sizeof(in_addr));
989
990
0
      if (c < 0)
991
0
      {
992
0
         return true;
993
0
      }
994
0
      else if (c > 0)
995
0
      {
996
0
         return false;
997
0
      }
998
0
   }
999
0
#ifdef USE_IPV6
1000
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
1001
0
            rhs.mSockaddr.sa_family == AF_INET6)
1002
0
   {
1003
0
      int c = memcmp(&lhs.m_anonv6.sin6_addr,
1004
0
                     &rhs.m_anonv6.sin6_addr,
1005
0
                     sizeof(in6_addr));
1006
0
      if (c < 0)
1007
0
      {
1008
0
         return true;
1009
0
      }
1010
0
      else if (c > 0)
1011
0
      {
1012
0
         return false;
1013
0
      }
1014
0
   }
1015
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
1016
0
            rhs.mSockaddr.sa_family == AF_INET)
1017
0
   {
1018
0
      return true;
1019
0
   }
1020
0
   else if (lhs.mSockaddr.sa_family == AF_INET &&
1021
0
            rhs.mSockaddr.sa_family == AF_INET6)
1022
0
   {
1023
0
      return false;
1024
0
   }
1025
0
#endif
1026
#ifdef USE_NETNS
1027
   // transport type and addresses are equal, so compare netns
1028
   if(lhs.mNetNs < rhs.mNetNs)
1029
   {
1030
       //DebugLog(<< "AnyPortCompare netns less than (l=" << lhs.mNetNs << ", r=" << rhs.mNetNs);
1031
       return(true);
1032
   }
1033
   else if(rhs.mNetNs < lhs.mNetNs)
1034
   {
1035
       //DebugLog(<< "AnyPortCompare netns greater than (l=" << lhs.mNetNs << ", r=" << rhs.mNetNs);
1036
       return(false);
1037
   }
1038
   //DebugLog(<< "AnyPortCompare netns equal to (l=\"" << lhs.mNetNs << "\", r=\"" << rhs.mNetNs << "\"");
1039
#endif
1040
1041
0
   return false;
1042
0
}
1043
1044
bool
1045
Tuple::FlowKeyCompare::operator()(const Tuple& lhs,
1046
                                  const Tuple& rhs) const
1047
0
{
1048
0
   if (lhs == rhs)
1049
0
   {
1050
0
      return lhs.mFlowKey < rhs.mFlowKey;
1051
0
   }
1052
0
   return lhs < rhs;
1053
0
};
1054
1055
GenericIPAddress 
1056
Tuple::toGenericIPAddress() const
1057
0
{
1058
0
   if (isV4())
1059
0
   {
1060
0
      return GenericIPAddress(m_anonv4);
1061
0
   }
1062
0
   else
1063
0
#ifdef USE_IPV6
1064
0
  {
1065
0
      return GenericIPAddress(m_anonv6);
1066
0
  }
1067
#else
1068
  {
1069
     resip_assert(0);
1070
     return m_anonv4; //bogus
1071
  }
1072
#endif
1073
0
}
1074
1075
bool
1076
Tuple::AnyPortAnyInterfaceCompare::operator()(const Tuple& lhs,
1077
                                              const Tuple& rhs) const
1078
0
{
1079
0
   if (lhs.mTransportType < rhs.mTransportType)
1080
0
   {
1081
0
      return true;
1082
0
   }
1083
0
   else if (lhs.mTransportType > rhs.mTransportType)
1084
0
   {
1085
0
      return false;
1086
0
   }
1087
0
#ifdef USE_IPV6
1088
0
   else if (lhs.mSockaddr.sa_family == AF_INET6 &&
1089
0
            rhs.mSockaddr.sa_family == AF_INET)
1090
0
   {
1091
0
      return true;
1092
0
   }
1093
0
   else if (lhs.mSockaddr.sa_family == AF_INET &&
1094
0
            rhs.mSockaddr.sa_family == AF_INET6)
1095
0
   {
1096
0
      return false;
1097
0
   }
1098
0
#endif
1099
0
   else
1100
0
   {
1101
0
      return false;
1102
0
   }
1103
0
};
1104
1105
/* ====================================================================
1106
 * The Vovida Software License, Version 1.0 
1107
 * 
1108
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
1109
 * 
1110
 * Redistribution and use in source and binary forms, with or without
1111
 * modification, are permitted provided that the following conditions
1112
 * are met:
1113
 * 
1114
 * 1. Redistributions of source code must retain the above copyright
1115
 *    notice, this list of conditions and the following disclaimer.
1116
 * 
1117
 * 2. Redistributions in binary form must reproduce the above copyright
1118
 *    notice, this list of conditions and the following disclaimer in
1119
 *    the documentation and/or other materials provided with the
1120
 *    distribution.
1121
 * 
1122
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1123
 *    and "Vovida Open Communication Application Library (VOCAL)" must
1124
 *    not be used to endorse or promote products derived from this
1125
 *    software without prior written permission. For written
1126
 *    permission, please contact vocal@vovida.org.
1127
 *
1128
 * 4. Products derived from this software may not be called "VOCAL", nor
1129
 *    may "VOCAL" appear in their name, without prior written
1130
 *    permission of Vovida Networks, Inc.
1131
 * 
1132
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1133
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1134
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1135
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
1136
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1137
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1138
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1139
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1140
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1141
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1142
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1143
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1144
 * DAMAGE.
1145
 * 
1146
 * ====================================================================
1147
 * 
1148
 * This software consists of voluntary contributions made by Vovida
1149
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1150
 * Inc.  For more information on Vovida Networks, Inc., please see
1151
 * <http://www.vovida.org/>.
1152
 *
1153
 */