[asterisk-commits] blanchet: branch blanchet/v6 r60523 - /team/blanchet/v6/channels/chan_sip.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Apr 6 12:04:53 MST 2007


Author: blanchet
Date: Fri Apr  6 14:04:53 2007
New Revision: 60523

URL: http://svn.digium.com/view/asterisk?view=rev&rev=60523
Log:
converted chan_sip to support both v4 and v6 the same way: make it IP version in
dependent. as you see, major changes to networking code (and others). 
for additional information, see README-IPV6.txt


Modified:
    team/blanchet/v6/channels/chan_sip.c

Modified: team/blanchet/v6/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/blanchet/v6/channels/chan_sip.c?view=diff&rev=60523&r1=60522&r2=60523
==============================================================================
--- team/blanchet/v6/channels/chan_sip.c (original)
+++ team/blanchet/v6/channels/chan_sip.c Fri Apr  6 14:04:53 2007
@@ -85,6 +85,14 @@
  * This is deprecated and will be removed after the 1.4 release
  * - the SIPUSERAGENT dialplan variable
  * - the ALERT_INFO dialplan variable
+ *
+ * \par IPv6 support:
+ *  uses the updated netsock library which provides ip version independant
+ *   routines for sockets.
+ *  currently handles one socket per address family (one v4 socket, one v6 socket)
+ * see more info in README.ipv6
+ * \author Marc Blanchet <marc.blanchet at viagenie.ca>
+ * \author Frederick Lefebvre <frederick.lefebvre at viagenie.ca>
  */
 
 
@@ -142,6 +150,7 @@
 #include "asterisk/monitor.h"
 #include "asterisk/localtime.h"
 #include "asterisk/abstract_jb.h"
+#include "asterisk/netsock.h"
 #include "asterisk/compiler.h"
 #include "asterisk/threadstorage.h"
 #include "asterisk/translate.h"
@@ -592,7 +601,6 @@
 
 static struct sched_context *sched;     /*!< The scheduling context */
 static struct io_context *io;           /*!< The IO context */
-static int *sipsock_read_id;            /*!< ID of IO entry for sipsock FD */
 
 #define DEC_CALL_LIMIT	0
 #define INC_CALL_LIMIT	1
@@ -950,8 +958,9 @@
 	int redircodecs;			/*!< Redirect codecs */
 	int maxcallbitrate;			/*!< Maximum Call Bitrate for Video Calls */	
 	struct t38properties t38;		/*!< T38 settings */
-	struct sockaddr_in udptlredirip;	/*!< Where our T.38 UDPTL should be going if not to us */
-	struct ast_udptl *udptl;		/*!< T.38 UDPTL session */
+	struct sockaddr_storage udptlredirip;	/*!< Where our T.38 UDPTL should be going if not to us */
+        socklen_t udptlredirip_len;
+	struct ast_viudptl *udptl;		/*!< T.38 UDPTL session */
 	int callingpres;			/*!< Calling presentation */
 	int authtries;				/*!< Times we've tried to authenticate */
 	int expiry;				/*!< How long we take to expire */
@@ -959,14 +968,19 @@
 	char tag[11];				/*!< Our tag for this session */
 	int sessionid;				/*!< SDP Session ID */
 	int sessionversion;			/*!< SDP Session Version */
-	struct sockaddr_in sa;			/*!< Our peer */
-	struct sockaddr_in redirip;		/*!< Where our RTP should be going if not to us */
-	struct sockaddr_in vredirip;		/*!< Where our Video RTP should be going if not to us */
+	struct sockaddr_storage sa;		/*!< Our peer */
+	socklen_t sa_len;
+	struct sockaddr_storage redirip;	/*!< Where our RTP should be going if not to us */
+	socklen_t redirip_len;
+	struct sockaddr_storage vredirip;	/*!< Where our Video RTP should be going if not to us */
+	socklen_t vredirip_len;
 	time_t lastrtprx;			/*!< Last RTP received */
 	time_t lastrtptx;			/*!< Last RTP sent */
 	int rtptimeout;				/*!< RTP timeout time */
-	struct sockaddr_in recv;		/*!< Received as */
-	struct in_addr ourip;			/*!< Our IP */
+	struct sockaddr_storage recv;		/*!< Received as */
+	socklen_t recv_len;
+	struct sockaddr_storage ourip;			/*!< Our IP */
+	socklen_t ourip_len;
 	struct ast_channel *owner;		/*!< Who owns us (if we have an owner) */
 	struct sip_route *route;		/*!< Head of linked list of routing steps (fm Record-Route) */
 	int route_persistant;			/*!< Is this the "real" route? */
@@ -993,14 +1007,15 @@
 	struct sip_peer *relatedpeer;		/*!< If this dialog is related to a peer, which one 
 							Used in peerpoke, mwi subscriptions */
 	struct sip_registry *registry;		/*!< If this is a REGISTER dialog, to which registry */
-	struct ast_rtp *rtp;			/*!< RTP Session */
-	struct ast_rtp *vrtp;			/*!< Video RTP session */
+	struct ast_virtp *rtp;			/*!< RTP Session */
+	struct ast_virtp *vrtp;			/*!< Video RTP session */
 	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
 	struct sip_history_head *history;	/*!< History of this SIP dialog */
 	struct ast_variable *chanvars;		/*!< Channel variables to set for inbound call */
 	struct sip_pvt *next;			/*!< Next dialog in chain */
 	struct sip_invite_param *options;	/*!< Options for INVITE */
 	int autoframing;
+	struct ast_vinetsock *netsock;
 } *iflist = NULL;
 
 #define FLAG_RESPONSE (1 << 0)
@@ -1097,7 +1112,8 @@
 	int rtpkeepalive;		/*!<  Send RTP packets for keepalive */
 	ast_group_t callgroup;		/*!<  Call group */
 	ast_group_t pickupgroup;	/*!<  Pickup group */
-	struct sockaddr_in addr;	/*!<  IP address of peer */
+	struct sockaddr_storage addr;	/*!<  IP address of peer */
+	socklen_t addr_len;
 	int maxcallbitrate;		/*!< Maximum Bitrate for a video call */
 	
 	/* Qualification */
@@ -1107,7 +1123,8 @@
 	int maxms;			/*!<  Max ms we will accept for the host to be up, 0 to not monitor */
 	struct timeval ps;		/*!<  Ping send time */
 	
-	struct sockaddr_in defaddr;	/*!<  Default IP address, used until registration */
+	struct sockaddr_storage defaddr;/*!<  Default IP address, used until registration */
+	socklen_t defaddr_len;
 	struct ast_ha *ha;		/*!<  Access control list */
 	struct ast_variable *chanvars;	/*!<  Variables to set for channel created by user */
 	struct sip_pvt *mwipvt;		/*!<  Subscription for MWI */
@@ -1145,7 +1162,8 @@
 	time_t regtime;		/*!< Last succesful registration time */
 	int callid_valid;		/*!< 0 means we haven't chosen callid for this registry yet. */
 	unsigned int ocseq;		/*!< Sequence number we got to for REGISTERs for this registry */
-	struct sockaddr_in us;		/*!< Who the server thinks we are */
+	struct sockaddr_storage us;	/*!< Who the server thinks we are */
+	socklen_t us_len;
 	int noncecount;			/*!< Nonce-count */
 	char lastmsg[256];		/*!< Last Message sent/received */
 };
@@ -1178,18 +1196,18 @@
 
 
 /* --- Sockets and networking --------------*/
-static int sipsock  = -1;			/*!< Main socket for SIP network communication */
-static struct sockaddr_in bindaddr = { 0, };	/*!< The address we bind to */
-static struct sockaddr_in externip;		/*!< External IP address if we are behind NAT */
-static char externhost[MAXHOSTNAMELEN];		/*!< External host name (possibly with dynamic DNS and DHCP */
+static struct ast_vinetsock_list *netsocks = NULL;
+static struct sockaddr_storage externip;	/*!< External IP address if we are behind NAT */
+static socklen_t externip_len = 0;
+static char externhost[NI_MAXHOST];		/*!< External host name (possibly with dynamic DNS and DHCP */
 static time_t externexpire = 0;			/*!< Expiration counter for re-resolving external host name in dynamic DNS */
 static int externrefresh = 10;
 static struct ast_ha *localaddr;		/*!< List of local networks, on the same side of NAT as this Asterisk */
-static struct in_addr __ourip;
-static struct sockaddr_in outboundproxyip;
-static int ourport;
-static struct sockaddr_in debugaddr;
-
+static struct sockaddr_storage outboundproxyip;
+static socklen_t outboundproxyip_len = 0;
+static int defport = STANDARD_SIP_PORT;
+static struct sockaddr_storage debugaddr;
+static socklen_t debugaddr_len;
 static struct ast_config *notify_types;		/*!< The list of manual NOTIFY types we know how to send */
 
 /*---------------------------- Forward declarations of functions in chan_sip.c */
@@ -1218,7 +1236,7 @@
 static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
 static int retrans_pkt(void *data);
 static int transmit_sip_request(struct sip_pvt *p, struct sip_request *req);
-static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
+static int transmit_response_using_temp(ast_string_field callid, struct sockaddr *sa, socklen_t sa_len, struct ast_vinetsock *ns, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
 static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
 static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
 static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
@@ -1247,8 +1265,12 @@
 static int does_peer_need_mwi(struct sip_peer *peer);
 
 /*--- Dialog management */
-static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
+static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr *sa,
+				 socklen_t sa_len, struct ast_vinetsock *ns,
 				 int useglobal_nat, const int intended_method);
+static struct sip_pvt *sip_alloc_fromhost(ast_string_field callid, const char *hoststr,
+					  struct sip_peer *peer_param,
+					  int useglobal_nat, const int intended_method);
 static int __sip_autodestruct(void *data);
 static void sip_scheddestroy(struct sip_pvt *p, int ms);
 static void sip_cancel_destroy(struct sip_pvt *p);
@@ -1261,12 +1283,14 @@
 static int update_call_counter(struct sip_pvt *fup, int event);
 static int hangup_sip2cause(int cause);
 static const char *hangup_cause2sip(int cause);
-static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method);
+static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr *sa,
+				 socklen_t sa_len, struct ast_vinetsock* ns,
+				 const int intended_method);
 static void free_old_route(struct sip_route *route);
 static void list_route(struct sip_route *route);
 static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards);
-static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin,
-					      struct sip_request *req, char *uri);
+static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr *sa,
+					      socklen_t sa_len, struct sip_request *req, char *uri);
 static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);
 static void check_pendings(struct sip_pvt *p);
 static void *sip_park_thread(void *stuff);
@@ -1286,6 +1310,8 @@
 				char **m_buf, size_t *m_size, char **a_buf, size_t *a_size,
 				int debug);
 static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p);
+static const char *ast_sip_sdp_sa2addrtype(struct sockaddr* sa);
+static int ast_sip_sdp_addrtype2af(const char* addrtype);
 
 /*--- Authentication stuff */
 static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len);
@@ -1295,8 +1321,8 @@
 					 char *uri, enum xmittype reliable, int ignore);
 static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
 					      int sipmethod, char *uri, enum xmittype reliable,
-					      struct sockaddr_in *sin, struct sip_peer **authpeer);
-static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin);
+					      struct sockaddr *sa, socklen_t sa_len, struct sip_peer **authpeer);
+static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr *sa, socklen_t sa_len);
 
 /*--- Domain handling */
 static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
@@ -1317,7 +1343,7 @@
 static int restart_monitor(void);
 static int sip_send_mwi_to_peer(struct sip_peer *peer);
 static void sip_destroy(struct sip_pvt *p);
-static int sip_addrcmp(char *name, struct sockaddr_in *sin);	/* Support for peer matching */
+static int sip_addrcmp(char *name, struct sockaddr *sin, socklen_t *sinlen); /* Support for peer matching */
 static int sip_refer_allocate(struct sip_pvt *p);
 static void ast_quiet_chan(struct ast_channel *chan);
 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
@@ -1391,7 +1417,8 @@
 	a SIP dialog
 */
 static void sip_dump_history(struct sip_pvt *dialog);	/* Dump history to LOG_DEBUG at end of dialog, before destroying data */
-static inline int sip_debug_test_addr(const struct sockaddr_in *addr);
+      static inline int sip_debug_test_addr(const struct sockaddr *addr, 
+					    socklen_t addrlen);
 static inline int sip_debug_test_pvt(struct sip_pvt *p);
 static void append_history_full(struct sip_pvt *p, const char *fmt, ...);
 static void sip_dump_history(struct sip_pvt *dialog);
@@ -1408,7 +1435,7 @@
 static void set_peer_defaults(struct sip_peer *peer);
 static struct sip_peer *temp_peer(const char *name);
 static void register_peer_exten(struct sip_peer *peer, int onoff);
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime);
+static struct sip_peer *find_peer(const char *peer, struct sockaddr *sa, socklen_t sa_len, int realtime);
 static struct sip_user *find_user(const char *name, int realtime);
 static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
 static int expire_register(void *data);
@@ -1417,14 +1444,17 @@
 static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v);
 
 /* Realtime device support */
-static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expirey);
+static void realtime_update_peer(const char *peername, struct sockaddr *sin,
+				 socklen_t sinlen, const char *username, 
+				 const char *fullcontact, int expirey);
 static struct sip_user *realtime_user(const char *username);
 static void update_peer(struct sip_peer *p, int expiry);
-static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
+static struct sip_peer *realtime_peer(const char *peername, struct sockaddr *sa, socklen_t sa_len);
 static int sip_prune_realtime(int fd, int argc, char *argv[]);
 
 /*--- Internal UA client handling (outbound registrations) */
-static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us);
+static int ast_sip_ouraddrfor(struct sockaddr *them, socklen_t them_len,
+			      struct sockaddr *us, socklen_t *us_len);
 static void sip_registry_destroy(struct sip_registry *reg);
 static int sip_register(char *value, int lineno);
 static char *regstate2str(enum sipregistrystate regstate) attribute_const;
@@ -1454,7 +1484,7 @@
 static int get_also_info(struct sip_pvt *p, struct sip_request *oreq);
 static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
 static int set_address_from_contact(struct sip_pvt *pvt);
-static void check_via(struct sip_pvt *p, struct sip_request *req);
+      static void check_via(struct sip_pvt *p, struct sip_request *req, int af);
 static char *get_calleridname(const char *input, char *output, size_t outputsize);
 static int get_rpid_num(const char *input, char *output, int maxlen);
 static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq);
@@ -1470,10 +1500,8 @@
 static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod);
 static int init_resp(struct sip_request *resp, const char *msg);
 static int respprep(struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req);
-static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p);
+static const struct sockaddr *sip_real_dst(const struct sip_pvt *p, socklen_t *sa_len);
 static void build_via(struct sip_pvt *p);
-static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer);
-static int create_addr(struct sip_pvt *dialog, const char *opeer);
 static char *generate_random_string(char *buf, size_t size);
 static void build_callid_pvt(struct sip_pvt *pvt);
 static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain);
@@ -1494,18 +1522,18 @@
 static void build_rpid(struct sip_pvt *p);
 
 /*------Request handling functions */
-static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock);
-static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e);
+static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr *sa, socklen_t sa_len, int *recount, int *nounlock);
+static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr *sa, socklen_t sa_len, int *recount, char *e);
 static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, int seqno, int *nounlock);
-static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, char *e);
-static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
+static int handle_request_bye(struct sip_pvt *p, struct sip_request *req, struct sockaddr* sa, socklen_t sa_len);
+static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr *sa, socklen_t sa_len, char *e);
+static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req, struct sockaddr *sa, socklen_t sa_len);
 static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
+static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr *sa, socklen_t sa_len, int seqno, char *e);
 static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
 static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
-static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, int seqno, struct sockaddr_in *sin);
-static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
+static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, int seqno, struct sockaddr *sa, socklen_t sa_len);
+static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr *sa, socklen_t sal_len, int seqno, char *e);
 static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno);
 
 /*------Response handling functions */
@@ -1515,9 +1543,9 @@
 static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno);
 
 /*----- RTP interface functions */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);
-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_virtp *rtp, struct ast_virtp *vrtp, int codecs, int nat_active);
+static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_virtp **rtp);
+static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_virtp **rtp);
 static int sip_get_codec(struct ast_channel *chan);
 static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
 
@@ -1525,8 +1553,8 @@
 static int sip_handle_t38_reinvite(struct ast_channel *chan, struct sip_pvt *pvt, int reinvite); /*!< T38 negotiation helper function */
 static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
 static int transmit_reinvite_with_t38_sdp(struct sip_pvt *p);
-static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan);
-static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl);
+static struct ast_viudptl *sip_get_viudptl_peer(struct ast_channel *chan);
+static int sip_set_viudptl_peer(struct ast_channel *chan, struct ast_viudptl *udptl);
 
 /*! \brief Definition of this channel for PBX channel registration */
 static const struct ast_channel_tech sip_tech = {
@@ -1547,7 +1575,7 @@
 	.fixup = sip_fixup,
 	.send_digit_begin = sip_senddigit_begin,
 	.send_digit_end = sip_senddigit_end,
-	.bridge = ast_rtp_bridge,
+	.bridge = ast_virtp_bridge,
 	.send_text = sip_sendtext,
 	.func_channel_read = acf_channel_read,
 };
@@ -1586,19 +1614,19 @@
 	} while (0)
 
 /*! \brief Interface structure with callbacks used to connect to RTP module */
-static struct ast_rtp_protocol sip_rtp = {
+static struct ast_virtp_protocol sip_rtp = {
 	type: "SIP",
-	get_rtp_info: sip_get_rtp_peer,
-	get_vrtp_info: sip_get_vrtp_peer,
-	set_rtp_peer: sip_set_rtp_peer,
+	get_virtp_info: sip_get_rtp_peer,
+	get_vivrtp_info: sip_get_vrtp_peer,
+	set_virtp_peer: sip_set_rtp_peer,
 	get_codec: sip_get_codec,
 };
 
 /*! \brief Interface structure with callbacks used to connect to UDPTL module*/
-static struct ast_udptl_protocol sip_udptl = {
+static struct ast_viudptl_protocol sip_udptl = {
 	type: "SIP",
-	get_udptl_info: sip_get_udptl_peer,
-	set_udptl_peer: sip_set_udptl_peer,
+	get_udptl_info: sip_get_viudptl_peer,
+	set_udptl_peer: sip_set_viudptl_peer,
 };
 
 /*! \brief Convert transfer status to string */
@@ -1711,23 +1739,30 @@
 }
 
 /*! \brief See if we pass debug IP filter */
-static inline int sip_debug_test_addr(const struct sockaddr_in *addr) 
+static inline int sip_debug_test_addr(const struct sockaddr *addr, socklen_t addrlen) 
 {
 	if (!sipdebug)
 		return 0;
-	if (debugaddr.sin_addr.s_addr) {
-		if (((ntohs(debugaddr.sin_port) != 0)
-			&& (debugaddr.sin_port != addr->sin_port))
-			|| (debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
+	if (debugaddr_len) {
+		if (((ast_vinetsock_sa_getport((struct sockaddr*)&debugaddr, debugaddr_len) != 0)
+		     && ast_vinetsock_sacmp_port((struct sockaddr*)&debugaddr, debugaddr_len, addr, addrlen))
+		    || ast_vinetsock_sacmp((struct sockaddr*)&debugaddr, debugaddr_len, addr, addrlen,1))
 			return 0;
 	}
 	return 1;
 }
 
 /*! \brief The real destination address for a write */
-static const struct sockaddr_in *sip_real_dst(const struct sip_pvt *p)
-{
-	return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? &p->recv : &p->sa;
+static const struct sockaddr *sip_real_dst(const struct sip_pvt *p, 
+					   socklen_t *sa_len)
+{
+	if (ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE) {
+		*sa_len = p->recv_len;
+		return (struct sockaddr*)&p->recv;
+	} else {
+		*sa_len = p->sa_len;
+		return (struct sockaddr*)&p->sa;
+	}
 }
 
 /*! \brief Display SIP nat mode */
@@ -1739,20 +1774,31 @@
 /*! \brief Test PVT for debugging output */
 static inline int sip_debug_test_pvt(struct sip_pvt *p) 
 {
+	socklen_t sa_len = 0;
 	if (!sipdebug)
 		return 0;
-	return sip_debug_test_addr(sip_real_dst(p));
+	return sip_debug_test_addr(sip_real_dst(p, &sa_len), sa_len);
 }
 
 /*! \brief Transmit SIP message */
 static int __sip_xmit(struct sip_pvt *p, char *data, int len)
 {
 	int res;
-	const struct sockaddr_in *dst = sip_real_dst(p);
-	res = sendto(sipsock, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+	char hostport[NI_MAXHOST];
+	socklen_t dstlen = 0;
+	int sockfd = 0;
+	const struct sockaddr *dst = sip_real_dst(p, &dstlen);
+
+	ast_vinetsock_sa_get_hostport(dst, dstlen, hostport, sizeof(hostport));
+	sockfd = ast_vinetsock_list_getsockfd(netsocks, dst->sa_family);
+	if (!sockfd) {
+		ast_log(LOG_WARNING, "sip_xmit : Tried to transmit a SIP msg to %s but no opened socket\n", hostport);
+		return -1;
+	}
+	res=sendto(sockfd, data, len, 0, dst, dstlen);
 
 	if (res != len)
-		ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno));
+		ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, hostport, res, strerror(errno));
 	return res;
 }
 
@@ -1760,12 +1806,16 @@
 /*! \brief Build a Via header for a request */
 static void build_via(struct sip_pvt *p)
 {
+	char hostport[NI_MAXHOST];
+
 	/* Work around buggy UNIDEN UIP200 firmware */
 	const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
 
+	ast_vinetsock_sa_get_hostport((struct sockaddr*)&p->ourip, p->ourip_len, hostport, sizeof(hostport));
+
 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
-	ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
-			 ast_inet_ntoa(p->ourip), ourport, p->branch, rport);
+	ast_string_field_build(p, via, "SIP/2.0/UDP %s;branch=z9hG4bK%08x%s",
+			       hostport, p->branch, rport);
 }
 
 /*! \brief NAT fix - decide which IP address to use for ASterisk server?
@@ -1774,35 +1824,49 @@
  * apply it to their address to see if we need to substitute our
  * externip or can get away with our internal bindaddr
  */
-static enum sip_result ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
-{
-	struct sockaddr_in theirs, ours;
+static enum sip_result ast_sip_ouraddrfor(struct sockaddr *them, socklen_t them_len, struct sockaddr *us, socklen_t *us_len)
+{
+	struct ast_vinetsock* ns = NULL;
+	int portno = 0;
+	char iabuf[NI_MAXHOST];
+	char sbuf[NI_MAXSERV];
+
+	/* Sanity check */
+	if (!them || !them_len)
+		return AST_FAILURE;
 
 	/* Get our local information */
-	ast_ouraddrfor(them, us);
-	theirs.sin_addr = *them;
-	ours.sin_addr = *us;
-
-	if (localaddr && externip.sin_addr.s_addr &&
-	    (ast_apply_ha(localaddr, &theirs)) &&
-	    (!global_matchexterniplocally || !ast_apply_ha(localaddr, &ours))) {
-		if (externexpire && time(NULL) >= externexpire) {
-			struct ast_hostent ahp;
-			struct hostent *hp;
-
-			externexpire = time(NULL) + externrefresh;
-			if ((hp = ast_gethostbyname(externhost, &ahp))) {
-				memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
-			} else
+	if(ast_vinetsock_sa_getsrc(them, them_len, us, us_len, SOCK_DGRAM))
+		return AST_FAILURE;
+
+	ns = ast_vinetsock_find_best(netsocks, them, them_len, AF_UNSPEC);
+	portno = ns ? ast_vinetsock_getport(ns) : defport;
+	ast_vinetsock_sa_setport((struct sockaddr*)us, portno);
+	ast_vinetsock_free(ns);
+	ns = NULL;
+
+	/* If we are not on IPv4, we can return here as
+	 * NATs are specific to IPv4 */
+	if (!ast_vinetsock_sa_is_ipv4(them))
+		return AST_SUCCESS;
+
+	if (localaddr && externip_len &&
+		(!ast_vinetsock_sa_is_ipv4(them) || 
+			ast_apply_ha(localaddr, (struct sockaddr_in*)them)) &&
+		(!ast_vinetsock_sa_is_ipv4(us) || !global_matchexterniplocally || 
+			!ast_apply_ha(localaddr, (struct sockaddr_in*)us))) {
+                if (externexpire && time(NULL) >= externexpire) {
+                        externexpire = time(NULL) + externrefresh;
+			if (ast_vinetsock_sa_fromstr(externhost, sbuf, (struct sockaddr*)&externip, &externip_len, AF_INET, 0))
 				ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
-		}
-		*us = externip.sin_addr;
+                }
+		memcpy(us, &externip, sizeof(externip));
+		*us_len = externip_len;
 		if (option_debug) {
-			ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", 
-				ast_inet_ntoa(*(struct in_addr *)&them->s_addr));
-		}
-	} else if (bindaddr.sin_addr.s_addr)
-		*us = bindaddr.sin_addr;
+			ast_vinetsock_sa_getaddr(them, them_len, iabuf, sizeof(iabuf));
+			ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", iabuf);
+                }
+	}
 	return AST_SUCCESS;
 }
 
@@ -1852,6 +1916,7 @@
 {
 	struct sip_pkt *pkt = data, *prev, *cur = NULL;
 	int reschedule = DEFAULT_RETRANS;
+	char hostport[NI_MAXHOST];
 
 	/* Lock channel PVT */
 	ast_mutex_lock(&pkt->owner->lock);
@@ -1883,11 +1948,13 @@
  		} 
 
 		if (sip_debug_test_pvt(pkt->owner)) {
-			const struct sockaddr_in *dst = sip_real_dst(pkt->owner);
-			ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
-				pkt->retrans, sip_nat_mode(pkt->owner),
-				ast_inet_ntoa(dst->sin_addr),
-				ntohs(dst->sin_port), pkt->data);
+			socklen_t dstlen = 0;
+			const struct sockaddr *dst = sip_real_dst(pkt->owner, &dstlen);
+	
+			ast_vinetsock_sa_get_hostport(dst, dstlen, hostport, sizeof(hostport));
+			ast_verbose("Retransmitting #%d (%s) to %s:\n%s\n---\n",
+				    pkt->retrans, sip_nat_mode(pkt->owner),
+				    hostport, pkt->data);
 		}
 
 		append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
@@ -2158,15 +2225,17 @@
 static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno)
 {
 	int res;
+	char hostport[NI_MAXHOST];
 
 	add_blank(req);
 	if (sip_debug_test_pvt(p)) {
-		const struct sockaddr_in *dst = sip_real_dst(p);
-
-		ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
+		socklen_t dstlen = 0;
+		const struct sockaddr *dst = sip_real_dst(p,&dstlen);
+
+		ast_vinetsock_sa_get_hostport(dst, dstlen, hostport, sizeof(hostport));
+		ast_verbose("\n<--- %sTransmitting (%s) to %s --->\n%s\n<------------>\n",
 			reliable ? "Reliably " : "", sip_nat_mode(p),
-			ast_inet_ntoa(dst->sin_addr),
-			ntohs(dst->sin_port), req->data);
+			hostport, req->data);
 	}
 	if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) {
 		struct sip_request tmp;
@@ -2186,13 +2255,17 @@
 static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno)
 {
 	int res;
+	char hostport[NI_MAXHOST];
 
 	add_blank(req);
 	if (sip_debug_test_pvt(p)) {
-		if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE))
-			ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data);
-		else
-			ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data);
+		if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) {
+			ast_vinetsock_sa_get_hostport((struct sockaddr*)&p->recv, p->recv_len, hostport, sizeof(hostport));
+			ast_verbose("%sTransmitting (NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", hostport, req->data);
+		} else {
+			ast_vinetsock_sa_get_hostport((struct sockaddr*)&p->sa, p->sa_len, hostport, sizeof(hostport));
+			ast_verbose("%sTransmitting (no NAT) to %s:\n%s\n---\n", reliable ? "Reliably " : "", hostport, req->data);
+		}
 	}
 	if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) {
 		struct sip_request tmp;
@@ -2290,10 +2363,12 @@
 	that name and store that in the "regserver" field in the sippeers
 	table to facilitate multi-server setups.
 */
-static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expirey)
-{
-	char port[10];
-	char ipaddr[INET_ADDRSTRLEN];
+static void realtime_update_peer(const char *peername, struct sockaddr *sa,
+				 socklen_t sa_len, const char *username, 
+				 const char *fullcontact, int expirey)
+{
+	char port[NI_MAXSERV];
+	char ipaddr[NI_MAXHOST];
 	char regseconds[20];
 
 	char *sysname = ast_config_AST_SYSTEM_NAME;
@@ -2303,8 +2378,13 @@
 	const char *fc = fullcontact ? "fullcontact" : NULL;
 	
 	snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime);	/* Expiration time */
-	ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
-	snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
+	ast_vinetsock_sa_getaddr(sa, sa_len, ipaddr, sizeof(ipaddr));
+	snprintf(port, sizeof(port), "%d",
+		 ast_vinetsock_sa_getport(sa, sa_len));
+	
+	if(getnameinfo(sa, sa_len, ipaddr, sizeof(ipaddr), port, sizeof(port),
+		       NI_NUMERICHOST|NI_NUMERICSERV))
+		return;
 	
 	if (ast_strlen_zero(sysname))	/* No system name, disable this */
 		sysname = NULL;
@@ -2395,7 +2475,9 @@
 	int rtcachefriends = ast_test_flag(&p->flags[1], SIP_PAGE2_RTCACHEFRIENDS);
 	if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTUPDATE) &&
 	    (ast_test_flag(&p->flags[0], SIP_REALTIME) || rtcachefriends)) {
-		realtime_update_peer(p->name, &p->addr, p->username, rtcachefriends ? p->fullcontact : NULL, expiry);
+		realtime_update_peer(p->name, (struct sockaddr*)&p->addr,
+				     p->addr_len, p->username, 
+				     rtcachefriends ? p->fullcontact : NULL, expiry);
 	}
 }
 
@@ -2405,21 +2487,21 @@
  * \todo Consider adding check of port address when matching here to follow the same
  * 	algorithm as for static peers. Will we break anything by adding that?
 */
-static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_in *sin)
+      static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr *sa, socklen_t sa_len)
 {
 	struct sip_peer *peer;
 	struct ast_variable *var = NULL;
 	struct ast_variable *tmp;
-	char ipaddr[INET_ADDRSTRLEN];
+	char iabuf[NI_MAXHOST];
 
 	/* First check on peer name */
 	if (newpeername) 
 		var = ast_load_realtime("sippeers", "name", newpeername, NULL);
-	else if (sin) {	/* Then check on IP address for dynamic peers */
-		ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
-		var = ast_load_realtime("sippeers", "host", ipaddr, NULL);	/* First check for fixed IP hosts */
+	else if (sa) {	/* Then check on IP address for dynamic peers */
+		ast_vinetsock_sa_getaddr(sa, sa_len, iabuf, sizeof(iabuf));
+		var = ast_load_realtime("sippeers", "host", iabuf, NULL);	/* First check for fixed IP hosts */
 		if (!var)
-			var = ast_load_realtime("sippeers", "ipaddr", ipaddr, NULL);	/* Then check for registred hosts */
+			var = ast_load_realtime("sippeers", "ipaddr", iabuf, NULL);	/* Then check for registred hosts */
 	}
 
 	if (!var)
@@ -2437,7 +2519,7 @@
 	}
 	
 	if (!newpeername) {	/* Did not find peer in realtime */
-		ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr);
+		ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", iabuf);
 		ast_variables_destroy(var);
 		return NULL;
 	}
@@ -2468,29 +2550,32 @@
 }
 
 /*! \brief Support routine for find_peer */
-static int sip_addrcmp(char *name, struct sockaddr_in *sin)
+static int sip_addrcmp(char *name, struct sockaddr *sa, socklen_t *sa_len)
 {
 	/* We know name is the first field, so we can cast */
 	struct sip_peer *p = (struct sip_peer *) name;
-	return 	!(!inaddrcmp(&p->addr, sin) || 
+	return !(! ast_vinetsock_sacmp((struct sockaddr*)&p->addr, p->addr_len,
+                       (struct sockaddr*)sa, *sa_len, 0) || 
 					(ast_test_flag(&p->flags[0], SIP_INSECURE_PORT) &&
-					(p->addr.sin_addr.s_addr == sin->sin_addr.s_addr)));
+					 ! ast_vinetsock_sacmp((struct sockaddr*)&p->addr, p->addr_len,
+							       (struct sockaddr*)sa, *sa_len, 1)));
 }
 
 /*! \brief Locate peer by name or ip address 
  *	This is used on incoming SIP message to find matching peer on ip
 	or outgoing message to find matching peer on name */
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
+static struct sip_peer *find_peer(const char *peer, struct sockaddr *sa,
+					socklen_t sa_len, int realtime)
 {
 	struct sip_peer *p = NULL;
 
 	if (peer)
 		p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
 	else
-		p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp);
+		p = ASTOBJ_CONTAINER_FIND_FULL2(&peerl, sa, &sa_len, name, sip_addr_hashfunc, 1, sip_addrcmp);
 
 	if (!p && realtime)
-		p = realtime_peer(peer, sin);
+		p = realtime_peer(peer, sa, sa_len);
 
 	return p;
 }
@@ -2575,17 +2660,17 @@
 	if (p->rtp) {
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", mode);
-		ast_rtp_setnat(p->rtp, natflags);
+		ast_virtp_setnat(p->rtp, natflags);
 	}
 	if (p->vrtp) {
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", mode);
-		ast_rtp_setnat(p->vrtp, natflags);
+		ast_virtp_setnat(p->vrtp, natflags);
 	}
 	if (p->udptl) {
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", mode);
-		ast_udptl_setnat(p->udptl, natflags);
+		ast_viudptl_setnat(p->udptl, natflags);
 	}
 }
 
@@ -2594,29 +2679,28 @@
  */
 static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
 {
-	if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
-	    (!peer->maxms || ((peer->lastms >= 0)  && (peer->lastms <= peer->maxms)))) {
-		dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
-		dialog->recv = dialog->sa;
-	} else 
+	char iabuf[NI_MAXHOST];
+
+	if(!peer)
 		return -1;
-
+	
 	ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
 	dialog->capability = peer->capability;
 	if ((!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && dialog->vrtp) {
-		ast_rtp_destroy(dialog->vrtp);
+		ast_virtp_destroy(dialog->vrtp);
 		dialog->vrtp = NULL;
 	}
 	dialog->prefs = peer->prefs;
-	if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
+	if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT) &&
+		ast_vinetsock_sa_is_ipv4((struct sockaddr*)&dialog->sa)) {
 		dialog->t38.capability = global_t38_capability;
 		if (dialog->udptl) {
-			if (ast_udptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_FEC )
+			if (ast_viudptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_FEC )
 				dialog->t38.capability |= T38FAX_UDP_EC_FEC;
-			else if (ast_udptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_REDUNDANCY )
+			else if (ast_viudptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_REDUNDANCY )
 				dialog->t38.capability |= T38FAX_UDP_EC_REDUNDANCY;
-			else if (ast_udptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_NONE )
+			else if (ast_viudptl_get_error_correction_scheme(dialog->udptl) == UDPTL_ERROR_CORRECTION_NONE )
 				dialog->t38.capability |= T38FAX_UDP_EC_NONE;
 			dialog->t38.capability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF;
 			if (option_debug > 1)
@@ -2624,27 +2708,27 @@
 		}
 		dialog->t38.jointcapability = dialog->t38.capability;
 	} else if (dialog->udptl) {
-		ast_udptl_destroy(dialog->udptl);
+		ast_viudptl_destroy(dialog->udptl);
 		dialog->udptl = NULL;
 	}
 	do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE );
 
 	if (dialog->rtp) {
-		ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-		ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-		ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
-		ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
-		ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
+		ast_virtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+		ast_virtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+		ast_virtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
+		ast_virtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
+		ast_virtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
 		/* Set Frame packetization */
-		ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
+		ast_virtp_codec_setpref(dialog->rtp, &dialog->prefs);
 		dialog->autoframing = peer->autoframing;
 	}
 	if (dialog->vrtp) {
-		ast_rtp_setdtmf(dialog->vrtp, 0);
-		ast_rtp_setdtmfcompensate(dialog->vrtp, 0);

[... 3890 lines stripped ...]


More information about the asterisk-commits mailing list