Browse code

fixed IPv6 support

limitations: IPv6 DNS lookups are not supported yet.

Raphael Coeffic authored on 19/11/2012 16:23:06
Showing 20 changed files
... ...
@@ -67,7 +67,7 @@ int RtmpFactory::onLoad()
67 67
   else {
68 68
 
69 69
     if(cfg_file.hasParameter("listen_address")){
70
-      cfg.ListenAddress = fixIface2IP(cfg_file.getParameter("listen_address"));
70
+      cfg.ListenAddress = fixIface2IP(cfg_file.getParameter("listen_address"),false);
71 71
     }
72 72
 
73 73
     if(cfg_file.hasParameter("listen_port")){
... ...
@@ -538,8 +538,14 @@ void AmB2BMedia::replaceConnectionAddress(AmSdp &parser_sdp, bool a_leg, const s
538 538
         DBG("new stream connection address: %s",it->conn.address.c_str());
539 539
       }
540 540
       try {
541
-        if (a_leg) it->port = streams->a.getLocalPort();
542
-        else it->port = streams->b.getLocalPort();
541
+        if (a_leg) {
542
+	  streams->a.setLocalIP(relay_address);
543
+	  it->port = streams->a.getLocalPort();
544
+	}
545
+        else {
546
+	  streams->b.setLocalIP(relay_address);
547
+	  it->port = streams->b.getLocalPort();
548
+	}
543 549
         replaced_ports += (streams != audio.begin()) ? int2str(it->port) : "/"+int2str(it->port);
544 550
       } catch (const string& s) {
545 551
         mutex.unlock();
... ...
@@ -146,9 +146,23 @@ class AudioStreamData {
146 146
 
147 147
     // --- helper methods propagating our private member to outside world ---
148 148
 
149
-    void clearRTPTimeout() { if (stream) stream->clearRTPTimeout(); }
150
-    int getLocalPort() { if (stream) return stream->getLocalPort(); else return 0; }
151
-    AmRtpAudio *getStream() { return stream; }
149
+    void clearRTPTimeout() { 
150
+      if (stream) stream->clearRTPTimeout(); 
151
+    }
152
+
153
+    int getLocalPort() { 
154
+      if (stream) return stream->getLocalPort(); 
155
+      else return 0; 
156
+    }
157
+
158
+    void setLocalIP(const string& ip) { 
159
+      if (stream) stream->setLocalIP(ip);
160
+    }
161
+
162
+    AmRtpAudio *getStream() { 
163
+      return stream; 
164
+    }
165
+
152 166
     bool isInitialized() { return initialized; }
153 167
 };
154 168
 
... ...
@@ -43,6 +43,7 @@
43 43
 #include "AmSession.h"
44 44
 #include "Am100rel.h"
45 45
 #include "sip/transport.h"
46
+#include "sip/ip_util.h"
46 47
 #include "sip/sip_timers.h"
47 48
 
48 49
 #include <cctype>
... ...
@@ -759,20 +760,16 @@ static bool fillSysIntfList()
759 760
     if(p_if->ifa_addr == NULL)
760 761
       continue;
761 762
     
762
-    if( (p_if->ifa_addr->sa_family != AF_INET) //&&
763
-        //(p_if->ifa_addr->sa_family != AF_INET6) 
764
-	)
763
+    if( (p_if->ifa_addr->sa_family != AF_INET) &&
764
+        (p_if->ifa_addr->sa_family != AF_INET6) )
765 765
       continue;
766 766
 
767 767
     if( !(p_if->ifa_flags & IFF_UP) || !(p_if->ifa_flags & IFF_RUNNING) )
768 768
       continue;
769 769
 
770
-    int s = getnameinfo(p_if->ifa_addr,
771
-			(p_if->ifa_addr->sa_family == AF_INET) ? 
772
-			sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
773
-			host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
774
-    if (s != 0) {
775
-      ERROR("getnameinfo() failed: %s\n", gai_strerror(s));
770
+    if (am_inet_ntop((const sockaddr_storage*)p_if->ifa_addr,
771
+		     host, NI_MAXHOST) == NULL) {
772
+      ERROR("am_inet_ntop() failed\n");
776 773
       freeifaddrs(ifap);
777 774
       return false;
778 775
     }
... ...
@@ -794,7 +791,7 @@ static bool fillSysIntfList()
794 791
     }
795 792
 
796 793
     DBG("iface='%s';ip='%s';flags=0x%x\n",p_if->ifa_name,host,p_if->ifa_flags);
797
-    intf_it->addrs.push_back(host);
794
+    intf_it->addrs.push_back(AmConfig::IPAddr(host,p_if->ifa_addr->sa_family));
798 795
   }
799 796
 
800 797
   freeifaddrs(ifap);
... ...
@@ -802,21 +799,18 @@ static bool fillSysIntfList()
802 799
   return true;
803 800
 }
804 801
 
805
-/** Get the PF_INET address associated with the network interface */
806
-string fixIface2IP(const string& dev_name)
802
+/** Get the AF_INET[6] address associated with the network interface */
803
+string fixIface2IP(const string& dev_name, bool v6_for_sip)
807 804
 {
808 805
   string local_ip;
809 806
 
810
-#ifdef SUPPORT_IPV6
811 807
   struct sockaddr_storage ss;
812
-  if(inet_aton_v6(dev_name.c_str(), &ss))
813
-#else
814
-    struct in_addr inp;
815
-  if(inet_aton(dev_name.c_str(), &inp))
816
-#endif
817
-    {
808
+  if(am_inet_pton(dev_name.c_str(), &ss)) {
809
+    if(v6_for_sip && (ss.ss_family == AF_INET6) && (dev_name[0] != '['))
810
+      return "[" + dev_name + "]";
811
+    else
818 812
       return dev_name;
819
-    }
813
+  }
820 814
 
821 815
   for(list<AmConfig::SysIntf>::iterator intf_it = AmConfig::SysIfs.begin();
822 816
       intf_it != AmConfig::SysIfs.end(); ++intf_it) {
... ...
@@ -829,8 +823,12 @@ string fixIface2IP(const string& dev_name)
829 823
 	return "";
830 824
       }
831 825
       
832
-      DBG("dev_name = '%s'\n",dev_name.c_str());
833
-      local_ip = intf_it->addrs.front();
826
+      DBG("dev_name = '%s'\n", dev_name.c_str());
827
+      const AmConfig::IPAddr& ip = intf_it->addrs.front();
828
+      if(v6_for_sip && (ip.family == AF_INET6))
829
+	local_ip = "[" + ip.addr + "]";
830
+      else
831
+	local_ip = ip.addr;
834 832
       break;
835 833
     }
836 834
   }    
... ...
@@ -844,7 +842,7 @@ int AmConfig::finalizeIPConfig()
844 842
 
845 843
   for(int i=0; i < (int)AmConfig::Ifs.size(); i++) {
846 844
 
847
-    AmConfig::Ifs[i].LocalIP = fixIface2IP(AmConfig::Ifs[i].LocalIP);
845
+    AmConfig::Ifs[i].LocalIP = fixIface2IP(AmConfig::Ifs[i].LocalIP,false);
848 846
     if (AmConfig::Ifs[i].LocalIP.empty()) {
849 847
       ERROR("Cannot determine proper local address for media advertising!\n"
850 848
 	    "Try using 'ifconfig -a' to find a proper interface and configure SEMS to use it.\n");
... ...
@@ -852,18 +850,22 @@ int AmConfig::finalizeIPConfig()
852 850
     }
853 851
     
854 852
     if (AmConfig::Ifs[i].LocalSIPIP.empty()) {
855
-      AmConfig::Ifs[i].LocalSIPIP = AmConfig::Ifs[i].LocalIP;
853
+      AmConfig::Ifs[i].LocalSIPIP = fixIface2IP(AmConfig::Ifs[i].LocalIP,true);
856 854
     }
857 855
     else {
858
-      AmConfig::Ifs[i].LocalSIPIP = fixIface2IP(AmConfig::Ifs[i].LocalSIPIP);
856
+      AmConfig::Ifs[i].LocalSIPIP = fixIface2IP(AmConfig::Ifs[i].LocalSIPIP,true);
859 857
     }
860 858
 
861 859
     list<AmConfig::SysIntf>::iterator intf_it = AmConfig::SysIfs.begin();
862 860
     for(;intf_it != AmConfig::SysIfs.end(); ++intf_it) {
863 861
 
864
-      list<string>::iterator addr_it = std::find(intf_it->addrs.begin(),
865
-						 intf_it->addrs.end(),
866
-						 AmConfig::Ifs[i].LocalSIPIP);
862
+      list<AmConfig::IPAddr>::iterator addr_it = intf_it->addrs.begin();
863
+      for(;addr_it != intf_it->addrs.end(); addr_it++) {
864
+
865
+	if(AmConfig::Ifs[i].LocalSIPIP == addr_it->addr)
866
+	  break;
867
+      }
868
+
867 869
       // address not in this interface
868 870
       if(addr_it == intf_it->addrs.end())
869 871
 	continue;
... ...
@@ -871,10 +873,10 @@ int AmConfig::finalizeIPConfig()
871 873
       for(addr_it = intf_it->addrs.begin(); 
872 874
 	  addr_it != intf_it->addrs.end(); ++addr_it) {
873 875
 
874
-	if(AmConfig::LocalSIPIP2If.find(*addr_it)
876
+	if(AmConfig::LocalSIPIP2If.find(addr_it->addr)
875 877
 	   == AmConfig::LocalSIPIP2If.end()) {
876 878
 	
877
-	  AmConfig::LocalSIPIP2If.insert(make_pair(*addr_it,i));
879
+	  AmConfig::LocalSIPIP2If.insert(make_pair(addr_it->addr,i));
878 880
 	}
879 881
       }
880 882
     }
... ...
@@ -115,9 +115,20 @@ struct AmConfig
115 115
   static vector<IP_interface>       Ifs;
116 116
   static map<string,unsigned short> If_names;
117 117
 
118
+  struct IPAddr {
119
+    string addr;
120
+    short  family;
121
+    
122
+    IPAddr(const string& addr, const short family)
123
+      : addr(addr), family(family) {}
124
+
125
+    IPAddr(const IPAddr& ip)
126
+      : addr(ip.addr), family(ip.family) {}
127
+  };
128
+
118 129
   struct SysIntf {
119 130
     string       name;
120
-    list<string> addrs;
131
+    list<IPAddr> addrs;
121 132
     // identical to those returned by SIOCGIFFLAGS
122 133
     unsigned int flags;
123 134
   };
... ...
@@ -262,7 +273,7 @@ struct AmConfig
262 273
 };
263 274
 
264 275
 /** Get the PF_INET address associated with the network interface */
265
-string fixIface2IP(const string& dev_name);
276
+string fixIface2IP(const string& dev_name, bool v6_for_sip);
266 277
 
267 278
 #endif
268 279
 
... ...
@@ -30,6 +30,8 @@
30 30
 #include "log.h"
31 31
 #include "AmConfig.h"
32 32
 
33
+#include "sip/ip_util.h"
34
+
33 35
 #include <assert.h>
34 36
 #include <string.h>
35 37
 #include <errno.h>
... ...
@@ -50,8 +52,6 @@ AmRtpPacket::~AmRtpPacket()
50 52
 {
51 53
 }
52 54
 
53
-#ifdef SUPPORT_IPV6
54
-
55 55
 void AmRtpPacket::setAddr(struct sockaddr_storage* a)
56 56
 {
57 57
   memcpy(&addr,a,sizeof(sockaddr_storage));
... ...
@@ -62,20 +62,6 @@ void AmRtpPacket::getAddr(struct sockaddr_storage* a)
62 62
   memcpy(a,&addr,sizeof(sockaddr_storage));
63 63
 }
64 64
 
65
-#else
66
-
67
-void AmRtpPacket::setAddr(struct sockaddr_in* a)
68
-{
69
-  memcpy(&addr,a,sizeof(sockaddr_in));
70
-}
71
-
72
-void AmRtpPacket::getAddr(struct sockaddr_in* a)
73
-{
74
-  memcpy(a,&addr,sizeof(sockaddr_in));
75
-}
76
-
77
-#endif
78
-
79 65
 int AmRtpPacket::parse()
80 66
 {
81 67
   assert(buffer);
... ...
@@ -196,17 +182,9 @@ int AmRtpPacket::compile_raw(unsigned char* data_buf, unsigned int size)
196 182
 
197 183
 int AmRtpPacket::send(int sd)
198 184
 {
199
-  int err;
200
-#ifdef SUPPORT_IPV6
201
-  if(addr.ss_family != PF_INET)
202
-    err = sendto(sd,buffer,b_size,0,
203
-		 (const struct sockaddr *)&addr,
204
-		 sizeof(struct sockaddr_in6));
205
-  else 
206
-#endif
207
-    err = sendto(sd,buffer,b_size,0,
208
-		 (const struct sockaddr *)&addr,
209
-		 sizeof(struct sockaddr_in));
185
+  int err = sendto(sd,buffer,b_size,0,
186
+		   (const struct sockaddr *)&addr,
187
+		   SA_len(&addr));
210 188
 
211 189
   if(err == -1){
212 190
     ERROR("while sending RTP packet: %s\n",strerror(errno));
... ...
@@ -218,12 +196,7 @@ int AmRtpPacket::send(int sd)
218 196
 
219 197
 int AmRtpPacket::recv(int sd)
220 198
 {
221
-#ifdef SUPPORT_IPV6
222 199
   socklen_t recv_addr_len = sizeof(struct sockaddr_storage);
223
-#else
224
-  socklen_t recv_addr_len = sizeof(struct sockaddr_in);
225
-#endif
226
-
227 200
   int ret = recvfrom(sd,buffer,sizeof(buffer),0,
228 201
 		     (struct sockaddr*)&addr,
229 202
 		     &recv_addr_len);
... ...
@@ -51,24 +51,13 @@ public:
51 51
   unsigned int   ssrc;
52 52
 
53 53
   struct timeval recv_time;
54
-
55
-#ifdef SUPPORT_IPV6
56 54
   struct sockaddr_storage addr;
57
-#else
58
-  struct sockaddr_in addr;
59
-#endif
60
-    
61 55
 
62 56
   AmRtpPacket();
63 57
   ~AmRtpPacket();
64 58
 
65
-#ifdef SUPPORT_IPV6
66 59
   void setAddr(struct sockaddr_storage* a);
67 60
   void getAddr(struct sockaddr_storage* a);
68
-#else
69
-  void setAddr(struct sockaddr_in* a);
70
-  void getAddr(struct sockaddr_in* a);
71
-#endif
72 61
 
73 62
   // returns -1 if error, else 0
74 63
   int compile(unsigned char* data_buf, unsigned int size);
... ...
@@ -40,6 +40,7 @@
40 40
 #include "AmJitterBuffer.h"
41 41
 
42 42
 #include "sip/resolver.h"
43
+#include "sip/ip_util.h"
43 44
 
44 45
 #include "log.h"
45 46
 
... ...
@@ -81,15 +82,10 @@ PayloadMask::PayloadMask(const PayloadMask &src)
81 82
  */
82 83
 void AmRtpStream::setLocalIP(const string& ip)
83 84
 {
84
-#ifdef SUPPORT_IPV6
85
-  if (!inet_aton_v6(ip.c_str(), &l_saddr)) {
86
-    throw string ("Invalid IPv6 address: ") + ip;
85
+  if (!am_inet_pton(ip.c_str(), &l_saddr)) {
86
+    throw string ("AmRtpStream::setLocalIP: Invalid IP address: ") + ip;
87 87
   }
88
-#else
89
-  if (!inet_aton(ip.c_str(), (in_addr*)&l_saddr.sin_addr.s_addr)) {
90
-    throw string ("Invalid IPv4 address: ") + ip;
91
-  }
92
-#endif
88
+  DBG("ip = %s\n",ip.c_str());
93 89
 }
94 90
 
95 91
 int AmRtpStream::hasLocalSocket() {
... ...
@@ -102,25 +98,15 @@ int AmRtpStream::getLocalSocket()
102 98
     return l_sd;
103 99
 
104 100
   int sd=0, rtcp_sd=0;
105
-#ifdef SUPPORT_IPV6
106
-  if((sd = socket(l_saddr.ss_family,SOCK_DGRAM,0)) == -1)
107
-#else
108
-    if((sd = socket(PF_INET,SOCK_DGRAM,0)) == -1)
109
-#endif
110
-      {
111
-	ERROR("%s\n",strerror(errno));
112
-	throw string ("while creating new socket.");
113
-      } 
114
-
115
-#ifdef SUPPORT_IPV6
116
-  if((rtcp_sd = socket(l_saddr.ss_family,SOCK_DGRAM,0)) == -1)
117
-#else
118
-    if((rtcp_sd = socket(PF_INET,SOCK_DGRAM,0)) == -1)
119
-#endif
120
-      {
121
-	ERROR("%s\n",strerror(errno));
122
-	throw string ("while creating new RTCP socket.");
123
-      } 
101
+  if((sd = socket(l_saddr.ss_family,SOCK_DGRAM,0)) == -1) {
102
+    ERROR("%s\n",strerror(errno));
103
+    throw string ("while creating new socket.");
104
+  } 
105
+
106
+  if((rtcp_sd = socket(l_saddr.ss_family,SOCK_DGRAM,0)) == -1) {
107
+    ERROR("%s\n",strerror(errno));
108
+    throw string ("while creating new socket.");
109
+  } 
124 110
 
125 111
   int true_opt = 1;
126 112
   if(ioctl(sd, FIONBIO , &true_opt) == -1){
... ...
@@ -158,30 +144,15 @@ void AmRtpStream::setLocalPort()
158 144
       return;
159 145
 
160 146
     port = AmConfig::Ifs[l_if].getNextRtpPort();
161
-#ifdef SUPPORT_IPV6
162
-    set_port_v6(&l_saddr,port+1);
163
-    if(bind(l_rtcp_sd,(const struct sockaddr*)&l_saddr,
164
-	     sizeof(struct sockaddr_storage)))
165
-#else	
166
-    l_saddr.sin_port = htons(port+1);
167
-    if(bind(l_rtcp_sd,(const struct sockaddr*)&l_saddr,
168
-	     sizeof(struct sockaddr_in)))
169
-#endif
170
-    {
171
-      DBG("RTCP bind: %s\n",strerror(errno));
147
+
148
+    am_set_port(&l_saddr,port+1);
149
+    if(bind(l_rtcp_sd,(const struct sockaddr*)&l_saddr,SA_len(&l_saddr))) {
150
+      DBG("bind: %s\n",strerror(errno));		
172 151
       goto try_another_port;
173 152
     }
174 153
 
175
-#ifdef SUPPORT_IPV6
176
-    set_port_v6(&l_saddr,port);
177
-    if(bind(l_sd,(const struct sockaddr*)&l_saddr,
178
-	     sizeof(struct sockaddr_storage)))
179
-#else	
180
-    l_saddr.sin_port = htons(port);
181
-    if(bind(l_sd,(const struct sockaddr*)&l_saddr,
182
-	     sizeof(struct sockaddr_in)))
183
-#endif
184
-    {
154
+    am_set_port(&l_saddr,port);
155
+    if(bind(l_sd,(const struct sockaddr*)&l_saddr,SA_len(&l_saddr))) {
185 156
       DBG("bind: %s\n",strerror(errno));		
186 157
       goto try_another_port;
187 158
     }
... ...
@@ -410,19 +381,8 @@ AmRtpStream::AmRtpStream(AmSession* _s, int _if)
410 381
     relay_transparent_seqno(true)
411 382
 {
412 383
 
413
-#ifdef SUPPORT_IPV6
414 384
   memset(&r_saddr,0,sizeof(struct sockaddr_storage));
415 385
   memset(&l_saddr,0,sizeof(struct sockaddr_storage));
416
-#else
417
-  memset(&r_saddr,0,sizeof(struct sockaddr_in));
418
-  memset(&l_saddr,0,sizeof(struct sockaddr_in));
419
-#endif
420
-
421
-#ifndef SUPPORT_IPV6
422
-  /* By default we listen on all interfaces */
423
-  l_saddr.sin_family = AF_INET;
424
-  l_saddr.sin_addr.s_addr = INADDR_ANY;
425
-#endif
426 386
 
427 387
   l_ssrc = get_random();
428 388
   sequence = get_random();
... ...
@@ -481,48 +441,43 @@ void AmRtpStream::setRAddr(const string& addr, unsigned short port)
481 441
     throw string("invalid address") + addr;
482 442
   }
483 443
 
484
-#ifdef SUPPORT_IPV6
485
-
486 444
   memcpy(&r_saddr,&ss,sizeof(struct sockaddr_storage));
487
-  set_port_v6(&r_saddr,port);
488
-
489
-#else
490
-
491
-  struct sockaddr_in sa;
492
-  memset (&sa, 0, sizeof(sa));
493
-
494
-#ifdef BSD44SOCKETS
495
-  sa.sin_len = sizeof(sockaddr_in);
496
-#endif
497
-  sa.sin_family = AF_INET;
498
-  sa.sin_port = htons(port);
499
-
500
-  memcpy(&r_saddr,&sa,sizeof(struct sockaddr_in));
501
-  memcpy(&r_saddr.sin_addr,&((sockaddr_in*)&ss)->sin_addr,sizeof(in_addr));
502
-#endif
445
+  am_set_port(&r_saddr,port);
503 446
 
504 447
   r_host = addr;
505 448
   r_port = port;
506 449
 
507
-#ifndef SUPPORT_IPV6
508
-  mute = (r_saddr.sin_addr.s_addr == 0);
509
-#endif
450
+  mute = ((r_saddr.ss_family == AF_INET) && 
451
+	  (SAv4(&r_saddr)->sin_addr.s_addr == INADDR_ANY)) ||
452
+    ((r_saddr.ss_family == AF_INET6) && 
453
+     IN6_IS_ADDR_UNSPECIFIED(&SAv6(&r_saddr)->sin6_addr));
510 454
 }
511 455
 
512 456
 void AmRtpStream::handleSymmetricRtp(AmRtpPacket* rp) {
513
-#ifndef SUPPORT_IPV6
457
+
514 458
   if(passive) {
515
-    // #ifdef SUPPORT_IPV6
516
-    //     struct sockaddr_storage recv_addr;
517
-    // #else
518
-    struct sockaddr_in recv_addr;
459
+    struct sockaddr_storage recv_addr;
519 460
     rp->getAddr(&recv_addr);
520 461
 
462
+    struct sockaddr_in* in_recv = (struct sockaddr_in*)&recv_addr;
463
+    struct sockaddr_in6* in6_recv = (struct sockaddr_in6*)&recv_addr;
464
+
465
+    struct sockaddr_in* in_addr = (struct sockaddr_in*)&r_saddr;
466
+    struct sockaddr_in6* in6_addr = (struct sockaddr_in6*)&r_saddr;
467
+
521 468
     // symmetric RTP
522
-    if ((recv_addr.sin_port != r_saddr.sin_port)
523
-	|| (recv_addr.sin_addr.s_addr != r_saddr.sin_addr.s_addr)) {
524
-      string addr_str = get_addr_str((sockaddr_storage*)&recv_addr);
525
-      int port = ntohs(recv_addr.sin_port);
469
+    if ( ((recv_addr.ss_family == AF_INET) &&
470
+	  ((in_addr->sin_port != in_recv->sin_port)
471
+	   || (in_addr->sin_addr.s_addr != in_recv->sin_addr.s_addr))) ||
472
+	 ((recv_addr.ss_family == AF_INET6) &&
473
+	  ((in6_addr->sin6_port != in6_recv->sin6_port)
474
+	   || (memcmp(&in6_addr->sin6_addr,
475
+		      &in6_recv->sin6_addr,
476
+		      sizeof(struct in6_addr)))))
477
+	 ) {
478
+
479
+      string addr_str = get_addr_str(&recv_addr);
480
+      int port = am_get_port(&recv_addr);
526 481
       setRAddr(addr_str,port);
527 482
       DBG("Symmetric RTP: setting new remote address: %s:%i\n",
528 483
 	  addr_str.c_str(),port);
... ...
@@ -533,7 +488,6 @@ void AmRtpStream::handleSymmetricRtp(AmRtpPacket* rp) {
533 488
     // avoid comparing each time sender address
534 489
     passive = false;
535 490
   }
536
-#endif
537 491
 }
538 492
 
539 493
 void AmRtpStream::setPassiveMode(bool p)
... ...
@@ -720,9 +674,10 @@ int AmRtpStream::init(const AmSdp& local,
720 674
 
721 675
   if(local_media.send && !hold
722 676
      && (remote_media.port != 0)
723
-#ifndef SUPPORT_IPV6
724
-     && (r_saddr.sin_addr.s_addr != 0)
725
-#endif
677
+     && (((r_saddr.ss_family == AF_INET) 
678
+	  && (SAv4(&r_saddr)->sin_addr.s_addr != 0)) ||
679
+	 ((r_saddr.ss_family == AF_INET6) 
680
+	  && (!IN6_IS_ADDR_UNSPECIFIED(&SAv6(&r_saddr)->sin6_addr))))
726 681
      ) {
727 682
     mute = false;
728 683
   }
... ...
@@ -986,13 +941,13 @@ void AmRtpStream::recvRtcpPacket()
986 941
     return;
987 942
   }
988 943
 
989
-  struct sockaddr_in rtcp_raddr;
990
-  memcpy(&rtcp_raddr,&relay_stream->r_saddr,sizeof(struct sockaddr_in));
991
-  rtcp_raddr.sin_port = htons(relay_stream->l_rtcp_port);
944
+  struct sockaddr_storage rtcp_raddr;
945
+  memcpy(&rtcp_raddr,&relay_stream->r_saddr,sizeof(rtcp_raddr));
946
+  am_set_port(&rtcp_raddr, relay_stream->r_port+1);
992 947
 
993
-  int err = sendto(relay_stream->l_sd,buffer,recved_bytes,0,
994
-	       (const struct sockaddr *)&rtcp_raddr,
995
-	       sizeof(struct sockaddr_in));
948
+  int err = sendto(relay_stream->l_rtcp_sd,buffer,recved_bytes,0,
949
+		   (const struct sockaddr *)&rtcp_raddr,
950
+		   SA_len(&rtcp_raddr));
996 951
   
997 952
   if(err == -1){
998 953
     ERROR("could not relay RTCP packet: %s\n",strerror(errno));
... ...
@@ -191,13 +191,8 @@ protected:
191 191
   /**
192 192
    * Local and remote host addresses
193 193
    */
194
-#ifdef SUPPORT_IPV6
195 194
   struct sockaddr_storage r_saddr;
196 195
   struct sockaddr_storage l_saddr;
197
-#else
198
-  struct sockaddr_in r_saddr;
199
-  struct sockaddr_in l_saddr;
200
-#endif
201 196
 
202 197
   /** Local port */
203 198
   unsigned short     l_port;
... ...
@@ -987,7 +987,7 @@ bool AmSession::getSdpAnswer(const AmSdp& offer, AmSdp& answer)
987 987
         && audio_1st_stream 
988 988
         && (m_it->port != 0) ) {
989 989
 
990
-      RTPStream()->setLocalIP(advertisedIP());
990
+      RTPStream()->setLocalIP(answer.conn.address);
991 991
       RTPStream()->getSdpAnswer(media_index,*m_it,answer_media);
992 992
       if(answer_media.payloads.empty() ||
993 993
 	 ((answer_media.payloads.size() == 1) &&
... ...
@@ -31,9 +31,9 @@
31 31
 #include "AmThread.h"
32 32
 #include "AmConfig.h"
33 33
 #include "log.h"
34
-//#include "AmServer.h"
35 34
 #include "AmSipMsg.h"
36 35
 #include "sip/resolver.h"
36
+#include "sip/ip_util.h"
37 37
 
38 38
 #include <stdarg.h>
39 39
 #include <stdlib.h>
... ...
@@ -438,80 +438,16 @@ string filename_from_fullpath(const string& path)
438 438
 
439 439
 string get_addr_str(const sockaddr_storage* addr)
440 440
 {
441
-  char host[NI_MAXHOST];
442
-
443
-  int s = getnameinfo((sockaddr*)addr, (addr->ss_family == AF_INET) ? 
444
-		      sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
445
-		      host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
446
-  if (s != 0) {
447
-    ERROR("getnameinfo() failed: %s\n", gai_strerror(s));
448
-    return "";
449
-  }
450
-  
451
-  return host;
452
-}
453
-
454
-
455
-#ifdef SUPPORT_IPV6
456
-#include <netdb.h>
457
-
458
-int inet_aton_v6(const char* name, struct sockaddr_storage* ss)
459
-{
460
-  int error;
461
-  //struct sockaddr *sa;
462
-  struct addrinfo hints;
463
-  struct addrinfo *res;
464
-
465
-  memset(&hints, 0, sizeof(hints));
466
-  /* set-up hints structure */
467
-  hints.ai_family = PF_UNSPEC;
468
-  error = getaddrinfo(name, NULL, &hints, &res);
469
-  if (error)
470
-    ERROR("%s\n",gai_strerror(error));
471
-  else if (res) {
472
-    assert( (res->ai_family == PF_INET) || 
473
-	    (res->ai_family == PF_INET6) );
474
-    memset(ss,0,sizeof(struct sockaddr_storage));
475
-    memcpy(ss,res->ai_addr,res->ai_addrlen);
476
-    freeaddrinfo(res);
477
-    return 1;
478
-  }
479
-
480
-  return 0;
481
-}
482
-
483
-void set_port_v6(struct sockaddr_storage* ss, short port)
484
-{
485
-  switch(ss->ss_family){
486
-  case PF_INET:
487
-    ((struct sockaddr_in*)ss)->sin_port = htons(port);
488
-    break;
489
-  case PF_INET6:
490
-    ((struct sockaddr_in6*)ss)->sin6_port = htons(port);
491
-    break;
492
-  default:
493
-    ERROR("unknown address family\n");
494
-    assert(0);
495
-    break;
496
-  }
441
+  char host[NI_MAXHOST] = "";
442
+  return am_inet_ntop(addr,host,NI_MAXHOST);
497 443
 }
498 444
 
499
-short get_port_v6(struct sockaddr_storage* ss)
445
+string get_addr_str_sip(const sockaddr_storage* addr)
500 446
 {
501
-  switch(ss->ss_family){
502
-  case PF_INET:
503
-    return ntohs(((struct sockaddr_in*)ss)->sin_port);
504
-  case PF_INET6:
505
-    return ntohs(((struct sockaddr_in6*)ss)->sin6_port);
506
-  default:
507
-    ERROR("unknown address family\n");
508
-    assert(0);
509
-    break;
510
-  }
447
+  char host[NI_MAXHOST] = "";
448
+  return am_inet_ntop_sip(addr,host,NI_MAXHOST);
511 449
 }
512 450
 
513
-#endif
514
-
515 451
 string file_extension(const string& path)
516 452
 {
517 453
   string::size_type pos = path.rfind('.');
... ...
@@ -626,30 +562,13 @@ int get_local_addr_for_dest(const string& remote_ip, string& local)
626 562
     return -1;
627 563
   }
628 564
 
629
-  return ip_addr_to_str(&local_ss,local);
630
-}
631
-
632
-int ip_addr_to_str(sockaddr_storage* ss, string& addr)
633
-{
634
-  char ntop_buffer[INET6_ADDRSTRLEN];
635
-
636
-  if(ss->ss_family == AF_INET) {
637
-    if(!inet_ntop(AF_INET, &((sockaddr_in*)ss)->sin_addr,
638
-		  ntop_buffer,INET6_ADDRSTRLEN)) {
639
-      ERROR("Could not convert IPv4 address to string: %s",strerror(errno));
640
-      return -1;
641
-    }
642
-  }
643
-  else {
644
-    if(!inet_ntop(AF_INET6, &((sockaddr_in6*)ss)->sin6_addr,
645
-		  ntop_buffer,INET6_ADDRSTRLEN)) {
646
-      ERROR("Could not convert IPv4 address to string: %s",strerror(errno));
647
-      return -1;
648
-    }
565
+  char tmp_addr[NI_MAXHOST];
566
+  if(am_inet_ntop(&local_ss,tmp_addr,NI_MAXHOST) != NULL){
567
+    local = tmp_addr;
568
+    return 0;
649 569
   }
650
-
651
-  addr = string(ntop_buffer);
652
-  return 0;
570
+  
571
+  return -1;
653 572
 }
654 573
 
655 574
 string extract_tag(const string& addr)
... ...
@@ -189,12 +189,7 @@ string file_extension(const string& path);
189 189
 string add2path(const string& path, int n_suffix, ...);
190 190
 
191 191
 string get_addr_str(const sockaddr_storage* addr);
192
-
193
-#ifdef SUPPORT_IPV6
194
-int inet_aton_v6(const char* name, struct sockaddr_storage* ss);
195
-void set_port_v6(struct sockaddr_storage* ss, short port);
196
-short get_port_v6(struct sockaddr_storage* ss);
197
-#endif
192
+string get_addr_str_sip(const sockaddr_storage* addr);
198 193
 
199 194
 /** \brief microseconds sleep using select */
200 195
 #define sleep_us(nusecs) \
... ...
@@ -213,11 +208,6 @@ short get_port_v6(struct sockaddr_storage* ss);
213 208
 int get_local_addr_for_dest(sockaddr_storage* remote_ip, sockaddr_storage* local);
214 209
 int get_local_addr_for_dest(const string& remote_ip, string& local);
215 210
 
216
-/**
217
- * Converts an IP address contained in a sockaddr_storage into a string.
218
- */
219
-int ip_addr_to_str(sockaddr_storage* ss, string& addr);
220
-
221 211
 string extract_tag(const string& addr);
222 212
 
223 213
 /** returns true if key is in s_list, a list of items delimited by list_delim
224 214
new file mode 100644
... ...
@@ -0,0 +1,129 @@
1
+#include "ip_util.h"
2
+#include "log.h"
3
+
4
+#include <string.h>
5
+#include <errno.h>
6
+
7
+#include <netdb.h>
8
+#include <arpa/inet.h>
9
+
10
+int am_inet_pton(const char* src, struct sockaddr_storage* dst)
11
+{
12
+  char src_addr[NI_MAXHOST];
13
+
14
+  struct sockaddr_in *sin;
15
+  struct sockaddr_in6 *sin6;
16
+
17
+  bool must_be_ipv6 = false;
18
+
19
+  if(!src)
20
+    return 0;
21
+
22
+  size_t src_len = strlen(src);
23
+  if(!src_len || (src_len > NI_MAXHOST-1))
24
+    return 0;
25
+
26
+  if( (src[0] == '[') &&
27
+      (src[src_len-1] == ']') ) {
28
+
29
+    // IPv6
30
+    memcpy(src_addr,src+1,src_len-2);
31
+    src_addr[src_len-2] = '\0';
32
+    must_be_ipv6 = true;
33
+  }
34
+  else {
35
+    // IPv4
36
+    memcpy(src_addr,src,src_len+1);
37
+  }
38
+
39
+  memset((void*)dst, 0, sizeof(struct sockaddr_storage));
40
+  sin = (struct sockaddr_in *)dst;
41
+  sin6 = (struct sockaddr_in6 *)dst;
42
+    
43
+  if(!must_be_ipv6 && (inet_pton(AF_INET, src_addr, &sin->sin_addr) > 0)) {
44
+    dst->ss_family = AF_INET;
45
+    return 1;
46
+  }
47
+
48
+  if(inet_pton(AF_INET6, src_addr, &sin6->sin6_addr) > 0) {
49
+    dst->ss_family = AF_INET6;
50
+#ifdef SIN6_LEN
51
+    sin6->sin6_len = sizeof(struct sockaddr_in6);
52
+#endif
53
+    return 1;
54
+  }
55
+
56
+  return 0;
57
+}
58
+
59
+const char* am_inet_ntop(const sockaddr_storage* addr, char* str, size_t size)
60
+{
61
+  struct sockaddr_in *sin = (struct sockaddr_in *)addr;
62
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
63
+
64
+  if(addr->ss_family == AF_INET) {
65
+    if(!inet_ntop(AF_INET,&sin->sin_addr,str,size)) {
66
+      ERROR("Could not convert IPv4 address to string: %s",strerror(errno));
67
+      return NULL;
68
+    }
69
+  }
70
+  else {
71
+    if(!inet_ntop(AF_INET6,&sin6->sin6_addr,str,size)) {
72
+      ERROR("Could not convert IPv6 address to string: %s",strerror(errno));
73
+      return NULL;
74
+    }
75
+  }
76
+
77
+  return str;
78
+}
79
+
80
+const char* am_inet_ntop_sip(const sockaddr_storage* addr, char* str, size_t size)
81
+{
82
+  struct sockaddr_in *sin = (struct sockaddr_in *)addr;
83
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
84
+
85
+  if(addr->ss_family == AF_INET) {
86
+    if(!inet_ntop(AF_INET,&sin->sin_addr,str,size)) {
87
+      ERROR("Could not convert IPv4 address to string: %s",strerror(errno));
88
+      return NULL;
89
+    }
90
+  }
91
+  else {
92
+    if(!inet_ntop(AF_INET6,&sin6->sin6_addr,str+1,size-2)) {
93
+      ERROR("Could not convert IPv6 address to string: %s",strerror(errno));
94
+      return NULL;
95
+    }
96
+    size_t str_len = strlen(str);
97
+    str[0] = '[';
98
+    str[str_len] = ']';
99
+    str[str_len+1] = '\0';
100
+  }
101
+
102
+  return str;
103
+}
104
+
105
+void am_set_port(struct sockaddr_storage* addr, short port)
106
+{
107
+  struct sockaddr_in *sin = (struct sockaddr_in *)addr;
108
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
109
+
110
+  if(addr->ss_family == AF_INET) {
111
+    sin->sin_port = htons(port);
112
+  } else {
113
+    sin6->sin6_port = htons(port);
114
+  }
115
+}
116
+
117
+short am_get_port(struct sockaddr_storage* addr)
118
+{
119
+  struct sockaddr_in *sin = (struct sockaddr_in *)addr;
120
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
121
+
122
+  if(addr->ss_family == AF_INET) {
123
+    return ntohs(sin->sin_port);
124
+  }
125
+
126
+  return ntohs(sin6->sin6_port);
127
+}
128
+
129
+
0 130
new file mode 100644
... ...
@@ -0,0 +1,75 @@
1
+/*
2
+ * Copyright (C) 2012 Raphael Coeffic
3
+ *
4
+ * This file is part of SEMS, a free SIP media server.
5
+ *
6
+ * SEMS is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version. This program is released under
10
+ * the GPL with the additional exemption that compiling, linking,
11
+ * and/or using OpenSSL is allowed.
12
+ *
13
+ * For a license to use the SEMS software under conditions
14
+ * other than those described here, or to purchase support for this
15
+ * software, please contact iptel.org by e-mail at the following addresses:
16
+ *    info@iptel.org
17
+ *
18
+ * SEMS is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License 
24
+ * along with this program; if not, write to the Free Software 
25
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ */
27
+#ifndef _ip_util_h_
28
+#define _ip_util_h_
29
+
30
+#include <ctype.h>
31
+#include <sys/socket.h>
32
+#include <netinet/in.h>
33
+
34
+#define SAv4(addr) \
35
+            ((struct sockaddr_in*)addr)
36
+
37
+#define SAv6(addr) \
38
+            ((struct sockaddr_in6*)addr)
39
+
40
+#define SA_len(addr) \
41
+            ((addr)->ss_family == AF_INET ?				\
42
+	     sizeof(sockaddr_in) : sizeof(sockaddr_in6))
43
+
44
+/**
45
+ * Fill the sockaddr_storage structure based 
46
+ * on the address given in 'src'.
47
+ * @param src string representation of the IP address.
48
+ * @param dst address stucture
49
+ * @return 1 on success, 0 if address is not valid
50
+ */
51
+int am_inet_pton(const char* src, struct sockaddr_storage* dst);
52
+
53
+/**
54
+ * Print a string representation of the IP address in 'addr'.
55
+ *
56
+ * @param str buffer for the result string.
57
+ * @param size size of the result string buffer.
58
+ * @return NULL if failed, result string otherwise.
59
+ */
60
+const char* am_inet_ntop(const sockaddr_storage* addr, char* str, size_t size);
61
+
62
+/**
63
+ * Print a string representation of the IP address in 'addr'.
64
+ * IPv6 addresses are surrounded by '[' and ']', as needed for SIP header fields.
65
+ *
66
+ * @param str buffer for the result string.
67
+ * @param size size of the result string buffer.
68
+ * @return NULL if failed, result string otherwise
69
+ */
70
+const char* am_inet_ntop_sip(const sockaddr_storage* addr, char* str, size_t size);
71
+
72
+void  am_set_port(struct sockaddr_storage* addr, short port);
73
+short am_get_port(struct sockaddr_storage* addr);
74
+
75
+#endif
... ...
@@ -31,6 +31,7 @@
31 31
 #include "hash.h"
32 32
 
33 33
 #include "parse_dns.h"
34
+#include "ip_util.h"
34 35
 
35 36
 #include <sys/socket.h> 
36 37
 #include <netdb.h>
... ...
@@ -263,7 +264,7 @@ public:
263 264
 	((sockaddr_in*)sa)->sin_port = h->port;
264 265
 
265 266
 	// check if name is an IP address
266
-	if(str2ip(e->target.c_str(),sa,IPv4) == 1) {
267
+	if(am_inet_pton(e->target.c_str(),sa) == 1) {
267 268
 	    h->ip_n = -1; // flag end of IP list
268 269
 	    return 0;
269 270
 	}
... ...
@@ -635,7 +636,7 @@ int _resolver::resolve_name(const char* name,
635 636
     }
636 637
 
637 638
     // first try to detect if 'name' is already an IP address
638
-    ret = str2ip(name,sa,types);
639
+    ret = am_inet_pton(name,sa);
639 640
     if(ret == 1) {
640 641
 	h->ip_n = -1; // flag end of IP list
641 642
 	h->srv_n = -1;
... ...
@@ -676,37 +677,6 @@ int _resolver::resolve_name(const char* name,
676 677
     return -1;
677 678
 }
678 679
 
679
-int str2ip(const char* name,
680
-	   sockaddr_storage* sa,
681
-	   const address_type types)
682
-{
683
-    if(types & IPv4){
684
-	int ret = inet_pton(AF_INET,name,&((sockaddr_in*)sa)->sin_addr);
685
-	if(ret==1) {
686
-	    ((sockaddr_in*)sa)->sin_family = AF_INET;
687
-	    return 1;
688
-	}
689
-	else if(ret < 0) {
690
-	    ERROR("while trying to detect an IPv4 address '%s': %s",name,strerror(errno));
691
-	    return ret;
692
-	}
693
-    }
694
-    
695
-    if(types & IPv6){
696
-	int ret = inet_pton(AF_INET6,name,&((sockaddr_in6*)sa)->sin6_addr);
697
-	if(ret==1) {
698
-	    ((sockaddr_in6*)sa)->sin6_family = AF_INET6;
699
-	    return 1;
700
-	}
701
-	else if(ret < 0) {
702
-	    ERROR("while trying to detect an IPv6 address '%s': %s",name,strerror(errno));
703
-	    return ret;
704
-	}
705
-    }
706
-
707
-    return 0;
708
-}
709
-
710 680
 void _resolver::run()
711 681
 {
712 682
     for(;;) {
... ...
@@ -193,11 +193,6 @@ private:
193 193
 
194 194
 typedef singleton<_resolver> resolver;
195 195
 
196
-/** Converts a string into an IP structure*/
197
-int str2ip(const char* name,
198
-	   sockaddr_storage* sa,
199
-	   const address_type types);
200
-
201 196
 #endif
202 197
 
203 198
 /** EMACS **
... ...
@@ -40,6 +40,7 @@
40 40
 #include "msg_fline.h"
41 41
 #include "msg_hdrs.h"
42 42
 #include "udp_trsp.h"
43
+#include "ip_util.h"
43 44
 #include "resolver.h"
44 45
 #include "sip_ua.h"
45 46
 
... ...
@@ -52,6 +53,7 @@
52 53
 #include "AmConfig.h"
53 54
 #include "AmSipEvent.h"
54 55
 
56
+#include <netdb.h>
55 57
 #include <sys/socket.h>
56 58
 #include <netinet/in.h>
57 59
 #include <arpa/inet.h>
... ...
@@ -425,8 +427,7 @@ int _trans_layer::send_reply(trans_ticket* tt,
425 427
     if(local_socket->is_opt_set(trsp_socket::force_via_address)) {
426 428
 	DBG("force_via_address\n");
427 429
 	string via_host = c2stlstr(req->via_p1->host);
428
-	if (str2ip(via_host.c_str(), &remote_ip,
429
-			     (address_type)(IPv4 | IPv6)) != 1) {
430
+	if (am_inet_pton(via_host.c_str(), &remote_ip) != 1) {
430 431
 	    ERROR("Invalid via_host '%s'\n", via_host.c_str());
431 432
 	    delete [] reply_buf;
432 433
 	    goto end;
... ...
@@ -715,7 +716,7 @@ int _trans_layer::set_destination_ip(sip_msg* msg, cstring* next_hop, unsigned s
715 716
     string nh = c2stlstr(*next_hop);
716 717
 
717 718
     DBG("checking whether '%s' is IP address...\n", nh.c_str());
718
-    if (str2ip(nh.c_str(), &(msg->remote_ip), IPv4) != 1) {
719
+    if (am_inet_pton(nh.c_str(), &(msg->remote_ip)) != 1) {
719 720
 
720 721
 	// nh does NOT contain a valid IP address
721 722
     
... ...
@@ -1906,8 +1907,6 @@ trsp_socket* _trans_layer::find_transport(sockaddr_storage* remote_ip)
1906 1907
   }
1907 1908
 
1908 1909
   sockaddr_storage from;
1909
-  string local_ip;
1910
-
1911 1910
   socklen_t    len=sizeof(from);
1912 1911
   trsp_socket* tsock=NULL;
1913 1912
 
... ...
@@ -1941,12 +1940,13 @@ trsp_socket* _trans_layer::find_transport(sockaddr_storage* remote_ip)
1941 1940
       return tsock;
1942 1941
 
1943 1942
   // try with alternative address
1944
-  if(ip_addr_to_str(&from,local_ip) == 0) {
1943
+  char local_ip[NI_MAXHOST];
1944
+  if(am_inet_ntop(&from,local_ip,NI_MAXHOST) != NULL) {
1945 1945
       map<string,unsigned short>::iterator if_it = AmConfig::LocalSIPIP2If.find(local_ip);
1946 1946
       if(if_it == AmConfig::LocalSIPIP2If.end()){
1947 1947
 	  ERROR("Could not find a local interface for "
1948 1948
 		"resolved local IP (local_ip='%s')",
1949
-		local_ip.c_str());
1949
+		local_ip);
1950 1950
       }
1951 1951
       else {
1952 1952
 	  tsock = transports[if_it->second];
... ...
@@ -102,24 +102,17 @@ unsigned short trsp_socket::get_if()
102 102
     return if_num;
103 103
 }
104 104
 
105
-int trsp_socket::send(const sockaddr_storage* sa, const char* msg, const int msg_len)
105
+int trsp_socket::send(const sockaddr_storage* sa, const char* msg, 
106
+		      const int msg_len)
106 107
 {
107 108
     if (log_level_raw_msgs >= 0) {
108 109
 	_LOG(log_level_raw_msgs, 
109 110
 	     "send  msg\n--++--\n%.*s--++--\n", msg_len, msg);
110 111
     }
111 112
 
112
-  int err;
113
-#ifdef SUPPORT_IPV6
114
-  if (sa->ss_family == AF_INET6) {
115
-    err = sendto(sd, msg, msg_len, 0, (const struct sockaddr*)sa, sizeof(sockaddr_in6));
116
-  }
117
-  else {
118
-#endif
119
-    err = sendto(sd, msg, msg_len, 0, (const struct sockaddr*)sa, sizeof(sockaddr_in));
120
-#ifdef SUPPORT_IPV6
121
-  }
122
-#endif
113
+  int err = sendto(sd, msg, msg_len, 0, (const struct sockaddr*)sa, 
114
+		   sa->ss_family == AF_INET ? 
115
+		   sizeof(sockaddr_in) : sizeof(sockaddr_in6));
123 116
 
124 117
   if (err < 0) {
125 118
     ERROR("sendto: %s\n",strerror(errno));
... ...
@@ -35,12 +35,6 @@
35 35
 #include <string>
36 36
 using std::string;
37 37
 
38
-#define SAv4(addr) \
39
-            ((struct sockaddr_in*)addr)
40
-
41
-#define SAv6(addr) \
42
-            ((struct sockaddr_in6*)addr)
43
-
44 38
 class trsp_socket
45 39
 {
46 40
 public:
... ...
@@ -27,22 +27,25 @@
27 27
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 28
  */
29 29
 
30
+#define __APPLE_USE_RFC_3542
31
+#include <netinet/in.h>
32
+
30 33
 #include "udp_trsp.h"
34
+#include "ip_util.h"
31 35
 #include "sip_parser.h"
32 36
 #include "trans_layer.h"
33 37
 #include "log.h"
34 38
 
35 39
 #include "SipCtrlInterface.h"
36 40
 
37
-#include <netinet/in.h>
41
+#include <netdb.h>
42
+
38 43
 #include <sys/param.h>
39 44
 #include <arpa/inet.h>
40 45
 
41 46
 #include <errno.h>
42 47
 #include <string.h>
43 48
 
44
-// FIXME: support IPv6
45
-
46 49
 #if defined IP_RECVDSTADDR
47 50
 # define DSTADDR_SOCKOPT IP_RECVDSTADDR
48 51
 # define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_addr)))
... ...
@@ -52,13 +55,19 @@
52 55
 # define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo)))
53 56
 # define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
54 57
 #else
55
-# error "can't determine socket option (IP_RECVDSTADDR or IP_PKTINFO)"
58
+# error "can't determine v4 socket option (IP_RECVDSTADDR or IP_PKTINFO)"
59
+#endif
60
+
61
+#if !defined IPV6_RECVPKTINFO
62
+# define DSTADDR6_SOCKOPT IPV6_PKTINFO
63
+# define dstaddr6(x) (&(((struct in6_pktinfo *)(CMSG_DATA(x)))->ipi6_addr))
64
+#elif defined IPV6_PKTINFO
65
+# define DSTADDR6_SOCKOPT IPV6_RECVPKTINFO
66
+# define dstaddr6(x) (&(((struct in6_pktinfo *)(CMSG_DATA(x)))->ipi6_addr))
67
+#else
68
+# error "cant't determine v6 socket option (IPV6_RECVPKTINFO or IPV6_PKTINFO)"
56 69
 #endif
57 70
 
58
-// union control_data {
59
-//     struct cmsghdr  cmsg;
60
-//     u_char          data[DSTADDR_DATASIZE];
61
-// };
62 71
 
63 72
 /** @see trsp_socket */
64 73
 int udp_trsp_socket::bind(const string& bind_ip, unsigned short bind_port)
... ...
@@ -68,33 +77,29 @@ int udp_trsp_socket::bind(const string& bind_ip, unsigned short bind_port)
68 77
 	close(sd);
69 78
     }
70 79
     
71
-    memset(&addr,0,sizeof(addr));
72
-
73
-    addr.ss_family = AF_INET;
74
-#if defined(BSD44SOCKETS)
75
-    addr.ss_len = sizeof(struct sockaddr_in);
76
-#endif
77
-    SAv4(&addr)->sin_port = htons(bind_port);
78
-
79
-    if(inet_aton(bind_ip.c_str(),&SAv4(&addr)->sin_addr)<0){
80
+    if(am_inet_pton(bind_ip.c_str(),&addr) == 0){
80 81
 	
81
-	ERROR("inet_aton: %s\n",strerror(errno));
82
+	ERROR("am_inet_pton(%s): %s\n",bind_ip.c_str(),strerror(errno));
82 83
 	return -1;
83 84
     }
85
+    
86
+    if( ((addr.ss_family == AF_INET) && 
87
+     	 (SAv4(&addr)->sin_addr.s_addr == INADDR_ANY)) ||
88
+     	((addr.ss_family == AF_INET6) && 
89
+     	 IN6_IS_ADDR_UNSPECIFIED(&SAv6(&addr)->sin6_addr)) ){
84 90
 
85
-    if(SAv4(&addr)->sin_addr.s_addr == INADDR_ANY){
86
-	ERROR("Sorry, we cannot bind 'ANY' address\n");
87
-	return -1;
91
+     	ERROR("Sorry, we cannot bind to 'ANY' address\n");
92
+     	return -1;
88 93
     }
89 94
 
90
-    if((sd = socket(PF_INET,SOCK_DGRAM,0)) == -1){
95
+    am_set_port(&addr,bind_port);
96
+
97
+    if((sd = socket(addr.ss_family,SOCK_DGRAM,0)) == -1){
91 98
 	ERROR("socket: %s\n",strerror(errno));
92 99
 	return -1;
93 100
     } 
94 101
     
95
-
96
-    if(::bind(sd,(const struct sockaddr*)&addr,
97
-	     sizeof(struct sockaddr_in))) {
102
+    if(::bind(sd,(const struct sockaddr*)&addr,SA_len(&addr))) {
98 103
 
99 104
 	ERROR("bind: %s\n",strerror(errno));
100 105
 	close(sd);
... ...
@@ -103,14 +108,25 @@ int udp_trsp_socket::bind(const string& bind_ip, unsigned short bind_port)
103 108
     
104 109
     int true_opt = 1;
105 110
 
106
-    if(setsockopt(sd, IPPROTO_IP, DSTADDR_SOCKOPT,
107
-		  (void*)&true_opt, sizeof (true_opt)) == -1) {
108
-	
109
-	ERROR("%s\n",strerror(errno));
110
-	close(sd);
111
-	return -1;
111
+    if(addr.ss_family == AF_INET) {
112
+	if(setsockopt(sd, IPPROTO_IP, DSTADDR_SOCKOPT,
113
+		      (void*)&true_opt, sizeof (true_opt)) == -1) {
114
+	    
115
+	    ERROR("%s\n",strerror(errno));
116
+	    close(sd);
117
+	    return -1;
118
+	}
119
+    } else {
120
+	if(setsockopt(sd, IPPROTO_IPV6, DSTADDR6_SOCKOPT,
121
+		      (void*)&true_opt, sizeof (true_opt)) == -1) {
122
+	    
123
+	    ERROR("%s\n",strerror(errno));
124
+	    close(sd);
125
+	    return -1;
126
+	}
112 127
     }
113 128
 
129
+
114 130
     if (SipCtrlInterface::udp_rcvbuf > 0) {
115 131
 	DBG("trying to set SIP UDP socket buffer to %d\n",
116 132
 	    SipCtrlInterface::udp_rcvbuf);
... ...
@@ -138,7 +154,7 @@ int udp_trsp_socket::bind(const string& bind_ip, unsigned short bind_port)
138 154
     port = bind_port;
139 155
     ip   = bind_ip;
140 156
 
141
-    DBG("UDP transport bound to %s:%i\n",ip.c_str(),port);
157
+    DBG("UDP transport bound to %s/%i\n",ip.c_str(),port);
142 158
 
143 159
     return 0;
144 160
 }
... ...
@@ -223,10 +239,19 @@ void udp_trsp::run()
223 239
                 cmsgptr->cmsg_type == DSTADDR_SOCKOPT) {
224 240
 		
225 241
 		s_msg->local_ip.ss_family = AF_INET;
226
-		((sockaddr_in*)(&s_msg->local_ip))->sin_port   = htons(sock->get_port());
227
-                memcpy(&((sockaddr_in*)(&s_msg->local_ip))->sin_addr,dstaddr(cmsgptr),sizeof(in_addr));
242
+	        am_set_port(&s_msg->local_ip,sock->get_port());
243
+                memcpy(&((sockaddr_in*)(&s_msg->local_ip))->sin_addr,
244
+		       dstaddr(cmsgptr),sizeof(in_addr));
228 245
             }
229
-        } 
246
+	    else if(cmsgptr->cmsg_level == IPPROTO_IPV6 &&
247
+		    cmsgptr->cmsg_type == IPV6_PKTINFO) {
248
+
249
+		s_msg->local_ip.ss_family = AF_INET6;
250
+	        am_set_port(&s_msg->local_ip,sock->get_port());
251
+                memcpy(&((sockaddr_in6*)(&s_msg->local_ip))->sin6_addr,
252
+		       dstaddr6(cmsgptr),sizeof(in6_addr));
253
+	    }
254
+        }
230 255
 
231 256
 	// pass message to the parser / transaction layer
232 257
 	trans_layer::instance()->received_msg(s_msg);