Browse Source

- mcast fixes: avoid trying to send from multicast listening sockets
(the kernel will fix it, but in a non-ser deterministic way, e.g. the
sent packet might have as source ip and address on which we don't listen):
- get_send_socket() will ignore a forced mcast socket
- msg_send() will ignore a mcast source socket and it will
automatically choose another one

Andrei Pelinescu-Onciul 18 years ago
parent
commit
f479903ff7
2 changed files with 35 additions and 19 deletions
  1. 13 7
      forward.c
  2. 22 12
      forward.h

+ 13 - 7
forward.c

@@ -52,6 +52,8 @@
  *  2006-04-21  basic comp via param support (andrei)
  *  2006-07-31  forward_request can resolve destination on its own, uses the 
  *              dns cache and falls back on send error to other ips (andrei)
+ *  2007-10-08  get_send_socket() will ignore force_send_socket if the forced
+ *               socket is multicast (andrei)
  */
 
 
@@ -89,6 +91,7 @@
 #ifdef USE_DST_BLACKLIST
 #include "dst_blacklist.h"
 #endif
+#include "compiler_opt.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -158,24 +161,27 @@ struct socket_info* get_send_socket(struct sip_msg *msg,
 	struct socket_info* send_sock;
 	
 	/* check if send interface is not forced */
-	if (msg && msg->force_send_socket){
-		if (msg->force_send_socket->proto!=proto){
+	if (unlikely(msg && msg->force_send_socket)){
+		if (unlikely(msg->force_send_socket->proto!=proto)){
 			DBG("get_send_socket: force_send_socket of different proto"
 					" (%d)!\n", proto);
 			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
 											msg->force_send_socket->port_no,
 											proto);
-			if (msg->force_send_socket == 0){
+			if (unlikely(msg->force_send_socket == 0)){
 				LOG(L_WARN, "WARNING: get_send_socket: "
 						"protocol/port mismatch\n");
 				goto not_forced;
 			}
 		}
-		if (msg->force_send_socket->socket!=-1)
+		if (likely((msg->force_send_socket->socket!=-1) &&
+					!(msg->force_send_socket->flags & SI_IS_MCAST)))
 				return msg->force_send_socket;
-		else
-			LOG(L_WARN, "WARNING: get_send_socket: not listening"
-						 " on the requested socket, no fork mode?\n");
+		else{
+			if (!(msg->force_send_socket->flags & SI_IS_MCAST))
+				LOG(L_WARN, "WARNING: get_send_socket: not listening"
+							 " on the requested socket, no fork mode?\n");
+		}
 	};
 not_forced:
 	if (mhomed && proto==PROTO_UDP){

+ 22 - 12
forward.h

@@ -35,6 +35,8 @@
  *  2003-04-15  added tcp_disable support (andrei)
  *  2006-04-12  reduced msg_send() parameter list: it uses now a struct 
  *               dest_info param. (andrei)
+ *  2007-10-08  msg_send() will ignore a mcast send_sock and choose another
+ *               one by itself (andrei)
  */
 
 
@@ -54,6 +56,8 @@
 #include "tcp_server.h"
 #endif
 
+#include "compiler_opt.h"
+
 
 
 struct socket_info* get_send_socket(struct sip_msg* msg,
@@ -79,7 +83,8 @@ int forward_reply( struct sip_msg* msg);
 
 /* params:
  * dst = struct dest_info containing:
- *    send_sock = 0 if not known (e.g. for udp in some cases), non-0 otherwise
+ *    send_sock = 0 if not known (e.g. for udp in some cases), non-0 otherwise;
+ *                if 0 or mcast a new send_sock will be automatically choosen
  *    proto = TCP|UDP
  *    to = destination (sockaddr_union)
  *    id = only used on tcp, it will force sending on connection "id" if id!=0 
@@ -90,15 +95,20 @@ int forward_reply( struct sip_msg* msg);
  * returns: 0 if ok, -1 on error*/
 static inline int msg_send(struct dest_info* dst, char* buf, int len)
 {
+	struct dest_info new_dst;
 	
-	if (dst->proto==PROTO_UDP){
-		if (dst->send_sock==0) 
-			dst->send_sock=get_send_socket(0, &dst->to, dst->proto);
-		if (dst->send_sock==0){
-			LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
-			goto error;
+	if (likely(dst->proto==PROTO_UDP)){
+		if (unlikely((dst->send_sock==0) || 
+					(dst->send_sock->flags & SI_IS_MCAST))){
+			new_dst=*dst;
+			new_dst.send_sock=get_send_socket(0, &dst->to, dst->proto);
+			if (unlikely(new_dst.send_sock==0)){
+				LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
+				goto error;
+			}
+			dst=&new_dst;
 		}
-		if (udp_send(dst, buf, len)==-1){
+		if (unlikely(udp_send(dst, buf, len)==-1)){
 			STATS_TX_DROPS;
 			LOG(L_ERR, "msg_send: ERROR: udp_send failed\n");
 			goto error;
@@ -106,13 +116,13 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
 	}
 #ifdef USE_TCP
 	else if (dst->proto==PROTO_TCP){
-		if (tcp_disable){
+		if (unlikely(tcp_disable)){
 			STATS_TX_DROPS;
 			LOG(L_WARN, "msg_send: WARNING: attempt to send on tcp and tcp"
 					" support is disabled\n");
 			goto error;
 		}else{
-			if (tcp_send(dst, 0, buf, len)<0){
+			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
 				STATS_TX_DROPS;
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
 				goto error;
@@ -121,13 +131,13 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
 	}
 #ifdef USE_TLS
 	else if (dst->proto==PROTO_TLS){
-		if (tls_disable){
+		if (unlikely(tls_disable)){
 			STATS_TX_DROPS;
 			LOG(L_WARN, "msg_send: WARNING: attempt to send on tls and tls"
 					" support is disabled\n");
 			goto error;
 		}else{
-			if (tcp_send(dst, 0, buf, len)<0){
+			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
 				STATS_TX_DROPS;
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
 				goto error;