[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