Merge in strictrtp branch. This adds a strictrtp option to rtp.conf which drops packets that do not come from the remote party.
(closes issue #8952) Reported by: amorsen git-svn-id: http://svn.digium.com/svn/asterisk/trunk@100206 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
860bb66a0e
commit
341f67c198
2
CHANGES
2
CHANGES
|
@ -500,3 +500,5 @@ Miscellaneous
|
|||
specifying which socket to use to connect to the running Asterisk daemon
|
||||
(-s)
|
||||
* Added logging to 'make update' command. See update.log
|
||||
* Added strictrtp option to rtp.conf. If enabled this will drop RTP packets that
|
||||
do not come from the remote party.
|
||||
|
|
|
@ -20,3 +20,7 @@ rtpend=20000
|
|||
;dtmftimeout=3000
|
||||
; rtcpinterval = 5000 ; Milliseconds between rtcp reports
|
||||
;(min 500, max 60000, default 5000)
|
||||
;
|
||||
; Enable strict RTP protection. This will drop RTP packets that
|
||||
; do not come from the source of the RTP stream.
|
||||
; strictrtp=yes
|
||||
|
|
33
main/rtp.c
33
main/rtp.c
|
@ -78,6 +78,13 @@ static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this ho
|
|||
#ifdef SO_NO_CHECK
|
||||
static int nochecksums;
|
||||
#endif
|
||||
static int strictrtp;
|
||||
|
||||
enum strict_rtp_state {
|
||||
STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
|
||||
STRICT_RTP_LEARN, /*! Accept next packet as source */
|
||||
STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
|
||||
};
|
||||
|
||||
/* Uncomment this to enable more intense native bridging, but note: this is currently buggy */
|
||||
/* #define P2P_INTENSE */
|
||||
|
@ -165,6 +172,9 @@ struct ast_rtp {
|
|||
struct ast_rtcp *rtcp;
|
||||
struct ast_codec_pref pref;
|
||||
struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
|
||||
|
||||
enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
|
||||
struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
|
@ -1391,6 +1401,21 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
|
|||
res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
|
||||
0, (struct sockaddr *)&sin, &len);
|
||||
|
||||
/* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
|
||||
if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
|
||||
/* Copy over address that this packet was received on */
|
||||
memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
|
||||
/* Now move over to actually protecting the RTP port */
|
||||
rtp->strict_rtp_state = STRICT_RTP_CLOSED;
|
||||
ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
|
||||
} else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
|
||||
/* If the address we previously learned doesn't match the address this packet came in on simply drop it */
|
||||
if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
|
||||
ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
|
||||
return &ast_null_frame;
|
||||
}
|
||||
}
|
||||
|
||||
rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
|
||||
if (res < 0) {
|
||||
if (errno == EBADF)
|
||||
|
@ -2191,6 +2216,7 @@ void ast_rtp_new_init(struct ast_rtp *rtp)
|
|||
rtp->ssrc = ast_random();
|
||||
rtp->seqno = ast_random() & 0xffff;
|
||||
ast_set_flag(rtp, FLAG_HAS_DTMF);
|
||||
rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -2312,6 +2338,9 @@ void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
|
|||
rtp->rtcp->them.sin_addr = them->sin_addr;
|
||||
}
|
||||
rtp->rxseqno = 0;
|
||||
/* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
|
||||
if (strictrtp)
|
||||
rtp->strict_rtp_state = STRICT_RTP_LEARN;
|
||||
}
|
||||
|
||||
int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
|
||||
|
@ -4025,6 +4054,7 @@ static int __ast_rtp_reload(int reload)
|
|||
rtpstart = 5000;
|
||||
rtpend = 31000;
|
||||
dtmftimeout = DEFAULT_DTMF_TIMEOUT;
|
||||
strictrtp = STRICT_RTP_OPEN;
|
||||
if (cfg) {
|
||||
if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
|
||||
rtpstart = atoi(s);
|
||||
|
@ -4068,6 +4098,9 @@ static int __ast_rtp_reload(int reload)
|
|||
dtmftimeout = DEFAULT_DTMF_TIMEOUT;
|
||||
};
|
||||
}
|
||||
if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
|
||||
strictrtp = ast_true(s);
|
||||
}
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
if (rtpstart >= rtpend) {
|
||||
|
|
Reference in New Issue